4.7 Badoo全账号接管
难度:中
URL:https://www.badoo.com/
报告位置:https://hackerone.com/reports/127703/
报告日期:2016年4月1日
支付奖金:852美元
尽管开发者通常使用CSRF令牌来抵御CSRF漏洞攻击,但是在有些情况下,攻击者可以窃取令牌,就像你将在本漏洞案例中看到的一样。当你浏览社交网站https://www.badoo.com/时,你会发现该网站采用了CSRF令牌技术。特别地,该网站针对每个用户都使用了一个不同的URL参数rt。当Badoo的漏洞悬赏挂在HackerOne上时,我找不到该网站的漏洞利用的方法。但是Mahmoud Jamal做到了。
Jamal深知rt这个参数及其含义,他也注意到了几乎所有的JSON响应中都包含该参数。不幸的是,由于响应信息是采用application/json内容类型进行编码的,故CORS禁止了黑客读取Badoo的任何响应数据,因此这对于破解似乎没有什么帮助。但是,Jamal还是继续尝试进行漏洞的挖掘。
最后,Jamal发现了JavaScript文件https://eu1.badoo.com/worker-scope/chrome-service-worker.js包含一个变量url_stats,并被设置了如下的值:
变量url_stats中存放了一个URL,该URL包含了当用户浏览器访问该JavaScript文件时传送的用户唯一的rt值参数❶。为了得到用户的rt值,攻击者仅仅需要引导目标对象去访问一个将会访问该JavaScript文件的恶意网页。CORS不会阻止这些发生,因为浏览器是允许从外部资源读取或嵌入远程JavaScript文件的。然后攻击者使用该rt值将该用户的Badoo账号与任何可能的社交媒体账号关联。结果,攻击者就可以调用HTTP POST请求去修改目标对象的账号。下面是Jamal用于完成这次漏洞利用的HTML页面:
当目标对象加载该网页时,网页将会加载<script>标签中src属性所指向的Badoo JavaScript文件❶。在加载完这个JavaScript脚本后,网页会调用JavaScript函数windows.onload,它定义了一个匿名的JavaScript函数❸。浏览器在网页加载时会调用onload事件句柄,因为Jamal定义的函数是在windows.onload句柄中,所以当页面加载时,他的函数总是会被调用。
接下来,Jamal定义了一个变量csrf_code❹,并且把他在❷处定义的getCSRFcode函数的返回值赋值给这个变量。getCSRFcode函数接收一个字符串,并且通过字符'='作为分隔符把该字符串分解为一个字符串数组。当该函数在❹处解析来自Badoo的JavaScript文件中的url_stats变量时,将该字符串分解为如下数组值:
然后该函数返回数组的第三个元素,即rt值,并且赋值给csrf_code。
一旦拿到了CSRF令牌,Jamal就可以创建一个csrf_url变量,用来存储指向Badoo的/google/verify.phtml网页的URL。这个网页将Jamal自己的Google账号与目标对象的Badoo账号关联起来❺。该网页需要一些参数,这些参数都是硬编码为URL字符串的。我不想在这里详细描述这些参数,因为他们是Badoo特有的。然而,注意最后一个参数rt,它并不是硬编码的。实际上,csrf_code是级联到URL字符串末尾的,因此它是作为rt参数值进行传递的。然后Jamal通过调用window.location并赋值csrf_url来发起一个HTTP请求❻,这将重定向用户的浏览器到❺处的URL。这会导致向Badoo发起一个GET请求,Badoo会验证rt参数并处理该请求,将目标对象的Badoo账号与Jamal的Google账号关联起来,这样就完成了账号接管的全部过程。
要点
无风不起浪。Jamal注意到参数rt具有不同的地区返回值,特别是在JSON响应消息中也是这样。正因为如此,他直觉猜测rt可能在某些地方会显露出来,从而可以被攻击者访问和利用,就像我们例子中的JavaScript文件一样。如果你感觉某个网站可能存在漏洞,记得一定要坚持进行挖掘并告知该网站。在本例中,我认为如果CSRF令牌仅仅有5个数字的长度并包含在URL中,那么它将是奇怪的。一般来说,令牌要比这个长很多,这样使得它们更难被猜出来,而且一般都是包含在HTTP POST请求体而不是URL中。当你访问一个网站或应用时,可以使用代理来查看都调用了哪些资源。Burp允许你检索所有代理历史数据以查找特定的词或数值,这将有助于发现本例中JavaScript文件中包含的参数rt的取值。你也可能会发现敏感数据的信息泄露,例如CSRF令牌。