DOM-XSS 自动检测与验证模型

阅读量    135563 |

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

 

1 介绍

DOM-XSS 是网络中最常见的漏洞,再配合其它的攻击手段往往能轻易敲开服务器的大门。在各大漏洞平台中,DOM-XSS 漏洞也是数量最多的。本文介绍一种基于污染追踪技术的 DOM-XSS 自动检测与验证模型,并对模型中的污染源点、污染终点和传播过程记录方法做详细介绍。最后介绍基于 AST 技术的 payload 生成方法,该方法可以自动验证 DOM-XSS 是否为误报,提高 DOM-XSS 的自动检测效果。

 

2 原理介绍

污点分析技术(taint analysis, 又被称作信息流跟踪技术)是自动检测 DOM-XSS 的理论基础,它是信息流分析技术的一种实践方法, 该技术通过标记系统中的敏感数据, 进而跟踪‘标记数据’在程序中的传播过程, 以检测系统安全问题。

 

3 敏感数据

在污点分析技术中,最重要的两个概念分别是敏感数据和传播记录。首先引入敏感数据的定义:由 source 开始,经过传播后进入 sink 并引发“数据与指令的错用”的数据被定义为敏感数据。其中 source 为污染源点,也就是数据的生产者。sink 为污染终点,也就是数据的消费者。
攻击者可以控制的输入被称作污染源点,常规的污染源点如下:
(1) window.location.hash
(2) window.location.href
(3) window.location.pathname
(4) window.location.search
(5) document.documentURI
(6) document.baseURI
(7) document.URL
(8) document.referrer

漏洞的本质是数据与指令的错用,所以能消费敏感数据的方法(函数或属性)都是污染终点,常规的污染终点如下:
(1) eval setInterval setTimeout
(2) window.location
(3) Element.innerHTML
(4) Element.outerHTML
(5) Element.setAttribute
(6) HTMLScriptElement.src
(7) HTMLEmbedElement.src
(8) HTMLIFrameElement.src
(9) HTMLAnchorElement.href
(10) HTMLFormElement.action
(11) HTMLInputElement.formAction
(12) HTMLButtonElement.formAction
(13) HTMLObjectElement.data
(14) HTMLScriptElement.text
(15) HTMLScriptElement.textContent
(16) HTMLScriptElement.innerText

 

4 传播记录

接下来引入传播记录的定义:被 sink 消费的数据的来源以及变化过程称为传播记录。
传播记录描述了数据从 source 到 sink 的变化过程,传播记录的完整性直接影响 DOM-XSS 的检测结果。衡量传播记录的指标主要有:
(1) 传播记录是否全面、完整地描述了数据的变化过程;
(2) 传播记录是否可以做到字符级别的描述。

众所周知,触发 DOM-XSS 漏洞的字符串往往是来自于不同 source 的字符的组合,如果不能完整记录数据变化的过程或做不到字符级别的描述,那将会产生大量的漏报。通过分析 ES 和 HTML 规范可以得知:以下的 API 可以修改字符串。做好以下这些 API 的记录就可以最大程度保证传播记录的完整性。

  1. String.prototype.anchor 用于创建 a 标签,样例代码如下:
    var myString = "Table of Contents";
    document.body.innerHTML = myString.anchor("contents_anchor");
    //输出.............
    <a name="contents_anchor">Table of Contents</a>
    
  2. String.prototype.big 创建带有 big 标签的字符串,样例代码如下:
    var worldString = 'Hello, world';
    console.log(worldString.big());       // <big>Hello, world</big>
    
  3. String.prototype.blink 创建带有 blink 标签的字符串,样例代码如下:
    var worldString = 'Hello, world';
    console.log(worldString.blink());   // <blink>Hello, world</blink>
    
  4. String.prototype.charAt
  5. String.prototype.charCodeAt,charCodeAt() 方法返回指定位置的字符的 Unicode 编码。返回值是 0 – 65535 之间的整数。
  6. String.prototype.codePointAt()
  7. String.prototype.concat,concat() 方法拼接两个或多个字符串并返回一个新的字符串
  8. String.prototype.fixed,样例代码如下:
    var worldString = 'Hello, world';
    console.log(worldString.fixed()); // "<tt>Hello, world</tt>"
    
  9. String.prototype.fontcolor,样例代码如下:
    var worldString = 'Hello, world';
    console.log(worldString.fontcolor('red') +  ' is red in this line');
    // '<font color="red">Hello, world</font> is red in this line'
    
  10. String.prototype.fontsize
  11. String.prototype.link,样例代码如下:
    var hotText = 'MDN';
    var url = 'https://developer.mozilla.org/';
    console.log('Click to return to ' + hotText.link(url));
    // Click to return to <a href="https://developer.mozilla.org/">MDN</a>
    
  12. String.prototype.italics,样例代码如下:
    var worldString = 'Hello, world'; console.log(worldString.blink());
    //"<i>str</i>"
    
  13. String.prototype.match
  14. String.prototype.search
  15. String.prototype.matchAll
  16. String.prototype.normalize
  17. String.prototype.padEnd,样例代码如下:
    const str1 = 'Breaded Mushrooms';
    console.log(str1.padEnd(25, '.'));
    // expected output: "Breaded Mushrooms........"
    
  18. String.prototype.padStart
  19. String.prototype.repeat
  20. String.prototype.replace
  21. String.prototype.slice
  22. String.prototype.small,样例代码如下:
    var worldString = 'Hello, world';
    console.log(worldString.small());     // <small>Hello, world</small>
    
  23. String.prototype.split
  24. String.prototype.strike
  25. String.prototype.sub,样例代码如下:
    var worldString = 'Hello, world';
    console.log(worldString.sub());     // <sub>Hello, world</sub>
    
  26. String.prototype.substr
  27. String.prototype.substring
  28. String.prototype.sup
  29. String.prototype.toLocaleLowerCase
  30. String.prototype.toLocaleUpperCase
  31. String.prototype.toLowerCase
  32. String.prototype.toUpperCase
  33. String.prototype.toString
  34. String.prototype.trim The trim() method removes whitespace from both ends of a string and returns a new string, without modifying the original string.
  35. String.prototype.trimEnd
  36. String.prototype.trimStart
  37. String.prototype.valueOf
  38. RegExp.prototype.exec
  39. document.write
  40. document.writeln
  41. decodeURI encodeURI decodeURIComponent encodeURIComponent unescape escape
  42. postMessage
  43. ‘+’ 加法

