Rồi 👍 mình viết SSTI (Server-Side Template Injection) theo cùng cấu trúc bạn vừa dùng cho SSRF nhé — đầy đủ từ định nghĩa, phân loại, payload, hậu quả đến phòng ngừa.
1) SSTI là gì — tóm tắt
Server-Side Template Injection (SSTI) là lỗi khi ứng dụng render template trên server nhưng lại cho phép dữ liệu từ user trở thành một phần template . Attacker có thể chèn biểu thức template để engine thực thi → từ leak data đến RCE (nếu engine cho phép truy cập object hệ thống).
2) Phân loại SSTI & ví dụ cho mỗi loại
A. Basic SSTI (In-band)
Mô tả: attacker chèn biểu thức đơn giản để xác nhận engine có evaluate.
Ví dụ vulnerable code (Node.js EJS pseudo):
app.get('/hello', (req, res) => {
const tmpl = "<h1>Hello " + req.query.name + "</h1>"; // user input nối trực tiếp
res.send(ejs.render(tmpl));
});
Payload (lab):
/hello?name=<%= 7*7 %>
Nếu output hiển thị 49 → chứng tỏ SSTI.
Hậu quả: chứng minh khả năng thực thi expression, mở đường leo thang.
B. Variable/Object Access
Mô tả: attacker từ input truy xuất biến trong context hoặc class nội bộ.
Ví dụ payload (Jinja2, lab):
{{ config.items() }}
→ đọc config Flask app.
Hậu quả: lộ secrets, config, env vars.
C. Sandbox Escape / RCE
Mô tả: nếu engine cho phép truy cập object chain, attacker leo tới OS-level calls.
Ví dụ lab payload (Jinja2):
{{ ''.__class__.__mro__[1].__subclasses__() }}
→ dò các class, từ đó tìm subprocess/os → thực thi lệnh.
Hậu quả: Remote Code Execution.
D. Blind SSTI
Mô tả: response không hiển thị trực tiếp kết quả expression, nhưng attacker suy ra qua side-channel (thời gian, lỗi).
Payload test (lab):
{{ 7/0 }}
Nếu server trả error stacktrace liên quan template engine → SSTI blind.
3) Payload mẫu (lab-only)
- Detect:
{{7*7}}(Jinja2/Twig)<%= 7*7 %>(ERB/EJS)
- Access variable:
{{ request.headers }}(Flask/Jinja2)
- Blind/error-based:
{{ 1/0 }}→ error
- Sandbox escape (lab):
{{ ''.__class__.__mro__[1].__subclasses__() }}
4) Cách phát hiện / kiểm thử SSTI
- Tìm endpoint render output từ input (profile name, message template, error page).
- Thử payload benign (
{{7*7}}) → nếu evaluate → SSTI. - Thử gây error (
{{1/0}}) → nếu stacktrace của template engine lộ ra. - Kiểm tra logs/error server để xác nhận.
5) Hậu quả thực tế
- Data exposure (config, env vars).
- Template tampering (modify view logic).
- RCE (truy cập object chain → gọi hệ thống).
- Toàn quyền server, lateral movement.
6) Phòng ngừa — best practices
- Không render template từ input user (chỉ render template file sẵn có).
- Escape / autoescape: bật autoescape (Jinja2
select_autoescape, Twig autoescape). - Whitelist template features: tắt eval,
$where, helpers nguy hiểm. - Không bind object nhạy cảm (os, db, config) vào template context.
- Sandbox (nếu thật cần): dùng sandboxed environment, nhưng vẫn dễ bypass.
- Validate input: chỉ inject dữ liệu primitive (string/number), không object/code.
- Code review / pentest: kiểm tra chỗ
render(user_input)hoặccompile()từ input.
7) Ví dụ sửa code (Node.js với Handlebars)
Vulnerable:
app.get('/hello', (req, res) => {
const tmpl = req.query.tmpl; // user cung cấp template
res.send(Handlebars.compile(tmpl)({}));
});
Safe:
const template = Handlebars.compile("Hello, {{name}}!");
app.get('/hello', (req, res) => {
const name = String(req.query.name || 'guest'); // ép kiểu
res.send(template({ name }));
});
8) Checklist kiểm thử & remediation
- Xác định endpoint nào render template từ input.
- Test
{{7*7}},<%=7*7%>để detect. - Test error (
{{1/0}}). - Kiểm tra context leak (
{{config}}). - Remediate: không render user template, enable autoescape, remove dangerous helpers, sandbox/validate.