【技术分享】构建XSS Payload是一门艺术,用最简单的方法绕过XSS的缓解方案
作者:admin | 时间:2016-12-1 13:57:43 | 分类:黑客技术 隐藏侧边栏展开侧边栏
写在前面的话
如果你想要绕过测试人员/攻击者与目标应用之间的安全保护机制,那么最简单、最可靠的方法就是利用目标应用的敏感字符过滤功能。没错,这听起来似乎有些“以彼之道,还施彼身”的味道。
安全客小百科:XSS(跨站脚本攻击)
XSS 攻击是代码注入的一种,它允许攻击者将代码写到 Web 页面上,Web 应用会错误解析页面内容后执行网页中的脚本内容,导致其他用户浏览此网页时触发页面上的脚本内容,进而使用户浏览器做出脚本内容相应的行为,完成对用户的攻击。由于 Web 页面在用户提交文本信息时没有做合法性检测或依赖客户端的合法性检测,导致脚本文本顺利上传至服务器,而在 HTML 解析时,Web 应用没有对脚本文本做正确编码,致使用户提交的攻击脚本出现在客户端浏览器中,使用户加载并执行攻击者编写在 Web 页面中的脚本程序,这些脚本语言通常有:JavaScript、Java、VBScript、ActiveX、Flash 或者是普通的 HTML。攻击成功后,攻击者将可获取到用户的私密信息。
攻击思路
可能是出于对安全因素或其他方面的考虑,很多开发人员都会在自己编写的代码中添加某种字符过滤功能。但是他们往往都没有意识到,攻击者很有可能利用这种功能来欺骗目标设备并实施攻击。想必各位同学都知道,Web应用防火墙(WAF)以及浏览器的防XSS过滤器是目前最常用的两种威胁缓解方案。那么在这篇文章中,我们将会告诉大家如何利用这项技术影响WAF,并绕过浏览器的防XSS过滤器。
开发人员可以通过使用编程语言自带的函数和自定义函数来过滤/替换掉他们认为可能会具有危险性(或不需要的)的字符或字符串。那么接下来让我们首先看一看,当一个应用程序过滤掉用户输入数据中的空格字符时,程序会发生些什么。
技术分析
为了让大家更好地理解,我们专门制作了一个PHP网页[点我访问]。点开这个网页之后,大家可以看到该站点的URL地址中有两个参数,即“p”和“q”。
第一个参数“p”只是一个简单的“echo $_GET[“p”];”,由于我并没有将这个页面添加进我Web应用防火墙的白名单列表中,因此我们并不能使用普通场景下的漏洞利用方法去利用这个漏洞,具体情况如下图所示。实际上,Sucuri在这里所采用的安全解决方案(CloudProxy)就非常棒了,它并不是通过URL中的“(1)”来检测XSS攻击的,它检测的其实是URL中的“<svg onload=”。
第二个参数“q”是用来验证我们的绕过方案是否成功的。该部分的PHP代码如下所示:
1
|
echo str_replace(“ ”, “”, $_GET[“q”]);
|
这行代码可以剔除掉用户输入数据中的空格字符。这看起来虽然很简单,但是却足以欺骗CloudProxy、XSS审计程序、以及谷歌Chrome浏览器的XSS缓解方案。运行结果如下图所示:
从上图中可以看到,我们在相应参数中添加了符号“+”,通常情况下Web应用程序会将这个字符解析为空格符。我们故意将字符“+”添加进了攻击向量/payload中,而就是这一个简单的字符,就能够让目标应用的安全防御机制失效。Web应用防火墙无法检测到这种类型的XSS攻击,因为“<”之后紧跟的并不是字母。而且,由于这种形式的payload与XSS攻击向量样本库中的payload有很大不同,因此XSS审计程序同样也不会将其视为XSS攻击向量。
由此可见,攻击者所发送的内容和Web应用真正响应的内容并不一定是相同的。如果攻击者输入的数据与数据库中的恶意payload匹配度很低的话,那么攻击者所输入的内容就不会被当作恶意内容处理。
另外一种情况
除了上面这种方法之外,我们还可以利用字符/字符串替换功能来对付这些安全保护措施。为此,我们另外制作了一个网页[点我访问]。这一次,我们将要使用四个URL参数,即“p”、“q”、“r”和“s”。我们将该网页添加进了Web应用防火墙的白名单之中,因此这些参数还没有强大到能够绕过WAF:每一个请求中的“<script”字符串都会触发WAF的屏蔽功能。但是我们可以用这个方法来对付XSS审计程序。相关代码如下所示:
1
2
3
4
|
echo $_GET[“p”];
echo str_ireplace(“<script”, “”, $_GET[“q”]);
echo str_ireplace(“<script”,“InvalidTag”, $_GET[“r”]);
echo str_ireplace(“<script”,“<InvalidTag”, $_GET[“s”]);
|
正如下图所显示的那样,使用参数“p”的话,审计程序可以轻易地检测到它。
使用参数“q”的话,我们可以看到“<script”将会被过滤掉。
但是,如果换一种方法的话,我们还是可以迷惑这个审计程序的。我们可以将“<script”添加在事件处理器“onload”的“o”和“n”之间,这样就可以让网页执行我们的js代码了。
但是在参数“r”中,想要解决“<script”标签被替换的问题可就没那么容易了。与大多数情况一样,开发人员可以将参数中的恶意数据替换成无害的字符串,而此时我们之前所构造的payload也就失效了。如下图所示:
那么接下来,我们打算尝试一下,看看能不能把字符串“InvalidTag”当作一个JavaScript字符串来使用。但如果使用方法错误的话,浏览器将会抛出一个错误。错误信息如下图红色部分所示:
这是因为我们传递给事件处理器的内容只有字符串数据,而且还是包含在双引号中间的。在HTML中,这是我们给属性赋值时所用的标准方法,所以JavaScript在解析到第二个双引号的时候就会停止解析,因为代码中并没有定义“InvalidTag”。所以,我们要想办法修复这个语句中存在的问题。
事实证明,这并没有什么用。这样做的话未免有些太过于明显了,XSS审计程序可以轻而易举地检测到这个payload。但是,如果我们使用ES6的语法特性来“封装”这个JavaScript字符串的话,是否会有效果呢?
非常好,果然成功了。需要告诉大家的是,我们还有另一种方法同样可以实现类似的效果,这个方法非常有趣,但是该方法的适用范围就没有之前的方法那么广泛了(因为这个方法无法处理特殊字符)。
如上图所示。在这个方法中我们把可能会被替换的字符串当作标签(label)来使用,这种简洁的方法同样可以让浏览器弹出对话框。
不幸的是,上述所有这些所谓的“替换技巧”都无法用在参数“s”的身上。此时,审计程序似乎是根据字符“<”来过滤输入数据的。具体情况如下图所示:
总结
但是,广大开发人员请注意:即便是你在所有的HTML标签中都部署了相应的策略(例如正则表达式),但这项技术仍然不能被视作为一种防XSS的解决方案。因为这样将会为攻击者开启另外一扇大门,他们将可以通过替换后的“<InvalidTag”字符串以及任何一个事件处理器来构建出新的攻击向量。
本文由 安全客 翻译,作者:WisFree
原文链接:http://brutelogic.com.br/blog/the-easiest-way-to-bypass-xss-mitigations/