hacking-contest

Hacking Contest: retroscena e backstage

Indice dei contenuti

Luca racconta il backstage del Seeweb Hacking Contest

Retroscena e backstage del contest Blackout Resurrection

 
Abbiamo deciso di raccontarvi qualche retroscena, curiosità e dettaglio tecnico, su come abbiamo implementato alcune fasi dell’ultimo Seeweb Hacking Contest. Grazie al vostro impegno, anche quest’edizione ha riscosso un certo successo.
 
Questo articolo, è quindi un modo per ringraziare tutti i partecipanti, molti dei quali una volta terminato il contest hanno pubblicato sui propri siti web le soluzioni alle sfide che Seeweb ha messo in campo.

L’iscrizione

Il sito web che conteneva il form per la registrazione, era ospitato su un nostro prodotto Shared Hosting.

L’intero processo è stato gestito in PHP, utilizzando reCAPTCHA per proteggere il servizio da attacchi da parte di bot.

Sfortunatamente, nella predecente edizione, molti utenti hanno tentato senza successo un brute force sul servizio SSH, soluzione poco elegante e piuttosto lenta, ma capace di monopolizzare le risorse della macchina.

Per prevenirlo, sul server è stata installata l’applicazione fail2ban, un software capace di monitorare questo tipo di minacce, ed intervenire proattivamente filtrando l’indirizzo IP dell’attacker.

Circuito di emergenza della Quality Cloud Farmaceutic

Per questa fase della gara, abbiamo utilizzato un server Easy Cloud dotato di 8Gb di RAM e 4 CPU.

Sulla porta TCP 65533, era accessibile pubblicamente un servizio ideato appositamente per il contest e sviluppato in linguaggio C.

Di seguito, vi riportiamo il codice della funzione “main”, chiamata all’avvio del programma ed eseguita ad ogni nuova connessione:

int main (int argc, char *argv[])
{

    int listenfd, connfd, n;
    pid_t childpid;
    socklen_t clilen;
    struct sockaddr_in cliaddr, servaddr;
    struct sigaction sa;

    sa.sa_handler = SIG_IGN;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;

    if (sigaction(SIGCHLD, &sa, 0) == -1) {
    perror("Errore: sigaction");
    exit(EXIT_FAILURE);
    }

    if ((listenfd = socket (AF_INET, SOCK_STREAM, 0)) <0) {
    perror("Errore: socket()");
    exit(EXIT_FAILURE);
    }

    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    bind (listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));

    listen (listenfd, LISTENQ);

    for(; ; )
    {
    clilen = sizeof(cliaddr);

    connfd = accept (listenfd, (struct sockaddr *) &cliaddr, &clilen);

    int pid = fork();
    
    if (pid == 0){

        gestisci_connessione(connfd,listenfd);
    }

    else {
              close(connfd);
              }
    }

    exit(EXIT_SUCCESS);
}

Online, sono facilmente reperibili esempi di questo tipo, ma per esperienza, ho notato che spesso non viene implementata la parte per inizializzare i segnali tra parent e child, al fine di evitare che quest’ultimo vada nello stato “zombie” a seguito della disconnessione da parte dell’utente.

Per cui, la sezione da evidenziare, è quella composta da queste istruzioni:

    struct sigaction sa;

    sa.sa_handler = SIG_IGN;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;

    if (sigaction(SIGCHLD, &sa, 0) == -1) {
    perror("Errore: sigaction");
    exit(EXIT_FAILURE);
    }

e nel dettaglio, le funzioni sigemptyset() e sigaction().

Le attività di debugging (come la verifica di eventuali memory leak) e profiling, sono state svolte utilizzando il software valgrind.

 

Easter EGG

Avevamo pubblicato un contenuto speciale su ognuno dei 3 server in cui avevano accesso i concorrenti, fornendo questi indizi:

  • Il 2015 è l’anno in cui Marty McFly (Ritorno al Futuro II) torna al futuro dal 1985. Sei in grado di trovare il famoso almanacco?
  • Trova la navicella aliante e troverai la seconda Easter Egg
  • Per trovare la terza Easter Egg siamo andati sul classico riportando sulla scena la saga di Star Trek

Purtroppo non abbiamo ricevuto email con tutte e tre le soluzioni, e la sorpresa destinata ai primi utenti che ci segnalavano i “contenuti nascosti”, non è stata assegnata:

Seeweb Hacking Contest speciale Easter Eggs

Le date dei file in cui erano nascoste le Easter EGG, erano state alterate con il comando:

touch -d '13 May 2015 01:13' FILE

Il messaggio dei Black Hat

Il messaggio degli Hacker, è stato codificato utilizzando il Cifrario VIC.

Tecnica utilizzata dagli agenti segreti sovietici, che combinava il frazionamento alla trasposizione dei caratteri, risultando così uno dei cifrari “manuali” più all’avanguardia di quell’epoca.

Questo è il testo che i White Hat dovevano decifrare, con la relativa scacchiera a diffusione:

88181890981263980

514956371874315604565440045652956559885072828245650554345652495683048857565143568927568926237472566295655955328195696
541781439889565220045686504093585688015052565447814882503988562565149565228815295498843156905681255554848491568895474
3156885125651466156045588943156620565595532814

514885725256835856830488575651435688725980565925647256405945855561609625683503566287275689725526385565496525650555617
56592565990056881639650256315652955750893565815080

505545686502553456894555559175256892756488882522725640563501568971555598115618392339871

53895954574812259786
-----------------------
| |0|1|2|3|4|5|6|7|8|9|
| |l|o|e|t|a| |n|r| |i|
|5|u|h|d|j|f|s| |k|y|w|
|8|.|m|z|b|g|,|q|v|c|p|
-----------------------

 

Time-of-check Time-of-use (TOCTOU)

Tra gli obiettivi che i concorrenti dovevano raggiungere, c’era quello di recuperare la formula del vaccino contenuta nel file “/home/monday/antigene_sbc”.

Per farlo, era necessario sfruttare una vulnerabilità di tipo “Race Condition”, presente nel file SUID-root “/usr/bin/gmanager”.

Questo tipo di falla, fa leva sui controlli che l’applicazione esegue su una risorsa (come la verifica del proprietario di un dato) prima dell’effettivo utilizzo.

Nel nostro caso, le funzioni critiche erano le chiamate access() ed fopen():

        if(!access(FILES3, W_OK)){

            sleep(2);

            fp = fopen(FILES3, "r");

            if ( fp != NULL) {
                while (!feof(fp)) {
                    fread(buf, sizeof(buf), 1, fp);
                    printf("%s", buf);
                }
                fclose(fp);
            }
        }

L’errore logico è generato dal fatto che access() esegue un controllo sul real user ID ed il real group ID dell’utente che tenta di accedere al file, mentre, dopo un breve istante (simulato da “sleep()”), la chiamata “fopen()” apre la risorsa verificando solamente l’effective user ID o group ID.

Per eseguire l’exploit, l’Hacker doveva creare il dato “FILES3” (su cui aveva i permessi di scrittura), per poi eliminarlo ed entro 2 secondi creare un link simbolico verso “/home/monday/antigene_sbc”.

Vulnerabilità di questo tipo, sono difficilmente individuabili analizzando manualmente migliaia di righe di codice.

Esistono tuttavia strumenti automatici, che analizzano il sorgente di un’applicazione in cerca di pattern specifici, e quindi di funzioni vulnerabili ad attacchi noti (come strcpy() per gli overflow), come flawfinder.

CONDIVIDI SUI SOCIAL

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

37 − 32 =