賞金を懸けた侵入競技Steal My BitcoinでのPHP2Shellの悪用
James Pavurが開いた、賞金を懸けた侵入競技「Steal My Bitcoin」で、勝者がPHP2Shellの脆弱性を突き、サーバーに置かれたビットコインの鍵を取り出した[7]。鍵は、ビットコインの入ったアドレスの導出パス上の親鍵で、勝者はこの鍵では資金を動かせなかった[7]。競技サイトは、勝者が出た日時を2026年10月25日15時47分(UTC)と表示し、今はサーバーにビットコインは無いとしている[2]。
経緯
主催者の2026年10月30日のブログでは、ニューヨーク・タイムズなどの記事の主張が、競技を作る動機になった[7]。その主張は、PHP2Shellを突く数回の未認証のWebリクエストを送るだけで、どの攻撃者も世界で動く数百万のPHPのサービスで任意のコードを遠隔で実行できるというものだった[7]。主催者は、ハッキングされた具体的なサイトへの言及は見つけられなかったと書いた[7]。競技で確かめる問いは、PHP2Shellがラボの外で悪用できるかと、AIとPHPのソースを使える比較的未熟な攻撃者でもこの種の脆弱性を悪用できるかの2つだった[7]。
主催者は500ドル分のビットコインを新しいウォレットに入れ、月2.50ドルのDebianのVPSを借り、基本的なWebページをCodexに作らせ、PHPで公開させた[7]。print-flagという1つの実行ファイルだけが鍵(WIF)を含むフラグのファイルを読めるようにサーバーを設定し、ファイアウォールを外した[7]。当初は、少数が試した後にボットネットやスキャナーなどの自動の攻撃に盗まれる、通信の少ないハニーポットになると想定していた[7]。
主催者がold.stealmybitcoin.comに再掲した競技ページには、サーバーに隠したのはビットコイン約500ドル相当の鍵だとある[3]。鍵には、PHPのユーザーアカウントからprint-flagを通じて到達できる[3]。PHPの版はPHP2Shellの脆弱性のCVEが公開される前のものから選び、最初にウォレットを手にした人を勝ちとした[3]。主催者は当初、このページをstealmybitcoin.comに掲載していた[1]。
| 項目 | CVE-2026-109618 | CVE-2026-109619 | 資料 |
|---|---|---|---|
| 内容 | メモリ不足(OOM)時の破損による遠隔コード実行 | 古いグローバル状態による遠隔コード実行 | [10] |
| CVSS v4.0 | 9.2(CRITICAL) | 9.2 | [12、13] |
| 8.4系で影響を受ける版 | 8.4.27より前 | 8.4.27より前 | [12、13] |
主催者は参加の規約で、Webアプリケーションを試し、PHPのコンテナの中でprint-flagを実行するよう参加者に求めた[4]。ホスト・SSH・Docker・Nginx・他人・第三者のサービスへの攻撃と、コンテナからの脱出・サービス妨害・リソースの枯渇・永続化・妨害は禁止した[4]。
競技のソースのREADMEによると、ベースイメージは名前の上ではPHP 8.4.26のfpm-alpineだが、リクエストはPHPのCLIのHTTPサーバー(php -S)が処理していた[8]。その前段ではNginxがHTTPSを終端し、PHPのCLIサーバーへプロキシした[8]。PHPは非特権のwww-dataで動き、root所有の/flagはmode 0400、root所有のprint-flagはmode 4755だった[8]。print-flagを実行すると実効UIDがrootになり、フラグを読める[8]。
主催者は2026年10月25日のHacker Newsへの書き込みで、コンテナの中のPHPは既定の設定から何も無効にせず、特別な堅牢化もしていないと書いた[5]。ホストには、OSのゼロデイで競技が損なわれる危険を減らす堅牢化をしたとした[5]。主催者はVPSの構築の手引きで、構築のbootstrapがASLRを完全に有効にし、運営者のSSHと公開のHTTP(S)のほかは受信を拒否すると説明した[9]。
PHPの実行ページの追加
LiveOverflowは2026年10月24日にHacker Newsで、構成はnginxとPHPのCLIサーバーに見え、nginxの本文の上限の1MBが厄介だと書いた[16]。主催者はブログで、競技への最初の批判は、PHPの無いnginxのページだという主張と、構成のため悪用できないという主張だったと振り返った[7]。
主催者は10月25日のHacker Newsの更新で、nginxの設定はラボより現実的な普通の構成を再現する意図だと説明し、24時間以上解かれなければ易しくすることを検討すると書いた[5]。その後の書き込みでは、php-version.phpを加えるまではPHPを通じて純粋なHTMLを配信していたと認めた[5]。
LiveOverflowは10月25日のHacker Newsで、当初サーバーはindex.htmlだけを配信していたと主催者が認めたと書いた[15]。その構成では、.phpのファイルを要する脆弱なコードの経路に届かないとした[15]。php-version.phpの追加までの期間は、表示された競技の時間から差し引く必要があるとも指摘した[15]。LiveOverflowは、外部からのフィンガープリントでは今は悪用できる構成だと考えるとしたうえで、サーバーは大量のリクエストでクラッシュしていて悪用が大幅に難しく、現実的でない標的だとも書いた[15]。
主催者はブログで、php-version.phpは悪用にPHPのインタプリタの関与が要る場合に備え、すでにPHPで配信していたindex.htmlと並べて置いたと説明した[7]。ping.phpは利用者の入力に動的に反応する必要がある場合に備えて加え、この2つの条件は現実のアプリケーションにほぼ共通だとした[7]。主催者は、悪用できないという主張がどこまで正しかったかは今も100%は確かでなく、最初の版でもSIGSEGVを起こした参加者がいたと書いた[7]。PHPのアプリケーションの変種やnginxのプロキシの設定の変更を求める声は大半を取り上げず、変えていればより多くの参加者が解けた可能性はあるが、それを示す具体的な証拠は無いとした[7]。
CryptoSlateの10月26日の記事によると、Hacktronの共同創業者のMohan Pedhapatiは、序盤の競技は現実的でなかったと主張した[20]。大量の通信がシングルスレッドのPHPサーバーを圧倒し、悪用の成功を通常より難しくしていたとした[20]。Pedhapatiは、解かれていない設定の悪い競技を脆弱性が誇張されている証拠に使うと、誤った安心感を与え、パッチの適用を遅らせかねないとも述べた[20]。
勝者の攻撃の手法
勝者のKillaBoiはGitHubのREADMEで、競技で使ったリクエストの列を、Pythonの標準ライブラリだけを使う単一のファイルで再現したと説明した[14]。READMEの要約では、小さなmultipartのアップロードでPHPにメモリを大量に使わせ、セッションのupload-progressの解析の途中でメモリ不足を起こさせると、再利用されるワーカーに古い状態が残る[14]。ヒープとコードのアドレスはセッションのcookieから読み取り、後処理には偽の構造体を使ってPHPのsystemの処理(zif_system)を呼ばせている[14]。実行ごとのHTTPリクエストは最大20で、ループも再試行もしない[14]。
READMEの記述はライブの競技ではなくDockerのラボに対するもので、ラボではAlpine上のPHP 8.4.26で動くCLIサーバーの前段にnginxを置いている[14]。オフセットはこの組み込みのCLIサーバーの構成に合わせてあり、DebianのPHP 8.4.26のfpmの構成は同じ版を名乗ってもバイナリの配置が違うため、実行はコードの漏えいの段階で止まる[14]。
勝者のREADMEでは、勝った実行で、以前の版の実行ツールが健全なPHP 8.4.26のページと2段の漏えいを記録した[14]。最後のPOSTへの応答の本文は204バイトで、PHPのfatalエラーに続いてチェックサムの正しいWIFが1つ入っていた[14]。元の実行は送ったHTTPリクエストの全体と応答ヘッダーを記録しておらず、リクエストは後から組み立て直した[14]。リモートのPHPのELFとprint-flagのバイナリは取得せず、実行させただけだった[14]。
Cointelegraphによると、Wordfenceの創業者のMark Maunderは、ある解説を、PHP2Shellの悪用の難しさを示す最良の説明だと評した[19]。Maunderは、作者が精密なメモリ破損の条件を起こし、内部のメモリのアドレスを漏らし、ASLRを回避する必要があったと述べた[19]。PHPの内部のメモリ構造の解析、実行を乗っ取る構造の偽造、PHPのビルドの違い・ワーカーの挙動・タイミングへの対処も挙げた[19]。
勝者が得た鍵の種類
主催者は10月25日のHacker Newsの告知で、資金の入ったアドレスのWIFではなく、ウォレットの枝(wallet-branch)のWIFをサーバーに置いていたと説明した[6]。勝者は、その数時間前にこのスレッドに秘密鍵の末尾3文字を書き込んでいた[6]。主催者はブログで、今後同じ種類の競技を開くなら、個別の秘密鍵ではなくウォレット全体の復元鍵をフラグにするだろうとした[7]。
時系列
| 日付 | 主体 | 内容 | 資料 |
|---|---|---|---|
| 2026年 | The PHP Group | 8.5.12・8.4.27・8.3.36・8.2.35で、未認証の遠隔コード実行に至りうる重大な脆弱性2件を修正したと告知した〔注1〕 | [10] |
| 2026年 | 主催者 | 競技のタイマーを始め、Hacker Newsに「Show HN: Steal My Bitcoin」を投稿した | [7] |
| 2026年 | - | 競技の開始後で最初のPHPのSIGSEGVが記録され、php-version.phpの追加前の版ではその後も7回起きた | [7] |
| 2026年 | 主催者 | PHPの版とUTCの時刻を返すphp-version.phpを追加した〔注2〕 | [7] |
| 2026年 | 主催者 | message=pingにpongを返すPOSTのエンドポイントping.phpを追加した | [7] |
| 2026年 | - | 勝者に結び付くprint-flagの実行にPHPのプロセスが成功し、ping.phpは攻撃の連鎖に使われなかった | [7] |
| 2026年 | 勝者 | サーバー上の鍵に対して賞金のアドレスが誤っていないかを、メールで主催者に尋ねた | [7] |
| 2026年 | 主催者 | 勝者の主張をサーバーのログと照合し、フラグがサーバー上のものと完全に一致し、成功した実行の前後のWebの通信のログとも合うことを確かめた | [7] |
| 2026年 | 主催者 | Hacker Newsで解答者が出たと告知した | [6] |
| 2026年 | 主催者 | 勝者の最終的な解説を確認し、ウォレットの中身を直接送った〔注3〕 | [7] |
| 2026年 | 主催者 | stealmybitcoin.comの運営の観察をブログに公開した | [7] |
影響範囲
主催者のブログによると、投稿から1時間以内にリンクはHacker Newsのトップページに載り、ほぼ丸一日とどまった[7]。VPSは負荷でSSHの接続を保てなくなり、主催者はVPSの資源を増やした[7]。
VPSの事業者は、DDoS攻撃を受けている疑いで1回、CPUの使用が過剰だとして1回、サイトを一時停止した[7]。個々のPHPのワーカーは、高い負荷や一部成功したメモリへの攻撃などで止まり続け、主催者は定期的なリセットとヘルスチェックで比較的安定させた[7]。リンクがHacker Newsのトップページから外れると、通信は落ち着いた[7]。
主催者は、特定のPHPのクラッシュとprint-flagの周辺のログは期間を通じてほぼそろっていた一方、Webリクエストのログは競技の約1,600分のうち約600分しか残っていないと説明した[7]。
| 項目 | 値 | 資料 |
|---|---|---|
| 競技に実質的に関わったユニークIPアドレス | 約20,000 | [7] |
| サイトを訪れた送信元IP | 約120,000 | [7] |
| サーバーが受けたHTTPリクエスト | 1,300万件超 | [7] |
サーバーはピーク時に毎分18,000件を超えるリクエストを受けた[7]。主催者は、欠けたデータから外挿する統計的に信頼できる方法は無いが、数万人が挑んだとは言えるとした[7]。
主催者は、約26時間に約2,075件のPHPのSIGSEGVを観測し、ほかのバグでも起こりうるが、悪用に近い試行とおおまかに相関する可能性があるとした[7]。print-flagを起動できたIPは2つで、サーバーからデータを持ち出せたのは1人だった[7]。
寄付で賞金のウォレットは増えたと主催者は書いた[7]。mempool.spaceの記録では、賞金のアドレスへの入金は2026年10月24日〜25日の7件の取引だった[17]。Bitcoin.com Newsは10月25日の記事で、約2,000ドルの賞金が17時間以上たっても回収されていないと報じた[18]。
競技サイトは、ビットコインが19.28時間(19時間17分)で盗まれたと表示している[2]。その勝利で懸かっていた額として、同じサイトに載っているのは0.02511679 BTC(2,021.22ドル)である[2]。
対応と現状
主催者は10月25日の告知で、print-flagを実行してデータを持ち出せた例はこの1件が最初で唯一であり、サーバーのログもそれを裏付けているとした[6]。サーバー上にあるWIFの値を連絡者が知っていることを理由に、これを解答として扱うとも書いた[6]。
主催者のブログによると、勝者がメールで証拠として出したのは、サーバー上の鍵の全文とそのハッシュ・悪用した正確な時刻・使ったIPアドレス・使ったペイロード・エクスプロイトを開発したときのAIとのやり取り・解説の全文だった[7]。主催者はログで経緯をたどり、悪用の時刻をprint-flagのログと秒単位で照合した[7]。
競技のソースは、大半がCodexによるもので、主催者が告知への追記でGitHubに公開した[6]。ソースのREADMEには、公開した写しから本番のフラグ・ウォレットの秘密鍵・署名の秘密鍵・SSHの認証情報・TLSの資料・参加者のログを除いたとある[8]。
主催者の2026年10月30日のブログでは、1つ目の問いへの答えは「Yes. Absolutely.」で、勝者のエクスプロイトはサーバーのPHPの構成を狙って特別に作られていた[7]。2つ目の問いへの答えは「Not yet.」だった[7]。勝者はphp-version.phpの追加から約3時間で解き、その後も競技を止めるまでの約9時間に、数千人がflagのバイナリを起動できなかった[7]。
主催者は、競技を始めたときの懐疑的な見方は誤りだったとし、PHP2Shellは悪用できる脆弱性で、十分に動機のある攻撃者はAIの助けでWebサイトに侵入できると書いた[7]。PHPのサイトの運用者にはPHP2Shellのパッチの適用を求め、今後数か月で汎用の攻撃の連鎖が増えると予想した[7]。未熟な攻撃者が上位のLLMと難しいCVEを使って、信頼できる攻撃の道具を作れる段階にはまだないとも書いた[7]。
未公表の事項
- 勝者の手法とCVE-2026-109618・CVE-2026-109619との対応
- 勝者のエクスプロイトへのNginxの寄与(主催者はVPSの構築の手引きで、勝者の手法が再現されるまで未確認とした[9])
- print-flagを起動したもう1つのIPの持ち主と結果
- 勝者がエクスプロイトの開発でAIを使った範囲
- 修正版のPHPに対する勝者の手法の成否
注
- 〔注1〕The PHP GroupはChangeLogで、8.4.27の日付を2026年10月22日とした[11]。GIGAZINEは、PHP2Shellの緊急アップデートの公開を日本時間の10月21日23時頃と報じた[21]。
- 〔注2〕主催者のHacker Newsの書き込みでは、追加は「13:00-ish UTC」だった[5]。GIGAZINEは日本時間の22時頃と報じ[21]、LiveOverflowは実験の開始から18〜19時間ごろとした[15]。
- 〔注3〕mempool.spaceの記録では、賞金のアドレスからの送金は、ブロック時刻が22時59分33秒の取引と23時17分46秒の取引に分かれた[17]。
出典
当事者
- [1]James Pavur『Steal My Bitcoin』(公開日不明、保存記録のみ) 保存記録
- [2]James Pavur『Challenge won · Steal my Bitcoin』(公開日不明、2026年11月1日閲覧)
- [3]James Pavur『Steal My Bitcoin』(2026年10月26日公開)
- [4]James Pavur『Terms of participation』(2026年10月26日公開)
- [5]James Pavur『Show HN: Steal My Bitcoin』(2026年10月24日公開)
- [6]James Pavur『Update 4: There's a solve!!!』(2026年10月25日公開)
- [7]James Pavur『Observations from Running stealmybitcoin.com』(2026年10月30日公開)
- [8]James Pavur『Steal My Bitcoin — open source lab』(公開日不明、2026年11月1日閲覧)
- [9]James Pavur『Steal My Bitcoin VPS guide』(公開日不明、2026年11月1日閲覧)
関係組織
- [10]The PHP Group『Security advisory: Critical remote code execution vulnerabilities, update now』(2026年10月21日公開)
- [11]The PHP Group『PHP 8 ChangeLog — Version 8.4.27』(2026年10月22日公開)
公的機関
- [12]CVE Program『CVE-2026-109618: RCE via OOM corruption』(2026年10月21日公開)
- [13]CVE Program『CVE-2026-109619: RCE via stale global state』(2026年10月21日公開)
調査・観測
- [14]KillaBoi『Steal My Bitcoin CTF proof of concept』(公開日不明、2026年11月1日閲覧)
- [15]LiveOverflow『OP confirmed that the server was initially serving only an index.html.』(2026年10月25日公開)
- [16]LiveOverflow『If it's nginx + fpm + "empty" index.php, it's a meme and not exploitable.』(2026年10月24日公開)
- [17]The Mempool Open Source Project『bc1qlnu50y4zm0nwxkckxu09thn5xdcz8aw6t3cxqy』(公開日不明、2026年11月1日閲覧)
報道機関
- [18]Saint Bitts LLC『Website Dares Hackers to Steal Bitcoin as the Clock Keeps Ticking』(2026年10月25日公開、2026年10月26日更新)
- [19]Cointelegraph『AI Agents Rescue ETH's Glamsterdam Fork, 'Steal My Bitcoin' Site: Hodler's Digest』(2026年10月25日公開、2026年10月27日更新)
- [20]CryptoSlate『Bitcoin hacking challenge finally falls as researcher proves critical PHP flaw is exploitable』(2026年10月26日公開)
- [21]GIGAZINE『PHPの更新を適用していないサイトからビットコインを盗む賞金付きハッキングチャレンジが開催され19時間で突破される』(2026年10月26日公開)
更新記録
- 2026年11月1日:公開した。
- 2026年11月3日:題とリードの文の言い回しを改め、経緯・勝者の攻撃の手法・影響範囲・対応と現状・注の言い回しも改めた(事実と出典は変えていない)。
