使用CSRF盗取SELF-XSS的Cookie
一般来说,个人信息修改页面只有用户自己才能够看得到。假设网站A右上角的你好,用户
这个地方存在XSS,并且在修改昵称为XSS payload后能够触发这个XSS。但是这个网站没有能够让其他用户看到你昵称的类似于留言板讨论区的地方,而管理员也一百年不会去看一下你的昵称,这个XSS就成为了一个鸡肋的SELF-XSS。因为普通用户怎么可能把昵称改成XSS payload来把Cookie送给你,你又没办法把自己的昵称改成恶意代码然后让别人看到,所以只能用来X自己。但如果同时这个网站有一个CSRF漏洞的话那就不一样了。我们可以通过以下操作来打任意用户的Cookie:
1.在恶意网站B中写入CSRF payload,使用这个CSRF来修改用户在A网站的昵称为XSS payload
2.诱惑用户访问恶意网站B,CSRF payload触发,用户在A网站的昵称被修改为XSS payload
3.用户重新访问A网站时,由于右上角显示了昵称,所以会触发对应的XSS payload,乖乖的把Cookie给你送过来
这样,一个SELF-XSS便被利用了。恶意网站B可以是我们自己建立的,也可以是某些存在XSS漏洞的大型网站,通常大型网站更容易受信任。这些大型网站可能本身设置了HTTP-ONLY
导致攻击者无法拿到Cookie,又不好做其他操作。但是用来做攻击其他网站的跳板却是无法防范的。
使用XSS窃取防御CSRF的Token
生成一个随机Token是防御CSRF的经典方法之一。在页面涉及到表单时,会在服务器端生成一个Token,在页面加载时创建一个值为Token的input
,插入到表单中,并设置type=”hidden“
隐藏。当提交表单时,会将这个Token值一起提交。服务器端验证这个Token是否正确,如果不正确就会扔掉此次请求。本来只要获取目标页面Token的值,这种防御方法就会无效。但CSRF攻击是在其他网站发起的,由于同源策略,发起攻击的网站B不能读取被攻击的网站A的内容,只能够对其发送请求。因此攻击者是无法获取Token值的,CSRF攻击就此失效。但当目标网站有一个XSS漏洞时,我们便可以先发送一次请求,通过JS的跨域方法绕过同源策略,从而读取网站A页面中的Token值。再发送第二次请求,带上Token值,完成CSRF攻击。博主这里使用window.name
来跨域窃取Token值。假如发起攻击的网站为B,受害站点为A。
1.在A网站的URL中构造XSS payload,实现以下功能:
a.获取本页面的Token值
b.将Token值赋值给
window.name
2.在B网站中插入实现以下功能的JS:
a.创建一个
iframe
,并将iframe.src
设为上面构造好的带有XSS payload的A网站的URLb.写一个
function
,首先将iframe.contentWindow.location
设为任意一个与B网站同源的页面,然后使window.name = iframe.contentWindow.name
修改
iframe.contentWindow.location
的原因是:当iframe
中的页面为A网站的页面时,与B网站为不同源的,不能将iframe
的window.name
赋值给当前B网站窗口的window.name
。但是我们把iframe
中的页面换为与B网站同源的页面时,是可以进行window.name
的赋值的。由于window.name
的特性,其值本身与网站无关,是窗口的一个值。因此修改页面后window.name
并未改变,我们就可以顺利取出了。c.将这个
iframe
销毁
3.在B网站中插入真正的CSRF payload,带上已成功获取的window.name
中的Token值,进行攻击。
结语
有些看似无法利用的场景,稍作结合就可能出现意想不到的结果。在第二个姿势中,我们还可以不窃取Token值,直接窃取document.cookie
。但CSRF相当于批量操作,当进行高价值的操作时,可能会比收集很多cookie一个一个去操作更值得。况且这样的操作可以无视HTTP-ONLY
的限制。因此这个场景还是有很大价值的。