NahamCon CTF 2022

Just in Time Maple Bacon played in NahamCon CTF 2022 this past weekend, which came as a surprise - we were fully planning on focusing our efforts onto AngstromCTF which overlapped, however, NahamCon CTF proved to be interesting and good-quality so a last-minute decision was made to participate in both. AngstromCTF is still underway, but in the awkward passage of time between my last week and weekend, I played in NahamCon CTF for a little bit of practice. ...

May 2, 2022 · 1081 words · Vie

RaRCTF 2021: MAAS 2 + Unintended Solutions

MAAS 2 // Notes Source was the same from MAAS 1 (and will be the same for MAAS 3). MAAS 2 involved the ’notes’ part of MAAS, where you are prompted to register a user and afterwards add key:val attributes to yourself, give yourself a bio, or transfer key:value attributes to another user. The provided source has some interesting code: notes/app.py @app.route('/useraction', methods=["POST"]) def useraction(): mode = request.form.get("mode") username = request.form.get("username") if mode == "register": r = requests.get('http://redis_userdata:5000/adduser') port = int(r.text) red = redis.Redis(host="redis_users") red.set(username, port) return "" elif mode == "adddata": red = redis.Redis(host="redis_users") port = red.get(username).decode() requests.post(f"http://redis_userdata:5000/putuser/{port}", json={ request.form.get("key"): request.form.get("value") }) return "" elif mode == "getdata": red = redis.Redis(host="redis_users") port = red.get(username).decode() r = requests.get(f"http://redis_userdata:5000/getuser/{port}") return jsonify(r.json()) elif mode == "bioadd": bio = request.form.get("bio") bio.replace(".", "").replace("_", "").\ replace("{", "").replace("}", "").\ replace("(", "").replace(")", "").\ replace("|", "") bio = re.sub(r'\[\[([^\[\]]+)\]\]', r'{{data["\g<1>"]}}', bio) red = redis.Redis(host="redis_users") port = red.get(username).decode() requests.post(f"http://redis_userdata:5000/bio/{port}", json={ "bio": bio }) return "" elif mode == "bioget": red = redis.Redis(host="redis_users") port = red.get(username).decode() r = requests.get(f"http://redis_userdata:5000/bio/{port}") return r.text elif mode == "keytransfer": red = redis.Redis(host="redis_users") port = red.get(username).decode() red2 = redis.Redis(host="redis_userdata", port=int(port)) red2.migrate(request.form.get("host"), request.form.get("port"), [request.form.get("key")], 0, 1000, copy=True, replace=True) return "" @app.route("/render", methods=["POST"]) def render_bio(): data = request.json.get('data') if data is None: data = {} return render_template_string(request.json.get('bio'), data=data) The relevant parts are when mode is equal to bioadd. There’s a pretty hefty sanitizer in play that removes all relevant characters required for an SSTI. This is further supplemented by the endpoint to /render, which takes your input and passes it into render_template_string. TL;DR: Server-Side Template Injection involves injecting code into template expressions that are evaluated on the server. Essentially, if you have an app vulnerable to SSTI, then you should be able to inject any expression into {{double curly brackets}} and that expression would be evaluated. ...

Aug 20, 2021 · 731 words · Vie