Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
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.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
copy-fail-c — Porting in C multipiattaforma del Copy Fail Linux LPE (CVE-2026-31431). Divulgato il 2026-04-29 da Theori / Xint. | Kitploit
Strumenti/GitHubGitHub/tgies/copy-fail-c
Escalation di PrivilegiFramework di ExploitAnalisi delle VulnerabilitàExploitPaper e RicercaApprendimento e FormazioneSviluppo PayloadBinary Exploitation
GitHubtgies/copy-fail-c

copy-fail-c

Porting in C multipiattaforma del Copy Fail Linux LPE (CVE-2026-31431). Divulgato il 2026-04-29 da Theori / Xint.

Vedi Repository
4401211 mese faRevisionato da Kitploit

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

Copy Fail (CVE-2026-31431) - Porting C

Inglese (en) ∙ Giapponese (ja) ∙ Cinese semplificato (zh-cn) ∙ Coreano (ko) ∙ Russo (ru)

Una reimplementazione C multipiattaforma dell'LPE Linux Copy Fail (CVE-2026-31431), divulgato il 29-04-2026 da Theori / Xint. Consulta il writeup canonico su copy.fail per la descrizione completa della vulnerabilità, la cronologia e il processo di scoperta di Theori.

Il proof-of-concept rilasciato pubblicamente è uno script Python di 732 byte. Questo porting C dimostra che lo stesso exploit può essere espresso come C portabile compilabile per qualsiasi architettura supportata da nolibc, senza blob hex per architettura o assembly inline nel codice sorgente del progetto stesso.

Autore di questo porting: Tony Gies [email protected]. Scoperta e divulgazione originale: Theori / Xint.

Layout del repository

root@kitploit:~
copy-fail-c/
├── exploit.c           il dropper (variante mutazione binaria)
├── exploit-passwd.c    il dropper (variante /etc/passwd UID-flip)
├── vulnerable.c        verificatore di vulnerabilità non distruttivo
├── payload.c           il corpo che viene rilasciato (setgid+setuid+execve sh)
├── utils.c, utils.h    primitiva condivisa di mutazione della cache di pagina AF_ALG/splice
├── Makefile            orchestrazione della build
├── nolibc/             venduto da torvalds/linux tools/include/nolibc
└── README.md           questo file

Dopo make:

root@kitploit:~
├── payload             piccolo ELF statico, incorporato nel dropper come byte
├── payload.o           payload racchiuso come .o rilocabile da `ld -r -b binary`
├── exploit             dropper, variante mutazione binaria
├── exploit-passwd      dropper, variante /etc/passwd UID-flip
└── vulnerable          verificatore di vulnerabilità non distruttivo

exploit.c apre il binario target in sola lettura, quindi per ogni finestra di 4 byte del payload incorporato esegue un fittizio decifratura AEAD attraverso AF_ALG il cui input ciphertext è fornito tramite splice() dalle pagine della cache di pagina del target. L'ottimizzazione in-place del template authencesn tratta le pagine splice'd sia come input ciphertext che come destinazione plaintext, quindi la decifratura (fallita) ha già sovrascritto la pagina della cache di pagina quando la verifica di autenticazione rifiuta la richiesta. Dopo 4 * N iterazioni l'immagine cache del target è stata sostituita byte per byte con il payload. esecve() del target carica le pagine mutate; l'inode su disco è ancora setuid root, quindi il kernel concede i privilegi di root ed esegue il payload.

payload.c è C portabile semplice: setgid(0); setuid(0); execve("/bin/sh", ...). nolibc fornisce _start, il meccanismo delle syscall e la gestione dei registri per-arch.

Una seconda variante, exploit-passwd.c, muta quattro byte della cache di pagina di /etc/passwd invece dell'immagine di un binario setuid. Non necessita di payload incorporato e funziona su sistemi in cui la via di mutazione binaria è bloccata, ma la sua superficie di incasso è molto più limitata.

vulnerable.c non è un exploit. Crea un testfile locale contenente la stringa init, quindi esegue la stessa primitiva patch_chunk() contro la cache di pagina di quel file per sovrascrivere i byte con vulnerable. Se i contenuti letti corrispondono, il kernel in esecuzione è nella finestra per CVE-2026-31431. L'inode su disco non viene mai modificato; testfile viene rimosso all'uscita; la mutazione della cache di pagina svanisce con esso. Viene eseguito senza privilegi. Esce con 100 se vulnerabile, 0 se la primitiva è stata eseguita ma la mutazione non ha avuto effetto, 2 se la famiglia di socket AF_ALG o il template authencesn non sono disponibili quindi lo stato della patch non può essere determinato, e 1 per altri errori di runtime.

Build

Predefinita (nativa host-arch):

root@kitploit:~
make

Cross-compila per aarch64 (o qualsiasi altra architettura Linux per cui è installato un cross-toolchain):

root@kitploit:~
make CC=aarch64-linux-gnu-gcc LD=aarch64-linux-gnu-ld

