Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

FeedContattoPrivacy© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
StealMyBitcoin-PoC — Un rilascio pubblico della sfida Steal My Bitcoin | Kitploit
Strumenti/GitHubGitHub/killaboi/stealmybitcoin-poc
Memory ForensicsAnalisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebCTFSviluppo PayloadBinary ExploitationLab e Pratica
GitHubkillaboi/stealmybitcoin-poc

StealMyBitcoin-PoC

Un rilascio pubblico della sfida Steal My Bitcoin

Vedi Repository
21641531 giorno faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

sponsorizzato con ❤️ da hextree.io

Steal My Bitcoin CTF proof of concept

Un callback PHP live contro la challenge Steal My Bitcoin, dall'inizio alla fine, in un singolo file Python con sola libreria standard.

Python Dependencies Target Lab

Questo README spiega stealmybitcoin_poc.py, una riproduzione Python in un singolo file della sequenza di richieste usata nella mia esecuzione della CTF Steal My Bitcoin. Usa solo la libreria standard di Python. Lo script costruisce da sé le richieste, verifica ogni leak prima di proseguire e registra i byte HTTP di una nuova esecuzione.

Probabilmente si può fare più facilmente senza tutta la roba extra di debug e, come ho scoperto nel mio video su John Hammond riguardo alla Steam Local Privilege Escalation, potresti probabilmente ripulire questo brutto PoC.

[!NOTE] ⚠️ Onestamente, per favore ripuliscilo o crea la tua versione migliore che non sia accartocciata da Sol. ⚠️

Tutto quanto segue è scritto per il laboratorio Docker, non per la challenge live. Il laboratorio è un server CLI Alpine PHP 8.4.26 locale dietro nginx, che è la stessa build e lo stesso modello di worker su cui sono stati calibrati gli offset. Avvialo in un minuto e l'intera catena gira end to end sulla tua macchina. L'esecuzione live che ha effettivamente risolto la challenge è conservata come nota storica in fondo.

  stage                 what goes out                        what comes back
  ─────────────────────────────────────────────────────────────────────────────
  0  health      GET /php-version.php                 ->  PHP 8.4.26 confirmed
  1  heap leak   249,042 B producer + 8 x   6,672 B   ->  256 B cookie
                 (OOM poisons a worker)                   └─ Zend chunk base
  2  code leak   251,557 B producer + 8 x  92,388 B   ->   16 B cookie
                 (OOM poisons a worker)                   └─ zval_ptr_dtor
  3  callback    368,812 B POST                       ->  forged HashTable runs
                 (fake HashTable + command)               └─ zif_system(cmd)
  ─────────────────────────────────────────────────────────────────────────────
  20 HTTP requests at most. No looping, no retries.

La versione breve

  1. Un piccolo upload multipart fa consumare a PHP molta più memoria di quanto suggerisca la dimensione sulla rete.
  2. Quando esaurisce la memoria a metà dell'analisi dell'avanzamento dell'upload della sessione, PHP lascia uno stato obsoleto in un worker che viene poi riutilizzato.
  3. Modellando correttamente le richieste successive, i byte fuoriescono attraverso i cookie di sessione. Li leggo come un indirizzo heap e un indirizzo di codice PHP.
  4. Con entrambi gli indirizzi, una richiesta finale inserisce una struttura PHP contraffatta dove la pulizia la troverà, e la pulizia chiama zif_system, il gestore di PHP per system.
  5. Quel comando rimanda indietro un nuovo marcatore di prova e un risultato print-flag sulla connessione ancora aperta.

Perché due indirizzi? Il sistema operativo randomizza in modo indipendente dove finiscono il codice e lo heap di PHP. La fuga dello heap dice allo script dove collocare la struttura contraffatta, la fuga del codice gli dice dove risiede effettivamente la funzione che vuole chiamare. Gli indirizzi di un worker precedente o di un'esecuzione precedente non sono sostituti sicuri, e ogni volta che ci ho provato il tentativo è semplicemente fallito.

