0x01.背景

遇到一个DomXSS,本身传入参数在Javascript环境下,也就是说传入参数能直接执行,比如index.php?p=';alert`1`;\\。这种一般Chrome XSS Filter 都不会去拦,即便是拦截了也很容易bypass。

0x02.过滤规则

  • on函数过滤
  • " | ` | < | > | ( | ) | $过滤。
  • javascript关键词过滤。
  • url递归解码后若匹配上述规则,过滤。如 尖括号经过5次url编码%252525253c仍然会过滤。
  • url-Unicode编码过滤。如%u0061这种正常字符的url-Unicode编码也会拦截。

以上所谓过滤,是直接跳转404,所以不存在嵌套绕过的可能性。

0x03.绕过思路

3.1、首先参数本身在Javascript环境下,这为bypass提供了极好的环境。我们不需要考虑HTML环境下的javascript的绕过思路,如 <svg/onload+= 这种,因此这次绕过没有想去先绕尖括号来执行html标签。

3.2、根据前面测试过滤规则,整理一些能执行的规则:

  • 单引号
  • 中括号
  • 等号
  • 分号
  • %0d%0a
  • 反斜杠(这是最大的杀器)

3.3、圆括号被过滤很伤,一般我们执行弹窗如:

  • alert(1)
  • alert (1)
  • alert1
  • \u0061lert(1)

    以上几种还能互相组合利用。
    但是通过前面测试,反引号和圆括号都被过滤,这里很难下嘴。

3.4、其实在很多场景下,前面搜集的规则有多种绕法,但是需要HTML执行环境,这里本来就在javascript环境下,实在不想绕出去再跑到HTML的战场上去绕尖括号。也怪很少遇到这种场景,后来想到javascript场景下还有unicode编码,过滤器居然忘了过滤反斜杠,于是可以传入这样的参数:jav\u0061scrip\u0074:\u0061lert 未被过滤,窃喜,心想机会来了。

3.4、但是问题还卡在圆括号和反引号上,比如你在Chrome Console下执行 jav\u0061scrip\u0074:\u0061lert(1) 是没问题的, 但是如果执行 jav\u0061scrip\u0074:\u0061lert\u00281\u0029 这种肯定是直接出错的。这里为什么会出现这种情况三言两语是说不清的,强烈推荐看下360博客的这篇文章《深入理解浏览器解析机制和XSS向量编码》,理解文章对XSS挖掘帮助很大。

3.5、这里想到之前绕XSS的一个payload:

1
<svg/onload = location='jav'+'ascript'+':%2'+'0aler'+'t%20%2'+'81%'+'29'>

突然想到在location后面跟的参数是url编码环境,于是构造了如下payload:

1
location='jav\u0061scrip\u0074:\u0061lert\u0025281\u002529'

至此成功执行XSS代码。

0x04.总结

目标过滤机制有两个问题,一是参数传入了javascript执行环境內,二是未过滤反斜杠,这两个问题可以说是致命的。就算是前面过滤机制再严格,unicode编码能干的事情太多了,比如前面说的绕尖括号,可以跳到HTML执行环境下执行XSS。上文payload通过unicode编码传入参数 % ,再结合localtion后的url编码环境,点穴手法可以说是量身定做,恰到好处。这种环境很难再次遇到,记录一下奇淫巧技。