The Name That Ran: Server-Side Template Injection in Flask
The challenge
Peachtree's card page runs your name as code. Send template code like {{7*7}} as the name. Make the card print the app's SECRET_KEY.
What you'll learn
- Detect server-side template injection with an arithmetic probe
- Tell Jinja2 apart from other engines from its output
- Read Flask's config object from inside a template
- Explain why a leaked SECRET_KEY means forged sessions
- Render user input as data, never as template code
Skills tested
Prerequisites
- What a query string is
- What a web template does
How it works
A template engine turns a template plus variables into HTML. Server-side template injection happens when user input becomes part of the template instead of a variable: the engine then evaluates whatever the user wrote.
Here the app does TEMPLATE.replace("NAME", name) and renders the result. {{7*7}} returns 49, so the input is code. The app uses Jinja's sandboxed environment, which refuses attributes starting with an underscore, so code-execution chains end in a SecurityError. But a sandbox only limits what an expression may do, not what the template was given: in Flask every template can reach config, which holds SECRET_KEY, the key that signs session cookies.
Common mistakes
- Typing spaces. A raw space splits the request line, and gunicorn answers 400 Invalid HTTP Version. Write
{{config}}or encode spaces as%20. - Chasing code execution. The sandbox blocks
__class__and friends; those payloads only produce the generic 500 page. The secret is already inconfig. - Stopping at 49. The arithmetic probe only proves the bug; the secret is in
config. - Answering the database URL. The key asked for is
SECRET_KEY.
How to defend against it
- Never concatenate user input into a template string. Keep templates static and pass data as variables:
render_template_string(TEMPLATE, name=name). - Use a sandboxed environment (
jinja2.sandbox.SandboxedEnvironment) if users must author templates. - Rotate
SECRET_KEYafter a leak: every session signed with the old key can be forged.