
Codice sorgente e file di configurazione relativi al nostro articolo su MISC96
Questo repository è un'aggiunta all'articolo pubblicato su MISC Magazine #96.
Siamo riusciti ad elevare i nostri privilegi in modo affidabile, sulla nostra macchina virtuale con SMEP/SMAP e KASLR abilitati. Va comunque notato che il sistema viene lasciato in uno stato instabile e che è molto probabile che si verifichi un oops.
Nella cartella configs/, troverai i file di configurazione per il kernel Linux
e Busybox, ciascuno leggermente diverso da quelli predefiniti.
La cartella binaries/ contiene tutti i binari precompilati di cui avrai bisogno
per riprodurre il nostro ambiente di test, come un intero rootfs pronto per essere utilizzato con
QEMU.
linux-stable è un sottomodulo git che punta a una revisione vulnerabile del kernel
Linux. Usa git submodule update --recursive per recuperarlo (se hai almeno
1 GB di spazio libero sul sistema...). Lo stesso vale per busybox.
Il nostro ambiente si basa su una macchina virtuale QEMU x86 con una cartella
condivisa con l'host tramite 9P. Una versione vulnerabile del kernel (ff33952e4d23) è
compilata insieme a una build collegata staticamente di Busybox.
La nostra configurazione è piuttosto semplice, poiché non abbiamo bisogno di supportare alcun tipo
di architettura o hardware esotico. È stata generata eseguendo make defconfig e sono state abilitate alcune funzionalità per supportare il networking di QEMU e la
condivisione di cartelle:
CONFIG_BLK_MQ_VIRTIO=y
CONFIG_MEMORY_BALLOON=y
CONFIG_BALLOON_COMPACTION=y
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
CONFIG_NET_9P_DEBUG=y
CONFIG_VIRTIO_BLK=y
CONFIG_VIRTIO_BLK_SCSI=y
CONFIG_VIRTIO_NET=y
CONFIG_HVC_DRIVER=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM_VIRTIO=y
CONFIG_VIRTIO=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_PCI_LEGACY=y
CONFIG_VIRTIO_BALLOON=y
CONFIG_VIRTIO_INPUT=y
CONFIG_VIRTIO_MMIO=y
CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
CONFIG_9P_FS=y
CONFIG_9P_FS_POSIX_ACL=y
CONFIG_9P_FS_SECURITY=y
Sono stati aggiunti anche script GDB e simboli di debug per facilitare lo sviluppo dei primi PoC:
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF4=y
CONFIG_GDB_SCRIPTS=y
Tieni presente che in questa versione, KASLR è abilitato per impostazione predefinita su x86. Poiché il
kernel viene mappato a indirizzi diversi dopo ogni riavvio, GDB non sarà in grado
di abbinare il file dei simboli ad esso. Hai quindi due opzioni: eseguire test
senza KASLR o passare l'indirizzo di base del kernel a symbol-file quando
carichi i simboli in GDB.
Dopo averlo compilato, troverai il bzImage in linux-stable/arch/x86/boot/bzImage.
Questo file è presente in binaries/bzImage e il nostro file di configurazione in
confifs/kernel.config. Per usarlo, devi solo copiarlo come .config
in linux-stable.
Abbiamo usato l'ultima versione stabile di Busybox, 1.28. L'unica impostazione da modificare è
CONFIG_STATIC, impostala su y. La compilazione non dovrebbe causare alcun problema.
Il nostro file di configurazione è disponibile in configs/busybox.config e un
binario compilato staticamente in binaries/busybox. Come per Linux, copialo
come .config nella cartella dei sorgenti di Busybox.
Busybox implementa già un processo init che tenterà di eseguire /etc/init.d/rcS.
Di solito, è fornito dalla tua distribuzione (potenzialmente con un nome diverso),
ma qui dovremo farlo da soli! Questo script creerà e monterà
diverse cartelle di sistema obbligatorie (proc, sys, dev), la nostra cartella condivisa con
l'host e ci farà accedere a una shell senza privilegi:
for i in $(seq 1 9); do mknod /dev/tty$i c 4 1; done
mknod -m 0666 /dev/null c 1 3
mknod -m 0660 /dev/ttyS0 c 4 64
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs none /dev
mkdir -p /mnt/share
mount -t 9p -o trans=virtio share /mnt/share/ -oversion=9p2000.L,posixacl,sync
chmod 777 /mnt/share/
export ENV=/etc/profile
setsid cttyhack setuidgid 1000 sh
umount /proc
umount /sys
umount /dev
poweroff -f
Il file /etc/profile non è obbligatorio, ma è utile durante i nostri test,
soprattutto quando l'exploit non era affidabile e ci sono voluti diversi tentativi per
ottenere i privilegi di root.
Il processo alla base della scrittura dell'exploit è abbastanza documentato in MISC 96: usiamo
unsafe_put_user per sondare la memoria fino a trovare l'indirizzo base dello heap.
Quindi, migliaia di chiamate a clone ci permettono di spruzzare numerose strutture
cred in memoria. Durante i nostri test, la loro posizione in memoria era molto più
"costante" rispetto all'uso di fork, poiché alloca meno strutture per il nuovo task.
Uscire dal processo figlio causerà un kernel oops, a causa di una richiesta di paging difettosa, questo deve essere gestito correttamente.
Se vuoi migliorare l'affidabilità di questo exploit o aggiungere documentazione, i contributi sono benvenuti! Potremmo anche aver commesso errori o imprecisioni su alcuni concetti, non esitare ad aprire una issue se pensi che qualcosa sia sbagliato.
Kernel Linux
Sfruttamento