让我们继续寻找DOM XSS,在上一节里,在地址栏里输入的内容,很容易出现在了源代码里,然后我们发现源代码里是一个DOM 操作,通过js 的Unicode 转义,我们将利用代码植入到了innerHTML 指向的内容中,同时绕过了过滤。
关于编码的顺序问题,可以参考我之前总结的一篇文章,比较清晰。
那么,如果我们在源代码里,定位不到我们在URL 里的参数呢,其实这并没有太多不同。只是因为网页直接通过脚本,通过DOM 操作,修改了或者添加了某些标签,源码中看不到。但只需要进入调试工具里,就能找到了。
这里拉来一个老漏洞,现已修复:
|
|
这样一个地址,我们跑去源代码里,是不会直接找到输出的,其实这也是更为常见的情况:
此时我们应该去到调试工具里找,在审查元素里,我们看到了输出的位置:
按照以往的方法,我们仍然是使用常识构造的方式,去看那些写法是被过滤的,然后尝试去构造攻击模式。另一种方法,则是去resources 中,去查看脚本,是那个脚本执行了什么操作,让变量进入了标签,了解清楚了之后,可以对症下药的创造攻击向量。
我们直接对sid 这个参数在resource 中搜索,会找到响应的处理函数。在这里,是一个叫getUrlPara 的函数:
进一步,定位到该函数的定义,通过分析该函数,我们能了解脚本在获得该参数后的操作,在该函数里,我们发现,该函数对 location.href 中的尖括号和引号已经进行了过滤处理,但实际上,这段代码实际上是不太正确。
因为在进行处理之前,拿到的href 已经经过了URL 编码,该函数不会对任何符号进行处理。即使是浏览器不做编码处理,如果我们预先对它进行编码处理,也会跳过函数中的过滤。然后让我们再回到函数调用之后的上下文。
|
|
这里,通过decodeURLComponent 将编码后的参数,又解码成了原符号,而后边调用的insertFlash 操作,未经过滤的将sid 写进了页面:
|
|
我们很容易的想象到了构造< img src=# onerror=alert(1)>,对尖括号进行URL 编码就可以了。实际上,就这一个漏洞,我们不仅可以使用URL 编码的方式。结合我之前说的浏览器的解析顺序,在这里,从URL 获得的参数,进入脚本,脚本调用DOM 操作,修改DOM 树,所以我们用Unicode编码也能最后得到解析。
我们始终说,安全编码是一个不容易的技术,因为一步疏漏就会在最终造成满盘皆输。所以,对于开发者,想要真正构建安全的程序,就必须对程序所涉及的技术框架了如指掌。比如对于Web,应该对浏览器的原理,HTTP/HTTPS,各种编码原理,JS&CSS&HTML,PHP&ASP,的安全部分都有一定了解,才能在构建程序的时候,抓住最关键的部分,确保不出问题。