Architetture supportate dal nolibc venduto (secondo upstream): x86_64, i386, arm, aarch64, riscv32/64, mips, ppc, s390x, loongarch, m68k, sh, sparc. nolibc dispaccia sulle macro arch del compilatore, quindi scegliere il CC/LD corretto è sufficiente.

Necessario per compilare:

  • un compilatore C (cc, gcc, o qualsiasi variante cross)
  • un linker che supporti ld -r -b binary (binutils ld e lld lo fanno entrambi)
  • intestazioni UAPI del kernel che forniscono linux/if_alg.h e <asm/unistd.h> (Debian/Ubuntu: linux-libc-dev; varianti cross: solitamente incluse dal pacchetto cross-toolchain)

Set di intestazioni precedenti a Linux 5.6 sono antecedenti a __kernel_old_time_t e struct __kernel_old_timespec, che il nolibc venduto utilizza. compat.h (force-incluso nella build del payload) li fornisce quando assenti, quindi un linux-libc-dev più vecchio compila comunque. È un no-op su intestazioni 5.6+.

Non ci sono dipendenze da librerie esterne. Il payload è compilato freestanding contro nolibc; il dropper si collega alla libc host solo per fprintf e perror.

Scelte architetturali

Alcune piccole funzionalità del toolchain supportano la maggior parte del peso nel mantenere il codice portabile e il payload piccolo.

nolibc

nolibc/ è la minuscola sostituzione header-only della libc del kernel, venduta da torvalds/linux tools/include/nolibc/. Fornisce _start, una macro syscall() portabile e wrapper di syscall inline, con le convenzioni dei registri per-arch codificate in nolibc/arch-*.h. Compilare il payload con -nostdlib -static -ffreestanding -Inolibc produce un piccolo ELF statico che chiama direttamente il kernel senza trascinare l'avvio di glibc, l'inizializzazione TLS o la strumentazione di stack-canary. Risultato una volta impacchettato e privato delle sezioni (entrambi sotto): ~720 byte su x86_64, ~1.2 KB su aarch64, contro ~17 KB per lo stesso payload.c linkato contro musl-static o ~700 KB contro glibc-static.

ld -r -b binary per l'incorporamento

Il Makefile trasforma il payload ELF costruito in payload.o tramite ld -r -b binary -o payload.o payload. Il linker emette i byte di input verbatim come la sezione dati di un file oggetto rilocabile e sintetizza tre simboli dal nome del file di input:

root@kitploit:~
_binary_payload_start    indirizzo del primo byte del payload
_binary_payload_end      indirizzo dopo l'ultimo byte del payload
_binary_payload_size     simbolo assoluto il cui valore è la dimensione in byte

exploit.c dichiara i primi due come extern const unsigned char[] e calcola la dimensione come _binary_payload_end - _binary_payload_start.

-Wl,-N più max-page-size stretto

Il payload è linkato staticamente con -Wl,-N -Wl,-z,max-page-size=0x10, che collassa .text/.rodata/.data in un unico segmento LOAD con allineamento file di 16 byte invece dell'impostazione predefinita di 4 KB per segmento allineato alla pagina del kernel. Questo produce un avviso "RWX permissions" da ld, che è solo informativo - la protezione della memoria runtime del payload non ha importanza per il suo programma monouso. Senza questo flag, lo stesso codice si linka a ~13 KB su x86_64 (principalmente padding zero inter-segmento); con esso, ~1.3 KB prima della rimozione dell'intestazione di sezione sottostante.

Rimozione delle intestazioni di sezione

Dopo il linking, objcopy --strip-section-headers rimuove la tabella delle intestazioni di sezione del payload e .shstrtab. Il caricatore ELF del kernel mappa un programma dai suoi soli program headers, quindi quei byte non vengono mai caricati a runtime, e poiché payload è incorporato verbatim, essi gonfiano anche il drop e il conteggio delle iterazioni di patch_chunk. Rimuoverli porta il payload x86_64 da ~1.3 KB a 720 byte (322 iterazioni di quattro byte ridotte a 180). Due flag al momento del link rasano il resto: -Wl,--build-id=none elimina la nota build-id, e -fcf-protection=none elimina la nota CET x86 dove il compilatore la supporta.

Lo strip necessita di binutils >= 2.40. Le build cross passano l'objcopy del target tramite OBJCOPY= (es. OBJCOPY=aarch64-linux-gnu-objcopy); quando objcopy non può farlo, la build stampa una nota e mantiene un payload valido più grande.

Varianti e fattibilità dell'incasso

Questo repository fornisce due varianti dell'exploit che condividono la primitiva di mutazione della cache di pagina AF_ALG/splice ma incassano in esecuzione root in modo diverso. I loro profili di affidabilità non sono equivalenti, e la differenza conta quando si ragiona su modelli di minaccia reali.

Variante mutazione binaria (exploit)

Muta la cache di pagina di un binario setuid target con i byte del payload incorporato, quindi esegue il binario. Il kernel concede i privilegi di root dal bit setuid intatto su disco del binario, carica l'immagine corrotta in memoria, ed esegue il payload.

