Google Bughunter University上的一篇文章 Best reports series - Account Recovery XSS
是一个Google账号找回的漏洞,只要点击链接,攻击者就可以通过重置密码来窃取你已登录的Google账号。
漏洞报告者 是 Ramzes
攻击过程结合了www.google.com 上的 XSS、跨域CSRF token获取、信息泄露,外加细心的分析,很精彩的一个漏洞,花了点时间看了看,分析下过程,英文好的同学可以看原文,有错或者不准确欢迎指出~
PS. Google一共给了$12500,XSS $5000, Bug Chain $7500,感觉有点少了
利用过程有以下几步
Step 1: XSS on www.google.com
问题出在获取帮助文档的API上,google很多web application都会调用它显示帮助文档,是弹框的形式,就是这货
图片上红色框部分是一个iframe,原文中称为content frame,属于 www.google.com domain,用来显示帮助文档,这里文档内容是从另一个iframe获取的,粗略过程如下:
content frame 会用它 src (即API)中的一个url参数的值,作为 src 来创建一个新的iframe,称为communication frame,communication frame 和 content frame 的 domain是不同的,二者之间通过 postMessage() 方法来实现iframe跨域通信。
communication frame 会先把帮助文档的HTML代码生成(大概意思是这样,具体没仔细看哈),然后通过postMessage() 把代码发给 content frame,content frame收到后,会把发送过来的html代码作为可信的,直接插入到dom中。
因为用来创建communication frame的url参数值(src属性值)是可控的,因此可以控制communication frame 向 content frame发送的html 代码(最后会被插入到dom中),造成 www.google.com domain上的XSS
看下Google找回密码的页面:
攻击者首先要利用xss填入找回密码的邮箱
Step 2: accounts.google.com
第一步点击继续后,会经过几个 www.google.com domain下的跳转,最后跳转到accounts.google.com domain下,然后让你填写你最近使用过的密码。
原文里没有给出跳转的url和步骤,我自己测了下,一共会经过3次跳转,4次请求,如下图
最后的一次的跳转是到 https://accounts.google.com,后面会带上参数,类似这样
https://accounts.google.com/VerifyOldPassword?cpr=AHwGkRmVsrN65LtLtsa0U66ihdx-ppxMMjCeqcuGRC.......Qb6U3ow&hl=zh-CN
服务器端会根据 cpr 参数在响应中的表单内生成一个CSRF token,没有这个token请求就无法通过验证。
因为step 1 中的xss是在www domain下的,在跳转后的accounts domain下不起作用。
并且因为同源策略 也不能向 accounts.google.com domain发起请求,就没发获取到csrf token。
Ramzes想办法的是借助 外部服务器 来完成,但是这里的条件是需要能获取cookie,但是看了看,都设置了HTTP-only。
天无绝人之路,少年发现最后一个向 www.google.com domain发起的请求(图中recovery的那个)不需要cookie,只要有url参数,也能正常跳转,那么就666了,可以搞起了
exploit的步骤如下:
1. 302跳转的domain是 www.google.com 就利用xss来执行,即verifyuser和bkdispatch的两个请求
2. 获取bkdispatch请求的302跳转 url 的参数(即最后一个向 www.google.com domain发起的请求)
3. 把参数传到 外部服务器 上。
4. 外部服务器执行最后一个 向www.google.com 发送的请求,即 recovery 的那个请求,然后follow跳转获取响应中的csrf token
5. 返回csrf token到 client 端
6. 带上 csrf token 提交表单
这里 3-5步 是利用 jsonp吗?还是有其他方法,哪位师傅懂得可以补充下
接着,因为我们不知道用户的历史密码,所以这里模拟用户点击第二个button(“I don’t know [any previous password]”),
Step 3: Choosing the questionnaire
点击Step 2中的 “I don’t know,会跳转到如下页面
有两种方式,一种是通过密保邮箱,一种是验证身份,因为这里无法控制密保邮箱,所以这里点击 Verify your identity
Step 4: Answering the questionnaire using an information leak
点击step 3中的 Verify your identity,会跳转到如下页面
让你填一些信息,比如账户创建时间和最后一次登录时间,到这里一般人蒙B了,这些信息去哪里拿!
Ramzes 同学居然发现了一个页面包含这些信息,真好奇他怎么找的!而页面所在的 domain 和 发现xss的 domain 是相同的,那么就可以获取到信息。
就是下面这个在不同google account间迁移数据的页面,
Step 5: Win
填好需要的信息,点击 continue,验证通过,填写邮箱,重置密码链接就发送到你的邮箱了,搞定~
Fix
对 content frame src 的url参数的值 (即communication frame 的 src) 进行白名单过滤。原本是用户可控的
增加验证,防止在外部服务器上来完成 CSRF token 的生成过程 。修复那步不需要cookie的bug?
移除泄露信息页面中的日期信息