Recreate the completed challenge with a local practice environment and the source of the original deployment kit. The practice copy contains a public dummy flag, has no wallet or prize, and makes no requests to external balance APIs.
This was a heavily AI-assisted challenge in terms of the infrastructure setup. Basically just "Codex, give me a server with PHP on it" + some hardening steps to keep the solves focused on the RCE path.
Rely on it at your own risk.
Install Docker Engine or Docker Desktop with Docker Compose v2 or newer. Use an isolated Linux lab VM for this intentionally vulnerable runtime. The original runtime is amd64; ARM machines require working amd64 emulation.
From this directory:
docker compose up --build -dOpen http://127.0.0.1:8080. Check the endpoints:
curl --fail http://127.0.0.1:8080/php-version.php
curl --fail --data 'message=ping' http://127.0.0.1:8080/ping.phpThe second command should print pong. Port 8080 must be free. The first build
downloads the pinned PHP base image and compiler packages. Package repositories
are not snapshotted, so independently compiled helpers may differ byte for byte.
Verify the intended permissions and helper with:
python3 tools/verify.pyThis is an operator check using Docker access, not a solution through HTTP. To stop the lab and remove its container and network:
docker compose downStarting again restores the same public dummy flag. To rebuild after source edits:
docker compose up --build -dPHP runs as the unprivileged www-data user. /flag is owned by container root
with mode 0400, so PHP cannot read it directly. The root-owned helper
/usr/local/bin/print-flag has mode 4755: executing it gives that program an
effective root UID so it can read the flag and write it to standard output.
The participant's goal is to reach helper execution through the web application.
Read its complete source in helper/print-flag.c.
php-version.php reports the runtime version. ping.php responds to
POST message=ping with pong; other methods receive 405 and other messages
receive 400. Neither endpoint intentionally provides command execution.
Although the base image is named php:8.4.26-fpm-alpine, requests are served by
php -S, the CLI HTTP server. An exploit must apply to that SAPI and configuration.
The VPS guide covers Nginx, HTTPS, container isolation, logging and operation on a fresh Debian 13 amd64 host. It includes the original configuration so readers can investigate the complete request path.
Nginx terminated HTTPS and proxied requests to PHP's CLI server.
The local lab preserves the pinned PHP runtime, CLI HTTP server, eight workers, non-root PHP process and root-owned setuid helper. It uses a simpler teaching page and a public flag baked into the image. Never put a real secret into this Dockerfile. The original kit instead mounts a separately supplied flag read-only.
The local network is internal and the published port binds to loopback. This does not reproduce the original host firewall, user namespace remapping, Nginx, audit, TLS or recovery services. Docker shares a kernel with its Linux host; use a dedicated disposable VM when testing exploits.
| Path | Purpose |
|---|---|
app/ |
Local teaching page and original PHP endpoints |
helper/print-flag.c |
Original flag reader source |
Dockerfile, compose.yaml |
Local lab |
tools/verify.py |
Checks the running lab without printing the flag |
deployment/ |
Original dedicated Debian VPS deployment source |
The archived deployment includes the historical public wallet, domain and signed public authorship statement. Those describe the original event. Live flags, wallet private keys, signing private keys, SSH credentials, TLS material and participant logs are excluded from this copy.