在寻找安全漏洞时,对未知资产和隐蔽站点的搜集通常最终会让人舍本逐末。

如果您对一个目标进行安全测试,就像第一次对它执行安全评估一样细致,彻底检查所有内容,那么我相信您一定会找到新的东西:尤其是如果要测试的代码已经持续开发了一段时间。

这是一个关于高危漏洞的故事,该漏洞会影响PayPal访问量最大的页面之一:登录表单。(最后被奖励了$15300美金)

 

初步发现

在浏览PayPal的主要身份验证流程时,我注意到一个javascript文件,其中似乎包含了一个CSRF令牌和会话ID的内容:

这立即引起了我的注意,因为在一个有效的javascript文件中提供任何类型的会话数据的话,通常都给攻击者可趁之机。

在所谓的跨站点脚本包含(XSSI)攻击中,恶意网页可以使用HTML <script>标签导入跨域脚本,从而使其能够访问文件中包含的任何数据。

果然,我很快就测试确认了该XSSI漏洞,尽管它使用了JavaScript混淆器来随机化每个请求的变量名,但有趣的是,令牌仍被放置在十分容易查找的位置,一下子就被找到了。

然而,水可载舟亦可覆舟,要看该信息如何利用了。我立即着手找出_csrfh和_sessionID的确切含义,以及它们是否可以真正用于实际攻击中。

 

进一步挖掘

我尝试将PayPal平台上已授权请求中的常规CSRF令牌替换为_csrf的值,经过无数次的尝试后,我得出的结论是,使用此特定令牌无法进行经典的跨站点请求伪造攻击。同样,_sessionID也不行。

接下来,我返回该漏洞脚本,查看该令牌的的实际用途,最后对PayPal用来防止暴力攻击(安全挑战)的一个主要保护机制进行了深入研究。虽然此机制已被广泛使用,但我将重点介绍此登录表单。

这个想法很简单:几次尝试登录失败后,您需要先解决reCAPTCHA挑战,然后才能重试。但是,这个挑战就很有搞头了。

它的机制是这样的:在检测到可能的暴力破解尝试后,下一次身份验证尝试的响应将是一个页面,其中仅包含Google验证码。如果用户通过了验证码测试,会向/auth/validatecaptcha发起一个HTTP POST请求。

在请求主体中又看到了_csrf_sessionID熟悉的身影,主体中还有其他两个值,稍后会介绍。

对验证码请求的响应旨在将用户重新引入身份验证流程。为此,它包含一个自我提交的表单,其中包含用户最新登录请求提供的所有数据,包括他们的电子邮件和纯文本密码。

我意识到,通过正确的时序和一些用户交互,只要知道此请求中使用的所有令牌,就足以获取受害者的PayPal凭据。在实际攻击场景中,唯一需要的用户交互就是访问一下攻击者控制的网页。

因此,我回过头来尝试找出缺少的参数。这比预期的容易:

  1. jse的值完全未经验证。
  2. recaptcha是Google在解决reCAPTCHA挑战时提供的令牌。它并未绑定到特定的会话中,因此任何有效的令牌都可以被接受(例如,来自自动求解服务的令牌)。

 

Exploitation

综上所述,我创建了一个整个过程的POC(除了集成验证码解决方案服务外)。

首先,POC将利用最初的XSSI漏洞来获取一组在受害者会话中有效的令牌。然后,受害人的浏览器发出带有随机凭据的一些身份验证请求,模拟尝试暴力破解,这个过程将触发安全挑战流程。

一旦受害者使用相同的浏览器登录PayPal,缓存的随机凭证将被用户自己的电子邮件和密码替换。最后一步是获取一个新的reCAPTCHA令牌,此后,纯文本凭据会通过服务器端的请求被发送到/auth/validatecaptcha页面,并显示在页面上。

被马赛克掉的就是用户的电子邮件和明文密码

被马赛克掉的就是用户的电子邮件和明文密码

后来我发现,在某些未经身份验证的结帐页面上也使用了相同的漏洞验证,从而允许使用相同的技术泄漏纯文本信用卡数据。

 

后记

POC以及相关信息已于2019年11月18日提交到PayPal的漏洞赏金计划,18天后HackerOne也通过了验证。

在paypal团队迅速确认并提出一些其他问题之后,我于12月10日获得了15300美元的奖金。奖励金额对应于bug的8.0级(高)CVSS分数,这与我在提交报告时最初建议的分数相同。

 

修复和预防建议

/auth/validatecaptcha页面添加一个额外的CSRF令牌,该令牌无法被跨站点脚本包含泄露。

尽管以上可以正确修复漏洞,但作者认为,按照最古老、最重要的信息安全建议中的一项,在设计系统时就可以避免此类漏洞,那就是:永远不要以纯文本形式存储密码。