Temi


Debolezze


  1. Il binario /home/flag01/flag01 ha privilegi di esecuzione ****ingiustificatamente elevati. (Considerando per fini didattici flag01 un utente privilegiato). → minimo privilegio
  2. Il binario /bin/sh non abbassa i propri privilegi di esecuzione. → minimo privilegio
  3. Uso indiretto dell’input tramite la variabile d’ambiente PATHcontrollo input

🐲 Strategia di attacco


1. Si analizzano i permessi dei file

Nella cartella /home/flag01 è presente il file binario flag01. Analizzando i permessi, notiamo che il bit SETUID è attivo e che l’utente owner è flag01.

ls -l /home/flag01

-rwsr-x--- 1 flag01 level01 7322 2011-11-20 21:22 flag01

Dal codice sorgente possiamo vedere che avviene un’elevazione permanente dei privilegi (id effettivo e id salvato impostati all’id effettivo) → irreversibile.

gid_t gid;
uid_t uid;
gid = getegid();
uid = geteuid();

setresgid(gid, gid, gid);
setresuid(uid, uid, uid);

Dall’intersezione di queste 2 informazioni, sappiamo che l’id effettivo recuperato dallo script è quello dell’utente owner del file, in quanto il bit SETUID è attivo, ed esso è proprio flag01.

2. Analisi dei canali di input

Tracciamo l’esecuzione dello script:

ltrace ./flag01

Si nota che:

type -a echo

echo is a shell builtin
echo is /bin/echo

Con il comando sopra, scopriamo che esistono due varianti del comando echo:

Sappiamo che il comando echo è eseguito tramite il comando env nel nostro script. env consente di eseguire un comando esterno in un ambiente UNIX modificato (possiamo verificarlo con man env). Per queste ragioni, la variante utilizzata sarà il comando esterno /bin/echo. Come possiamo dunque modificare l’ambiente UNIX per trarne un vantaggio?

Una variabile d’ambiente interessante è PATH che contiene i possibili percorsi di ricerca dei binari.

3. Sfruttamento della debolezza

Debolezza: Esecuzione a privilegi elevati per tutto il tempo, e chiamata di sistema con variabili d’ambiente.

Per sfruttare questa debolezza, basterà creare un nuovo path, ad esempio in /tmp/ e creare un finto script echo al suo interno. Tale script potrà eseguire qualsivoglia codice malizioso con i privilegi di flag01. Nel nostro caso, copiamo l’eseguibile /bin/getflag all’interno di /tmp e gli assegnamo il permesso di esecuzione sull’utente.

cp /bin/getflag /tmp/echo
chmod u+x /tmp/echo

A questo punto basterà prependere /tmp alla variabile PATH.

export PATH=/tmp:$PATH

A questo punto eseguendo flag01 verrà in realtà eseguito /bin/getflag con i privilegi di flag01.

Questa è, a tutti gli effetti, una iniezione di comando effettuata tramite l’iniezione di un percorso

👼 Mitigazione debolezze


La vulnerabilità è un AND logico di tre debolezze. Inibendo una delle tre debolezze, si annulla la vulnerabilità. È preferibile inibirle tutte e tre.

Mitigazione #1

A. Binario flag01 con privilegi ingiustificatamente elevati

💡 A carico dell’amministratore di sistema

Si spegne il bit SETUID nel file eseguibile flag01.

chmod u-s /home/flag01/flag01

L’exploit non funziona più.

B. Privilege drop-restore

Se il binario non consente di spegnere il bit SETUID perché necessario ai fini della sua esecuzione è necessario:

A questo scopo si eliminano le seguenti righe:

setresgid(gid, gid, gid);
setresuid(uid, uid, uid);
  1. setresgid() è inutile in quanto il file non è SETGID
  2. La rimozione della seconda istruzione consente di mantenere l’id salvato a quello dell’utente effettivo, e quindi di alzarli/abbassarli temporaneamente.

È dunque necessario abbassare i privilegi prima della chiamata system.

uid_t uid;
uid = getuid();
setresuid(-1, uid, -1);

In questo modo la chiamata system avverrà con i soli privilegi di level01.

Mitigazione #2

Binario /bin/sh non abbassa i propri privilegi di esecuzione

Per mitigare la seconda debolezza è necessario modificare il comportamento di /bin/sh.

Si modicano nel file /etc/apt/sources.list tutte le occorrenze di http://us.archive.ubuntu.com/ubuntu/ con http://old-releases.ubuntu.com/ubuntu/.

sed -i 's/http:\\/\\/us.archive.ubuntu.com\\/ubuntu\\//http:\\/\\/old-releases.ubuntu.com\\/ubuntu\\//g' /etc/apt/sources.list

Dopodiché si sincronizzano in locale i metadati del repository:

apt-get update

A questo punto si può scaricare il pacchetto sorgente di BASH e installare le sue dipendenze di build:

apt-get source bash
apt-get build-dep bash

Si rimuove la patch privmode.dpatch:

cd /path/to/bash-4.2/debian/patches
rm privmode.dpatch

Rimuovere tutte le occorrenze di privmode in /path/to/bash-4.2/debian/rules .

Dopodiché si compila il pacchetto binario, senza eseguire gli unit test e si installano i pacchetti binari prodotto:

cd /path/to/bash-4.2 
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -us -uc -b
cd /path/to/bash-4.2/.. dpkg -i bash-4.2*deb

A questo punto si possono togliere tutti gli statement dal file C, tranne la chiamata a system. BASH potrà così liberamente rilasciare i privilegi.

Mitigazione #3

Binario flag01 usa indirettamente input tramite la variabile PATH

Il binario usa indirettamente l’input tramite la variabile d’ambiente PATH, tramite il comando env. Tale variabile non è controllata prima dell’esecuzione di system(). Di conseguenza si può iniettare un comando arbitrario al posto di echo.

Per renderlo sicuro, è necessario sanitizzare l’input, con le fasi viste:

  1. Filtro → Si imposta nel codice un percorso standard, eliminando eventuali iniezioni nella variabile d’ambiente. Per farlo si usa la funzione putenv() che permette di impostare uno specifico valore per una variabile d’ambiente.
  2. Validazione → Non necessaria in quanto abbiamo impostato la variabile nel codice e non è stata fatta immettere dall’utente.
putenv(“PATH=/bin:/sbin:/usr/bin:/usr/sbin”);

L’attacco non è più possibile.