Indice

  • Il laboratorio
  • Inizia da qui
  • Cosa fa ogni richiesta
    • 1. Come un piccolo producer raggiunge il limite di memoria
    • 2. Come viene recuperato l'indirizzo dello heap
    • 3. Come viene recuperato l'indirizzo del codice PHP
    • 4. Come la richiesta finale raggiunge system
  • Leggere il risultato
  • Quanto spesso funziona davvero
  • L'esecuzione dal vivo che l'ha risolto
  • Gergo, in breve
  • Ringraziamenti

Il laboratorio

Gli offset in questo PoC sono calibrati per Alpine PHP 8.4.26 in esecuzione con il server CLI integrato e quattro worker. Il laboratorio riproduce esattamente questo, dietro nginx, su loopback.

[!IMPORTANT] La build conta più della stringa di versione. Uno stack Debian php:8.4.26-fpm riporta lo stesso PHP/8.4.26 ma ha un layout del binario diverso, quindi l'impronta del puntatore al codice non corrisponderà mai e l'esecuzione si interrompe nella fase di fuga del codice. Usa l'immagine Alpine qui sotto.

Tre piccoli file. Mettili in una directory vuota:

public/php-version.php (l'endpoint di health, e l'unica pagina di cui il PoC ha bisogno)

<?php
header('Content-Type: text/plain');
echo 'PHP ', PHP_VERSION, "\n";
echo 'PID: ', getmypid(), "\n";

print-flag (sostituto del binario della challenge, deve essere eseguibile)

#!/bin/sh
printf '%s\n' 'LOCAL_DUMMY_WIF_NEVER_USE'

nginx.conf

events {}
http {
    server {
        listen 80;
        server_name _;
        location / {
            proxy_pass http://ctf-cross-php:8000;
            proxy_http_version 1.1;
            proxy_set_header Host $host;
        }
    }
}

Poi avvialo:

docker network create ctf-cross-net

docker run -d --name ctf-cross-php --network ctf-cross-net \
  --read-only --tmpfs /tmp:rw,size=32m,mode=1777 --memory 1g \
  -v "$PWD/public:/app:ro" \
  -v "$PWD/print-flag:/usr/local/bin/print-flag:ro" \
  -e PHP_CLI_SERVER_WORKERS=4 \
  php:8.4.26-fpm-alpine3.23 php -S 0.0.0.0:8000 -t /app

docker run -d --name ctf-cross-nginx --network ctf-cross-net \
  -p 127.0.0.1:18166:80 \
  -v "$PWD/nginx.conf:/etc/nginx/nginx.conf:ro" \
  nginx:1.27-alpine

Controllalo:

$ curl -s http://127.0.0.1:18166/php-version.php
PHP 8.4.26
PID: 1

Il PID varia a seconda di quale worker risponde, e va bene così. La riga della versione è la parte che il PoC controlla.

Smontalo con docker rm -f ctf-cross-nginx ctf-cross-php && docker network rm ctf-cross-net.

[!TIP] Su Windows, esegui quei comandi docker run da PowerShell, oppure sostituisci $PWD con un percorso completo di unità come C:/lab. In Git Bash $PWD si espande in un percorso MSYS come /tmp/..., che Docker Desktop risolve all'interno della propria VM. I bind mount creano quindi silenziosamente directory vuote dove dovrebbero trovarsi nginx.conf e print-flag, e i container si avviano in modo difettoso.

Un paio di note su quella ricetta. L'immagine è il tag fpm ma il container esegue php -S, quindi la SAPI è cli-server, che è quella su cui è stata misurata la calibrazione. PHP_CLI_SERVER_WORKERS=4 è ciò che dà alle fasi di leak più di un worker su cui gareggiare. Il mio harness di laboratorio passava anche --cap-add SYS_PTRACE --security-opt seccomp=unconfined così da poter collegare un tracer ai worker; il PoC stesso non lo fa mai, quindi sono stati omessi sopra.


Inizia da qui

Scarica lo strumento