<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/steal-my-bitcoin-ctf-poc-3uyn40xtx" -->

---
title: Steal My Bitcoin CTF PoC | daily.dev
description: This GitHub repo releases a proof-of-concept Python exploit for the Steal My Bitcoin CTF challenge, targeting Alpine PHP 8.4.26 running the CLI server. It...
canonical: https://daily.dev/posts/steal-my-bitcoin-ctf-poc-3uyn40xtx
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Steal My Bitcoin CTF PoC | daily.dev
og:description: This GitHub repo releases a proof-of-concept Python exploit for the Steal My Bitcoin CTF challenge, targeting Alpine PHP 8.4.26 running the CLI server. It...
og:url: https://daily.dev/posts/steal-my-bitcoin-ctf-poc-3uyn40xtx
og:image: https://api.daily.dev/og/posts/3UyN40xtx.png
og:image:alt: Steal My Bitcoin CTF PoC
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Steal My Bitcoin CTF PoC

**[Hacker News](https://daily.dev/sources/hn)** · 16 min read · 1 upvotes · 0 comments

## Summary

This GitHub repo releases a proof-of-concept Python exploit for the Steal My Bitcoin CTF challenge, targeting Alpine PHP 8.4.26 running the CLI server. It abuses a small multipart upload that makes PHP exhaust its memory limit during session upload-progress parsing, leaking a heap address and a PHP code address through PHPSESSID cookies. A final forged HashTable request then redirects PHP's cleanup path to call zif_system, achieving command execution. The whole chain takes at most 20 HTTP requests and succeeds in roughly 7 out of 10 runs against a local Docker lab. A live run against the real challenge recovered a checksum-valid Bitcoin WIF.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://github.com/KillaBoi/StealMyBitcoin-PoC>

## Questions this post answers

### How does a PHP memory limit exhaustion during multipart upload parsing lead to leaking memory addresses?

A small multipart upload with many nested session upload-progress fields forces PHP to allocate far more memory than the wire size suggests, triggering an out-of-memory fatal that leaves stale state behind in a reused PHP worker. A follow-up request that repeats a numeric form key and alters the PHPSESSID cookie length causes that leftover heap memory to be written back into the 256-byte cookie, revealing a Zend heap base address.

_Developers investigating PHP memory-safety issues can track writeups like this one through daily.dev._

### What is zif_system in PHP and how can it be abused for code execution?

zif_system is PHP's internal C function handler for the system() call. In this exploit chain, a forged zend_array HashTable is placed in memory so that during cleanup PHP reads the table's pDestructor field as a pointer to zif_system and invokes it with a controlled zend_string argument, achieving arbitrary command execution. The offset is calculated as zval_ptr_dtor minus 0x204BC0 for this specific Alpine PHP 8.4.26 build.

_Security engineers studying PHP internals exploitation can follow deep technical breakdowns like this via daily.dev._

### Why does the Docker image choice matter for reproducing a PHP memory-corruption exploit calibrated for a specific build?

The exact binary layout, not just the version string, determines whether hardcoded memory offsets work, because a Debian php:8.4.26-fpm build reports the same PHP/8.4.26 version but has a different binary layout, causing the code-pointer fingerprint check to fail. The reliable reproduction uses the Alpine php:8.4.26-fpm-alpine3.23 image running php -S with PHP_CLI_SERVER_WORKERS=4 behind nginx.

_Developers reproducing environment-sensitive security research can verify setup details on daily.dev before testing._

## Community take

How the wider developer community reacted, aggregated from 1 discussion and 39 comments across hackernews (as of 2026-10-26).

**TL;DR:** The main argument is over whether the challenge's real-world realism and slow exploitation timeline mean typical unpatched PHP servers are mostly safe, or whether this PoC proves mass exploitation is now trivial and imminent.

**Sentiment:** 30% positive · 25% mixed · 45% skeptical

**The case for**

- Some see the exploit as a fun, impressive demonstration that experienced researchers were right that it was exploitable, just fiddly.
- It's seen as evidence that there weren't swarms of automated bots instantly rooting every unpatched server.
- A few note the challenge inspired independent, rapid LLM-assisted replications of a php2shell RCE against more realistic setups like nginx/mediawiki.

**The pushback**

- Many argue the challenge setup (PHP dev server proxied via nginx, initially serving static HTML) was unrealistic and doesn't reflect typical production PHP deployments.
- Others counter that dismissing the exploit's severity because of the unusual setup is a form of denial, since real exploitation happened quickly once actual PHP code was live.
- Some question how applicable the technique is to common hardened nginx/PHP-FPM setups versus the toy dev-server configuration used here.

**By community**

- hackernews (heated): Commenters are split and arguing over whether the challenge's artificial setup undermines or confirms the real-world danger of the underlying PHP vulnerability.

**Hottest debate:** Whether the unrealistic, non-standard server setup used in the challenge means the vulnerability is hard to exploit in the wild, or whether its eventual compromise shows real servers are just as vulnerable.

**Open questions**

- What percentage of unpatched PHP servers worldwide have actually been compromised since disclosure?
- Does the exploit chain work against common PHP-FPM/nginx production setups rather than just the PHP built-in dev server used in the challenge?
- Were the wallet funds actually present on the challenge server, or was that assumption mistaken?

**Highlights**

> It took about 2 hours to get taken over and that was with a setup that's sufficiently non-standard that existing PoC would've needed tweaking. The fact that people are still in denial over this is crazy.
> — [rockdoe on hackernews · 2 comments](https://news.ycombinator.com/item?id=50240872)

> To be fair, the person who created the challenge stated that is was a fairly standard setup, replicating something outside a lab, but in reality is was something completely different, and not anywhere near how PHP is usually used. It used the development server in PHP, and did not even run requests with fpm or mod_php. Instead, it used the built in dev server of PHP, and just proxied requests from nginx to the php dev server. Literally the first thing on top of the PHP docs about the dev server used here is this: "Warning This web server is designed to aid application development. It may also be useful for testing purposes or for application demonstrations that are run in controlled environments. It is not intended to be a full-featured web server. It should not be used on a public network." That is not something people do, and it also explains why the site was down all the time, cause the dev server is super slow, as it's not meant for this in any way shape or form. A real setup would add a few zeros to the requests per second a server could handle. So all in all, this was very pointless, as it was nothing like real php sites. A shame, cause a realistic setup woild be more interesting and relevant to answer the question of how hard is it really to gain RCE on a normal site.
> — [NorwegianDude on hackernews · 3 comments](https://news.ycombinator.com/item?id=50238530)

> The only professional I saw making that claim was the CEO of trailofbits who is a former NSA TAO member and doesn’t have anything to prove by talking a big game. It wasn’t that difficult of an exploit, to be honest. I myself am not the leetest of the leet but I was most of the way there, having been set back by the downtime and my time zone.  It’s definitely a fiddly, tricky exploit as most memory exploits are but I think the initial alarm was justified. While waiting for the server to come back up, it took me about 3 hours with LLM assistance to write a php2shell RCE for nginx and mediawiki on the same version of php as TFA. The biggest win, as others have also observe, was the demonstration that there aren’t swarms of automated pwnbots out there that will insta-root your server. Considering the amount of downtime, I think that flag got got pretty quickly.
> — [stackghost on hackernews · 2 comments](https://news.ycombinator.com/item?id=50239057)

> > there aren’t swarms of automated pwnbots out there that will insta-root your server There are, they just didn't have a working exploit. Anyone with a honeypot can tell you attempts were widespread going back to early last week, but it wasn't until Saturday that we started to see successes.
> — [FreakLegion on hackernews](https://news.ycombinator.com/item?id=50241431)

> Related: https://x.com/JamesPavur/status/2114501212313653696 Apparently the wallet key wasn't on the server, like some in the original thread suspected, but perhaps not due to maliciousness after all.
> — [bushwart on hackernews](https://news.ycombinator.com/item?id=50239126)

**Source threads**

- [hackernews](https://news.ycombinator.com/item?id=50237379) · 131 points · 39 comments

## Similar posts on daily.dev

- [Steal My Bitcoin](https://daily.dev/posts/steal-my-bitcoin-nbuzcqwqb) · Hacker News · 0 upvotes · 0 comments
- [HTB: CodeTwo](https://daily.dev/posts/htb-codetwo-klj991bhn) · 0xdf hacks stuff · 2 upvotes · 0 comments
- [Famous Chollima Targets PHP Developers Through Compromised P...](https://daily.dev/posts/famous-chollima-targets-php-developers-through-compromised-p--zloabwapj) · Socket · 0 upvotes · 1 comments

---

Tags: [#security](https://daily.dev/tags/security), [#python](https://daily.dev/tags/python), [#php](https://daily.dev/tags/php)

[View this post on daily.dev](https://daily.dev/posts/steal-my-bitcoin-ctf-poc-3uyn40xtx)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Steal My Bitcoin CTF PoC","url":"https://daily.dev/posts/steal-my-bitcoin-ctf-poc-3uyn40xtx","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/steal-my-bitcoin-ctf-poc-3uyn40xtx"},"datePublished":"2026-10-26T04:56:55.726Z","dateModified":"2026-10-26T12:13:06.148Z","description":"This GitHub repo releases a proof-of-concept Python exploit for the Steal My Bitcoin CTF challenge, targeting Alpine PHP 8.4.26 running the CLI server. It...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/fb2e421d8d8788e5be58b92a5cf09774?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/fb2e421d8d8788e5be58b92a5cf09774?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Hacker News","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Hacker News","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/hn","url":"https://daily.dev/sources/hn"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/steal-my-bitcoin-ctf-poc-3uyn40xtx","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":1},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"security,python,php","timeRequired":"PT16M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Hacker News","item":"https://daily.dev/sources/hn"},{"@type":"ListItem","position":3,"name":"Steal My Bitcoin CTF PoC"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/steal-my-bitcoin-ctf-poc-3uyn40xtx#faq","mainEntity":[{"@type":"Question","name":"How does a PHP memory limit exhaustion during multipart upload parsing lead to leaking memory addresses?","acceptedAnswer":{"@type":"Answer","text":"A small multipart upload with many nested session upload-progress fields forces PHP to allocate far more memory than the wire size suggests, triggering an out-of-memory fatal that leaves stale state behind in a reused PHP worker. A follow-up request that repeats a numeric form key and alters the PHPSESSID cookie length causes that leftover heap memory to be written back into the 256-byte cookie, revealing a Zend heap base address. Developers investigating PHP memory-safety issues can track writeups like this one through daily.dev."}},{"@type":"Question","name":"What is zif_system in PHP and how can it be abused for code execution?","acceptedAnswer":{"@type":"Answer","text":"zif_system is PHP's internal C function handler for the system() call. In this exploit chain, a forged zend_array HashTable is placed in memory so that during cleanup PHP reads the table's pDestructor field as a pointer to zif_system and invokes it with a controlled zend_string argument, achieving arbitrary command execution. The offset is calculated as zval_ptr_dtor minus 0x204BC0 for this specific Alpine PHP 8.4.26 build. Security engineers studying PHP internals exploitation can follow deep technical breakdowns like this via daily.dev."}},{"@type":"Question","name":"Why does the Docker image choice matter for reproducing a PHP memory-corruption exploit calibrated for a specific build?","acceptedAnswer":{"@type":"Answer","text":"The exact binary layout, not just the version string, determines whether hardcoded memory offsets work, because a Debian php:8.4.26-fpm build reports the same PHP/8.4.26 version but has a different binary layout, causing the code-pointer fingerprint check to fail. The reliable reproduction uses the Alpine php:8.4.26-fpm-alpine3.23 image running php -S with PHP_CLI_SERVER_WORKERS=4 behind nginx. Developers reproducing environment-sensitive security research can verify setup details on daily.dev before testing."}}]}
```

