README.md
Rendering markdown...
const express = require("express");
const Handlebars = require("handlebars");
const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.get("/", (req, res) => {
res.send(`
<h2>Content Renderer</h2>
<form method="POST" action="/render">
<textarea name="payload" rows="15" cols="80"></textarea><br><br>
<button>Render</button>
</form>
`);
});
app.post("/render", (req, res) => {
try {
// [STEP 1 - ENTRY POINT]
// Nhận dữ liệu từ request body (user-controlled input)
// req.body.payload là một JSON string do attacker gửi lên
const payload = JSON.parse(req.body.payload);
// Parse JSON string thành JavaScript object (AST object)
// Đây chính là điểm attacker inject AST thay vì template string
// Nếu attacker gửi object có structure hợp lệ (type: "Program"),
// Handlebars sẽ tin tưởng và sử dụng trực tiếp
// [STEP 2]
// Người dùng truyền payload vào Handlebars.compile()
const template = Handlebars.compile(payload);
// payload ở đây KHÔNG phải string template bình thường
// mà là AST object (Program node) do attacker kiểm soát
// [STEP 5]
// Gọi function template đã được compile trước đó → function được thực thi
const result = template({});
// [STEP 35]
res.send(`<pre>${result}</pre>`);
} catch (e) {
res.send(`<pre>${e.stack}</pre>`);
}
});
console.log(require.resolve("handlebars"));
app.listen(3000, () => {
console.log("http://localhost:3000");
});