绕过XSS filters的几种方法

YasHigginbo 8年前
   <p><strong><img src="https://simg.open-open.com/show/2f93cd623465125800da37ba0891e6b1.jpg"> </strong></p>    <p>XSS跨站脚本攻击是指,黑客向一个页面中注入Javascript脚本,其它的用户访问该页面时会执行这个脚本。为了防止这一攻击,一些软件尝试从输入中移除Javascript代码。这很难正确实现。在这篇文章中我会展示一些试图移除输入里的Javascript脚本的代码,并演示几中绕过它的方法。</p>    <p>以网上商城软件 <a href="/misc/goto?guid=4959673441664616735" rel="nofollow,noindex">Magento</a> 中的类 <a href="/misc/goto?guid=4959673441743246391" rel="nofollow,noindex">Mage_Core_Model_Input_Filter_MaliciousCode</a> 为例。这个类的作用是过滤“恶意代码”,包括以任何形式插入的Javascript。</p>    <p>代码如下所示:</p>    <pre>  <code class="language-javascript">protected $_expressions = array(      '/(\/\*.*\*\/)/Us',      '/(\t)/',      '/(javascript\s*:)/Usi',      '/(@import)/Usi',      '/style=[^<]*((expression\s*?\([^<]*?\))|(behavior\s*:))[^<]*(?=\>)/Uis',      '/(ondblclick|onclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onload|onunload|onerror)=[^<]*(?=\>)/Uis',      '/<\/?(script|meta|link|frame|iframe).*>/Uis',      '/src=[^<]*base64[^<]*(?=\>)/Uis',  );  function filter($value) {      return preg_replace($this->_expressions, '', $value);  }</code></pre>    <p>$_expressions变量包含一个正则表达式列表,preg_replace函数会移除文本中匹配该正则表达式的内容。所以如果你输入<script>foo</script>,两个标签都会被移除,只保留foo。</p>    <p>让我们看一些绕过这个filter的方法。我们的目标是绕过它传递一些执行Javascript的HTML代码。这个filter有若干表达式,它们的含义是阻止下面的内容:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/76c19e0075c9d2657f9c4f7387482c06.jpg"></p>    <h2>Javascript URL</h2>    <p>可以在URL中使用javascript:…让该链接执行javascript:</p>    <pre>  <code class="language-javascript"><a href="javascript:alert('test')">link</a></code></pre>    <p>filter移除了代码中的javascript:,所以我们不能直接用上面的代码。我们可以试着改变javascript:部分,让浏览器任然执行它并且正则表达式匹配不上。我们试试URL-encode:</p>    <pre>  <code class="language-javascript"><a href="javascript:alert('xss')">link</a></code></pre>    <p>正则表达式匹配不上了,但浏览器在用它之前对该链接做了URL-decode操作,所以依然可以执行它。</p>    <p>除了Javascript之外还有VBScript。它在IE11中被弃用并且禁用了,但是在Internet Explorer的老版本中依然可以使用,如果你把IE 11设置为IE 10模拟模式的话也是可用的。我们可以像Javascript链接那样执行相同的代码。</p>    <pre>  <code class="language-javascript"><a href='vbscript:MsgBox("XSS")'>link</a></code></pre>    <h2>CSS导入</h2>    <p>Internet Explorer在CSS中支持Javascript表达式,称为动态属性 <a href="/misc/goto?guid=4959673441832656551" rel="nofollow,noindex">https://msdn.microsoft.com/en-us/library/ms537634</a> (v=vs.85).aspx。允许攻击者加载外部的CSS样式表是非常危险的,因为攻击者可以在原始页面的上下文中执行Javascript。</p>    <p>在恶意的css中:</p>    <pre>  <code class="language-javascript">body {      color: expression(alert('XSS'));  }</code></pre>    <p>我们可以在CSS中使用反斜杠转义字符来规避@import过滤。</p>    <p>Internet Explorer允许反斜杠,现在它绕过了我们的filter。</p>    <h2>Inline样式</h2>    <p>我们也可以使用Inernet Explorer支持的内嵌样式中的动态属性:</p>    <pre>  <code class="language-javascript"><div style="color: expression(alert('XSS'))"></code></pre>    <p>filter会检查这样的字符串,style后面跟的不是<并且后面包含expression:</p>    <pre>  <code class="language-javascript">/style=[^<]*((expression\s*?\([^<]*?\))|(behavior\s*:))[^<]*(?=\>)/Uis</code></pre>    <p>因此,我们在那里增加一个<.</p>    <pre>  <code class="language-javascript"><div style="color: '<'; color: expression(alert('XSS'))"></code></pre>    <p>这可以绕过filter,因为[^<]匹配不上<,并且这还是一个有效的CSS,虽然“<”不是一个有效的color,但是其余部分仍然被使用了。</p>    <h2>Javascript事件</h2>    <p>可以在一个元素上定义事件句柄,如下:</p>    <pre>  <code class="language-javascript"><div onclick="alert('xss')"></code></pre>    <p>这样,这个Javascript会在有人点击它的时候执行,但是也有一些事件是在页面加载后或者用户移动鼠标的时候触发。filter移除了许多这样的事件,但是它并没有包含所有的事件句柄。比如,漏了onmouseenter:</p>    <pre>  <code class="language-javascript"><div onmouseenter="alert('xss')"></code></pre>    <p>我们的代码会在用户把鼠标移动到div上面时执行。</p>    <p>另一个绕过的方法是在属性和”=”之间加上一个空格。Magento在最新版本的恶意代码filter中已经修复了它。</p>    <pre>  <code class="language-javascript"><div onclick ="alert('xss')"></code></pre>    <h2>Script标签</h2>    <p>Script标签可以用来定义行内脚本,或者从其它位置加载脚本文件:</p>    <p>我们的filter移除了<script>标签。然而,它只是做一次,因此我们可以让我们想要的内容在移除标签之后出现:</p>    <pre>  <code class="language-javascript"><scr<script>ipt>alert("XSS")</scr<script>ipt></code></pre>    <p>filter移除了两个发现的<script>,最后我们还是执行了想要的代码。实际上,这个嵌套标签的办法可以用来规避任意的filter表达式。</p>    <h2>结论</h2>    <p>尽管filter试图阻止了几种脚本注入的办法,我们都找到了规避的方法。创建一个filter来规避XSS攻击是不容易的。你必须考虑各种编码类型以及不同的浏览器行为。这让开发者做起来很难,却方便了攻击者。</p>    <h2>安全影响</h2>    <p>我展示了几种绕过filter的办法。这是一个安全威胁,除非没有对不可信输入使用这个filter。在 <a href="/misc/goto?guid=4959673441924072224" rel="nofollow,noindex">Magento 2.0.1 release notes</a> 中有这样一段话:</p>    <p>用户在输入HTML代码的时候可以轻易绕过MaliciousCode filter函数。但是,Magento几乎不用这个filter,并且当前的用法都不允许未授权用户输入。</p>    <p>1月23日,我进一步联系了Magento,他们不认为这是一个安全问题,所以我发布了这篇文章。</p>    <p>*本文译者:felix,翻译自: <a href="/misc/goto?guid=4959673441999785961" rel="nofollow,noindex">http://www.sjoerdlangkemper.nl/2016/01/29/circumventing-xss-filters/</a> </p>    <p> </p>    <p>来自: <a href="/misc/goto?guid=4959673442086243912" rel="nofollow">http://www.freebuf.com/articles/web/104656.html</a></p>    <p> </p>