SSTI (Server-Side Template Injection)
Last updated
Was this helpful?
Last updated
Was this helpful?
Run the below command to fetch the SSTI lab container
The below command starts the container & runs the vulnerable app on port 60
Note : fire-up your proxy so we can intercept & observe the requests to be sent to the server
After browsing the app on 0.0.0.0:60
we can see a search field, and to detect the SSTI, we can use a simple payload (usually mathematical payloads are being used to see if the server does the calculation for us! if so, then we can confirm the vulnerability)
and if we observe the request before forwarding it, we can see that we are injecting into the username
parameter of the POST body
After forwarding the request, we can see that the Server executed the equation for us and the result is reflected in the server response!
at this phase, we can conclude that the vulnerable Parameter is username
now, we will move to the next step, to identify the Template Engine
as @u0pattern_cs mentioned in his post we can follow the approach presented in the below image to identify the Template Engine in use
Note: we will follow the green arrow and If the injection fails, we will follow the red arrow.
from the previous step we used the {{3*2}}
payload, so now we will move forward to the next test case and we will use the following payload
and after forwarding the request , we received the following response from the server
if we analyze the server response we can say that the server is still executing our payload (the server prints 2
three times), so the Template Engine can be either Jinja2 (for Python
) or Twig (for PHP
)
we will first start testing if it’s a Python
Template Engine, we will use the below payload (for Python 2
) which tries to dump the classes
and we can see in the below screenshots that we were able to dump the classes names
so we can confirm from this phase that the Template Engine is Jinja2
/etc/passwd
After dumping the classes, we can utilize the file
class to read the content of /etc/passwd
, the class index is 40
and to confirm this we can use the below command to obtain the class name at that index
Now we can call the read()
function from the File
class to read the content of /etc/passwd
ls
to execute bash commands in python we can utilize os library, but how can we use this library in Jinja template engine ? we would need to use the import
statement to bring the os library into our context so we can call the library functions.
Sam mentioned in his project-assignments for his students (which solved the same lab BTW!) that we can use the catch_warnings
function to reach the import
I tried to build a payload that performs steps mentioned by Sam which are :
looping over the classes
for each class, we are searching for a function that has a “warning
” string
using the catch_warnings
function to reach the import
using import
to import the os.system
calling popen
and passing our commands! (below we are passing ls
command)
after injecting this payload, we can see that we were able to perform ls
Using the previous approach we can also obtain a reverse shell, but instead we will pass a python one-line script to the popen
so the final payload will be :
and if we execute it we will successfully obtain the shell as can be seen below
Note:
As the vulnerable application is installed in a docker container, to obtain a reverse shell I started another container in my machine (kali as you see), I’m not aware of how to pass connections between docker containers and other VMs or main host machine