Teoria


Quella vista nell’attacco di questo livello è una iniezione di libreria (library injection). Nel mondo Windows è conosciuta con il nome di DDL Injection. Le DLL Injection sono alla base di quasi tutti i meccanismi di esecuzione fraudolenta di codice arbitrario (spesso nascondendosi dietro binari innocenti).

Temi


Debolezze


🐲 Strategia di attacco


1. Analisi codice sorgente

Analizzando il codice sorgente del binario /home/flag13/flag13 si può notare che:

  1. Avviene un controllo sull’id reale dell’utente che ha eseguito il binario
    1. Se l’id non corrisponde a FAKEUID (1000) si esce con un messaggio di errore
    2. Altrimenti viene stampata la password dell’utente flag13

È anche possibile capirlo dal solo output del binario, che segnala che l’id dell’utente che ha eseguito al binario è diverso da 1000 (eccessiva verbosità output).

Possiamo dedurre quindi che si tratta di un debolissimo meccanismo di autenticazione, per due ragioni:

  1. È basato su un unico fattore
  2. Il fattore usato è di dominio pubblico (user ID UNIX)

In questo modo un attaccante conosce il fattore e può facilmente provare ad impersonificare l’utente con lo user ID richiesto per autenticarsi.

2. Sfruttamento della debolezza

Si tratta di un’iniezione, ma molto ben nascosta.

Si studia il sistema, partendo dalle variabili d’ambiente:

man environ

Dall’introduzione si scopre che:

<aside> 📑

LD_LIBRARY_PATH, LD_PRELOAD and other LD_ variables influence the behavior of the dynamic loader/linker.*

</aside>

In breve, alcune variabili d’ambiente possono influenzare il comportamento del linker dinamico.

Nella sezione BUGS è anche abbozzato un possibile attacco mediante sfruttamento proprio della variabile d’ambiente LD_LIBRARY_PATH.


Ma cos’è questo linker dinamico? Si interroga il manuale UNIX con la parola chiave linker.

apropos linker

Si ottengono alcune pagine proprio riguardanti dynamic linker/loader, che sono: ld-linux, ld-linux.so, ld.so, tutte nella sezione 8. (Che in realtà puntano tutti alla stessa pagina di manuale).

Si analizza la pagina di manuale:

man ld.so

Nella lista ENVIRON troviamo la spiegazione delle due variabili d’ambiente viste prima LD_LIBRARY_PATH e LD_PRELOAD. La seconda in particolare, contiene una lista di librerie condivise ELF separate da spazio, definite dall’utente, che saranno collegate prima di tutte le altre. Lo scopo è quello di fare override dinamicamente di funzioni in altre shared libraries, senza dover ricompilare i sorgenti.

<aside> 📑

LD_PRELOAD A whitespace-separated list of additional, user-specified, ELF shared libraries to be loaded before all others. This can be used to selectively override functions in other shared libraries.

</aside>

Può essere definita per un singolo comando o per una sessione di terminale:

LD_PRELOAD=/path/to/lib.so <command>
export LD_PRELOAD=/path/to/lib.so 

L’idea è quella di usare la variabile LD_PRELOAD per caricare in anticipo una libreria condivisa che implementa la funzione di controllo degli accessi del programma flag13getuid() (la libreria condivisa va scritta da zero e compilata).

Si scrive un programma getuid.c. L’idea è quella di fare ritornare sempre 1000. Molto semplice.

#include <unistd.h>
#include <sys/types.h>

uid_t getuid(void) {
  return 1000;
}

Per generare la libreria condivisa si usa gcc con le opzioni:

gcc -shared -fPIC -o getuid.so getuid.c

Si lancia di nuovo il binario precaricando la libreria getuid.so:

LD_PRELOAD=./getuid.so /home/flag13/flag13

L’attacco non va a buon fine. Cosa non ha funzionato?


Si studia più approfonditamente la pagine di manuale relativa a ld.so. Si scopre che per i binari SETUID/SETGID, solo le librerie nelle standard search directories che sono anche SETGID **saranno caricate.

<aside> 📑

LD_PRELOAD For setuid/setgid ELF binaries, only libraries in the standard search directories that are also setgid will be loaded.

</aside>

Quindi, se l’eseguibile è SETUID deve esserlo anche la libreria condivisa.

Dunque l’iniezione di una libreria funziona solo se il binario e la libreria condivisa hanno lo stesso tipo di privilegi:

Cosa si può fare:

cp /home/flag13/flag13 /home/level13
ls -l /home/level13

Il binario non ha più il bit SETUID.

Si esegue di nuovo il binario precaricando la libreria:

LD_PRELOAD=./getuid.so ./flag13

Si ottiene così il token dell’utente → Attacco riuscito.

👼 Mitigazione debolezze


Mitigazione #1