Photo by Halacious on Unsplash

Server-Side Template Injection (SSTI)

Roshan Cheriyan
3 min readOct 1, 2020

--

On last day, When i was Playing CTF games, I played with one interesting vulnerability, Server-Side Template Injection (SSTI)

Now a days Template engines are widely used by web applications to display dynamic data via web pages. Unsafely embedding of user input to templates enables Server-Side Template Injection, Template Injection may cause with client side XSS or leads to critical Remote Code Execution(RCE)

Here, In that CTF ,Template injection leads to RCE to obtain flag. This is not a walkthrough of that CTF. Its just a note or explanation for, how the Template Injection works, and how i gains access to that server.

When i started the server, One simple webpage loads. After my simple enumeration using burp-suite response header told me, this web app using Werkzeug (It’s a Python based WSGI web application library). Then i started enumerate directory or possible URLs, On that time i noticed what ever i submitted in the URL it gets reflects on that webpage.

`home` is reflected in this page

Werkzeug is also a template based engines, So i want to confirm Template Injection in this web app, for that i entered this simple calculation payload {{ 2 * 7 }}, If its displays 14 then the template injection possible.

Then our attempt is success ,so i want to execute codes remotely. Before RCE,I used to read the ‘/etc/passwd’ in that server. For that i used the payload {{‘’.__class__.__mro__[2].__subclasses__()[40](‘/etc/passwd’).read()}}
There are many another payloads to read the files use reference from swisskyrepo

Finally to my favorite part Code execution, In this server RCE is pretty simple. When i executed the {{‘’.__class__.__mro__[2].__subclasses__()[396](‘id’,shell=True,stdout=-1).communicate()[0].strip()}}

There may be several methods to execute SSTI(Server side Template Injection), Template Injection is possible With every template based web application (Not only in Python In Other languages too)

Source Code Explanation

from flask import Flask,request,render_template_string 
from urllib import unquote
app = Flask(__name__)
@app.route("/")
def hello():
return "python template injection"
@app.errorhandler(404)
def page_not_found(error):
url = unquote(request.url)
return render_template_string("<h1>URL %s not found</h1><br/>"%url), 404
if __name__ == '__main__':
app.run(debug=False, host='0.0.0.0')

When page_not_found(error): function execute, The url parameter (unquote(request.url)) is directly Stored to a variable url, This variable directly rendered with the error template, So what ever user entered on URL, That will reflect on that templates. So we utilize this loophole to execute our payload, That will render on that page. This Leads To XSS(Cross Site Injection) or RCE ( Remote Code Execution )

Remediation

For securing from this kind of attack validate all the user controlled areas, Like urls, User Inputs etc… Don't render user inputs directly to the template.

--

--

Roshan Cheriyan

Security Researcher || Web Penetration Tester || Reverse Engineer || Web & Flutter Developer