Funziona ovunque l'attaccante possa open(target, O_RDONLY) per qualsiasi binario setuid di root sul sistema. Più o meno sconfitto da ambienti che bloccano i binari setuid dietro directory a lettura ristretta e da progetti di sistema senza setuid.

Variante /etc/passwd UID-flip (exploit-passwd)

Muta quattro byte della cache di pagina di /etc/passwd per impostare il campo UID dell'utente corrente a "0000". /etc/passwd è leggibile da tutti su ogni sistema Linux standard, quindi la mutazione è universale. Tradurla in esecuzione root dipende da qualche processo lato root che risolve l'utente tramite getpwnam/getpwuid e agisce sull'uid risolto senza cross-validazione. Molti consumatori di questo tipo esistono; molti di loro controllano in modo difensivo la coerenza con la vista del kernel dell'uid chiamante o con la proprietà del file su disco, rompendo l'incasso.

Matrice di fattibilità dell'incasso

Pivot dopo il fallimento di su

exploit-passwd esegue su <user> dopo la mutazione, come incasso più semplice possibile. Funziona contro su di util-linux ma fallisce contro su di shadow-utils con "Impossibile determinare il tuo nome utente." La mutazione della cache di pagina è ancora in atto a quel punto, e il pivot verso qualsiasi altro incasso (es. utilizzare un demone che risolve gli utenti tramite getpwnam senza cross-validazione) è possibile a quel punto. Esegui echo 3 > /proc/sys/vm/drop_caches come root per pulire la cache di pagina corrotta quando hai finito di testare.

Kernel affetti

root@kitploit:~
pavimento: torvalds/linux 72548b093ee3   Agosto 2017, v4.14
                                          (Rielaborazione iov_iter di AF_ALG che
                                          ha introdotto la primitiva di scrittura
                                          sulle pagine file tramite splice nello
                                          scatterlist AEAD)

soffitto:  torvalds/linux a664bf3d603d   Aprile 2026, mainline
                                          (Ripristina l'ottimizzazione in-place
                                          algif_aead del 2017; separa gli scatterlist
                                          di origine e destinazione in modo che le
                                          pagine della cache di pagina non possano più
                                          essere una destinazione crypto scrivibile)

In mezzo: ogni kernel di distribuzione principale che non ha backportato la correzione. Ubuntu, RHEL, SUSE, Amazon Linux e Debian sono stati tutti confermati vulnerabili nei loro kernel di immagini cloud standard al momento della divulgazione. I backport a livello di distribuzione hanno iniziato a essere rilasciati intorno al 29-04-2026 insieme alla divulgazione pubblica. Per verificare se un kernel target è nella finestra, controlla se a664bf3d603d (o il suo backport specifico per distribuzione) è presente nel git log del kernel o nel changelog della distribuzione.

Supporto commerciale

Per revisione di sicurezza a pagamento, lavoro di porting personalizzato o avvisi di sicurezza privati, contatta l'autore tramite la sua società di consulenza, Crash United, LLC.

Contatto: [email protected] · https://crashunited.com
GitHub: @tgies · X/Twitter: @me_irl

Licenza e crediti

Scoperta e divulgazione originale di CVE-2026-31431: Theori / Xint. Writeup pubblico: https://copy.fail/.

Questo porting C: Tony Gies [email protected]

nolibc/: venduto dall'albero del kernel Linux, con doppia licenza LGPL-2.1-or-later O MIT (vedi nolibc/nolibc.h e le intestazioni SPDX dei singoli file).

Il dropper e le fonti del payload in questo repository sono rilasciati sotto gli stessi termini di doppia licenza LGPL-2.1-or-later O MIT dell'albero nolibc da cui dipendono, per mantenere la compatibilità di licenza in modo banale per chiunque venda questa intera directory nel proprio lavoro.

L'exploit e il payload sono pubblicati per scopi di ricerca sulla sicurezza e rilevamento difensivo. L'uso contro sistemi che non possiedi o per cui non hai esplicita autorizzazione al test è un problema tuo, non dell'autore.

Scarica lo strumento
IncassoSetup pre-root necessarioNote
Lancio sessione WSL2NoIl setuid(getpwnam(default_user)->pw_uid) per sessione di WSL non esegue alcuna validazione. Funziona pulitamente.
su di util-linuxNoGestione permissiva dell'identità del chiamante.
su di shadow-utilsSìIl controllo getpwuid(getuid()) dell'identità del chiamante fallisce perché la mutazione rimuove l'uid reale.
sshd (StrictModes yes predefinito)Sì (disabilitare StrictModes)StrictModes richiede che la home directory sia di proprietà di root o di pw->pw_uid. La mutazione imposta pw_uid=0; il proprietario su disco rimane l'uid originale; la discrepanza rifiuta l'autenticazione.
Consegna locale MTA (postfix, exim, ecc.)VariabileDipende dalla validazione dei permessi home dell'MDA. Testare per MTA specifico.