Monday, October 26, 2026

StealMyBitcoin-PoC for studying PHP worker memory corruption in a Docker CTF lab

StealMyBitcoin-PoC for studying PHP worker memory corruption in a Docker CTF lab

StealMyBitcoin-PoC is a single-file, standard-library Python reproduction of a CTF exploit chain that walks a PHP 8.4.26 lab server from memory exhaustion to code execution, intended strictly for authorized lab study.

ToolKillaBoi/StealMyBitcoin-PoC — single-file Python 3.11+ PoC of a PHP session-upload-progress memory corruption chain against a self-hosted Docker CTF lab
CategoryExploit-development proof of concept / CTF challenge reproduction
Primary UseReproducing and studying a full heap-leak-to-code-execution chain against an intentionally vulnerable php:8.4.26-fpm-alpine lab behind nginx, in Docker on loopback
Safe UseEducational and documentary analysis for authorized professionals; the author explicitly warns the producer walks PHP into its memory limit and must only be run where that behavior is authorized, such as the bundled local Docker lab
Telemetry NoteThe script refuses any target that is not the challenge endpoint or a loopback URL, aborts before sending a packet otherwise; defenders would observe characteristic PHP memory-limit fatals and oversized PHPSESSID cookies from a single source

StealMyBitcoin-PoC is the public release of the author's solution to the Steal My Bitcoin CTF challenge, packaged as one Python file — stealmybitcoin_poc.py — that depends on nothing beyond the standard library. What makes it interesting to security professionals is not the flag at the end but the shape of the chain it documents: it takes a PHP request-parsing behavior that is ordinarily considered a nuisance, the fatal that appears when a script exceeds its memory_limit, and turns the stale worker state left behind by that failure into first an information disclosure and then arbitrary code execution. The repository carries roughly 771 stars and is written in Python, targeting an Alpine build of PHP 8.4.26.

The README is unusually disciplined about scope. Everything the script does is calibrated against a local Docker lab — an Alpine PHP 8.4.26 CLI server behind nginx, on loopback — rather than against any live third-party target. The author includes an explicit warning that the producer stage deliberately pushes PHP to its memory limit and that the tool must only be run somewhere that behavior is authorized, and the script itself enforces a guard: it will only talk to the challenge endpoint or a loopback URL, aborting before any packet leaves the machine otherwise. That combination of a self-contained lab recipe and built-in target validation marks this as an educational artifact rather than a general-purpose weapon.

Internally the chain is a four-stage pipeline, and the README renders it as a clean table: a health check that confirms the exact PHP build, a heap leak that recovers a Zend heap base address, a code leak that recovers a pointer to zval_ptr_dtor inside the PHP binary, and a final callback request that drops a forged HashTable where cleanup will find it and reach zif_system, the engine's handler for system. The whole run is bounded — at most twenty HTTP requests, no looping, no retries — which reflects the fragility of the underlying technique and the author's intent to record one deterministic, verifiable run rather than produce a spray-and-pray tool.

The first stage of the chain deserves attention because it is the part with the broadest defensive relevance. A relatively small multipart/form-data body, on the order of a quarter megabyte, is shaped with heavily nested form keys and a large set of empty cookie names so that PHP's session upload-progress handling expands it into gigabytes of nested array allocations during parsing. When the 128 MiB limit is hit mid-parse, the worker is left holding stale session state. The README is careful to note that a memory-limit fatal or an nginx 502 on its own proves nothing — it is the reuse of that poisoned worker by precisely-shaped follow-up requests that turns the crash into a leak.

The leak stages are where the tool's engineering shows. Each leak batch is one large producer request followed by eight pipelined consumer requests sent down a single open connection before any response is read. The consumers chase the memory tied to the stale session state; when one lands on the right reused worker with the right heap layout, the PHPSESSID cookie comes back oversized, carrying neighbouring heap data. The script then walks those bytes as little-endian 64-bit words, looking for multiple pointer-looking values that agree on one aligned 2 MiB Zend heap base before it will trust the result. The code-leak stage applies a similar consistency check, validating the recovered value against a locally calibrated fingerprint of zval_ptr_dtor for the Alpine build.

The dual-leak design answers a question anyone who has worked with modern exploit mitigations will recognize: ASLR randomizes the heap and the code independently. The heap leak tells the script where to place a forged structure; the code leak tells it where the function it wants called actually lives. The README notes that addresses from an earlier worker or an earlier run are not safe substitutes, and every attempt to reuse them failed — a candid operational detail that reinforces how worker-sensitive the whole chain is and why the script validates each leak before proceeding.

Build fidelity is treated as a hard requirement, not a nicety. The README warns that a Debian php:8.4.26-fpm stack reports the same PHP/8.4.26 version string but has a different binary layout, so the code-pointer fingerprint will never match and the run aborts at the code-leak stage. The calibration was measured against the cli-server SAPI with four workers — PHP_CLI_SERVER_WORKERS=4 — which is also what gives the leak stages a pool of workers to race for. For anyone studying why exploit PoCs are so brittle across distributions, this is a compact, concrete case study in how identical version strings can hide incompatible internals.

Operationally the tool is deliberately spartan: it takes a single --url flag pointing at the lab endpoint, and an --output-dir flag that defaults to a timestamped directory where the run's evidence is written. Invocation is simply python stealmybitcoin_poc.py --url http://127.0.0.1:18166/php-version.php, and running it with no arguments prints help and exits without touching the network. The lab itself is brought up with the docker run commands in the README, and torn down with matching docker rm calls — a complete, self-contained training environment with a dummy print-flag stand-in rather than anything real.

Verification is built into the design rather than left to the operator. A successful final stage returns a fresh nonce generated for that run, the output of id, a hash of the binary the callback resolved, and the dummy flag string — evidence that the forged cleanup path actually executed, not just that something crashed. Exit status is 0 on a verified run and 1 on anything else, which makes the tool usable as a repeatable experiment: change one variable in the lab, re-run, and observe whether the chain still holds. For defenders, the observable signatures are equally distinctive — memory-limit fatals from modest request sizes and anomalous PHPSESSID cookie lengths from a single source — and the README's stage-by-stage table maps neatly onto detection hypotheses for monitoring PHP workers under similar stress.

The author is disarmingly honest about the code quality, noting the PoC is cluttered with debug output and inviting readers to write a cleaner version. There is also a historical note preserving the live run that actually solved the challenge, kept separate from the lab-oriented instructions. For authorized professionals — exploit developers, PHP engine researchers, blue teams modeling worker-poisoning behavior — this repository is valuable precisely because it documents a complete, calibrated, evidence-verified chain in a form that can be studied end to end on a laptop, with every guardrail pointing inward at the operator's own lab.

Official project repository for KillaBoi/StealMyBitcoin-PoC.
Download Tool

Educational analysis for authorized security professionals. Use only in controlled, authorized environments.

Share articleFacebookXLinkedIn

Continue exploring

Browse all articles →

0 comentários:

Post a Comment

Note: Only a member of this blog may post a comment.