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(`
Content Renderer
`);
});
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(`${result}`);
} catch (e) {
res.send(`${e.stack}`);
}
});
console.log(require.resolve("handlebars"));
app.listen(3000, () => {
console.log("http://localhost:3000");
});