总结,检测 DOM-XSS就是记录数据从生产者到消费者的传播过程,这正污点分析技术的应有之义。

 

5 构造 payload

检测出从 source 到 sink 的敏感数据后还需要构造正确的payload,才能触发 DOM-XSS。根据敏感数据在 sink 中的位置分布,把形成 DOM-XSS 漏洞的原因分为以下三种:
(1) tag 污染是指敏感数据出现在 HTML Tag 标签中,敏感数据可能是 tag 名字或 tag 属性等,例如:

 document . write ('<script src ="// example . org /' + 敏感数据 + '"></ script >')

(2) 注释污染是指敏感数据出现在注释部分,例如:

document . write (' <!--' + 敏感数据 + '-->')

(3) 文本污染是指敏感数据出现在一对 HTML tag 标签中间,例如:

document . write ('<div >' + 敏感数据 + ' </div >')

众所周知,生成 payload 时最重要的工作是闭合上下文中的原有标签,并创建一个与上下文无关的<script>XXX</script>。我们使用语法树分析上下文的语法关系并识别前后的语法,以完成原有标签的闭合工作。使用语法树是因为分析过程是有限状态自动机,可以实现自动验证 DOM-XSS。样例代码如下:

var code = 'function test (){ ' + 'var x =' + location.referrer +  '; ' + 'doSomething (x); '+ '}'; 
eval ( code )

上述代码的语法树如下:

FunctionDeclaration
    Identifier : test
    FunctionConstructor
        Identifier : test
        Block
        Declaration
            Identifier : x
            StringLiteral : "http://example.org"
        ExpressionStmt
            SpecialOperation : FUNCTION_CALL
                Reference
                    Identifier : doSomething

通过对上述代码的分析,我们可以构建出如下的 payload。当location.referrer的值等于 payload时,就可以将 eval() 的参数拆解成一个独立的字符串,以触发 DOM-XSS 漏洞。

http://example.org/#;};dom-xss;//

 

6 开源工具

本文的思路借鉴了开源工具 dom-based-xss-finder,地址:https://github.com/AsaiKen/dom-based-xss-finder,总结说明如下:
(1) 通过对 API 进行 hook,实现了 source、sink、taint 三类传播功能的 wrapper;
(2) 利用 AST 对网页中 JS 源码转成语义等价的、用 wrapper 实现的 JS 源码;
(3) wrapper 方法保证 JS 功能正确的同时,记录了 taint 的传播过程,最后上报。
这个工具的思路很好,功能也很全面,但效率有些低。

 

致谢

w8ay 和独钓寒江雪两位师傅在我写作过程中给予了极大的帮助,在此特别感谢!
w8ay 从事安全自动化工具相关工作,W13scan 等著名工具作者,Hacking8 安全知识库(https://www.hacking8.com)作者。
独钓寒江雪 高级前端技术工程师,思否著名博主:https://segmentfault.com/u/king_hcj。
好了,今天到这里,下次见。

个人能力有限,有不足与纰漏,欢迎批评指正
微信:qq9123013 备注:v8交流 邮箱:v8blink@outlook.com

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多