Vai al contenuto
Home » Questione di malloc()

Questione di malloc()

Si è da poco spenta l’eco della Winter Edition 2016 di
HackInBo
. Lo si può semplicemente descrivere, come
l’evento italiano più figo in campo ICT Security, o Cyber Security o
Sicurezza Cibernetica, chiamatela come vi pare.

In questo momento sono in stazione che aspetto il mio treno, destinazione
Milano. Nel talk di oggi, che se vi siete persi via streaming, potrete rivedere
tra qualche tempo sul canale YouTube, c’è stato un acceso dibattito sul
seguente codice C.

Nel mio talk, un racconto sulla mia esperienza nella messa in sicurezza del
ciclo di vita del software, ho voluto inserire due momenti quiz. In premio, 1
shot di Grappa, definita cura ferite medie per non urtare la sensibilità
della platea astemia.

Essendo il premio ricco, capisco lo spirito agonisto nel voler risolvere il
quesito.

Il codice è questo, molto semplice.

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>

/*
 * Familiy: CODE REVIEW
 * Level  : MEDIUM
 *
 * This great tool reads a command stored in an environment variable and
 * execute it using system() function.
 * Allowed commands are 'ls' and 'll' and a whitelist approach is in place.
 */
int main(int argc, char **argv) {
  char *envy


  envy = malloc(20 * sizeof(char
  printf("%pn", envy
  bzero(envy, 20 * sizeof(char

  envy = getenv("HACKINBO"
  printf("%pn", envy
  if (envy == NULL) {
    fprintf(stderr, "Please set HACKINBO env variable for more funn"
    return -1
  }

  printf("HACKINBO variable found with value %sn", envy
  /*
   * export HACKINBO="ls"
   */
  if ((strstr(envy, "ls") != NULL) || (strstr(envy, "ll") != NULL)) {
    printf("Executing HACKINBO fun"
    system(envy
  } else {
    fprintf(stderr, "Well, you want too much fun now"
    return -2
  }

  return 0
}

L’idea è quella di leggere una variabile d’ambiente, HACKINBO, metterla in una
stringa, fare un whitelist sbagliato e poi eseguire il comando.

La vulnerabilità che avevo in mente era una command injection. Se HACKINBO
contiene la stringa “ls;sh”, il controllo sul comando non fallisce, quindi alls
system viene passato in realtà, non uno ma due comandi da eseguire.

Si è scatenata un po’ di bagarre. Alcuni dicevano di aggiungere un
cancelletto alla variabile d’ambiente e nella concitazione della discussione,
non ho approfondito.

Se cerco di mettere un cancelletto, non ottengo altro che un errore:

HackInBo] ./a.out
0x7f8b8e500000
0x7fff55c2df52
HACKINBO variable found with value ls#ls
sh: ls#ls: command not found
Executing HACKINBO fun%

Di sicuro, non controllo il valore di ritorno di malloc(), quindi, nel caso non
ci fosse memoria disponibile, andrebbe tutto in segmentation fault quando
provo a chiamre la bzero() la riga dopo.

Una scuola di pensiero ha puntato il dito sulla dimensione dell’input copiato
nella variabile, pensando ad un possibile buffer overflow. Questo punto lo
voglio poi approndire con più calma, ma almeno su macOS, passando un bel numero
di caratteri non riesco a mandare in segfault il mio esempio. Forse tra
randomizzazione dello stack e gestione della memoria da parte dell’OS, andare a
sovrascrivere l’instruction pointer è un impresa per veri duri.

Diciamo che, per essere rigorosi, va comunque controllata la dimensione del
buffer di destinazione, quando ci scrivo dentro dei byte letti dall’ambiente
esterno.

L’errore, che c’è e per il quale ringrazio
@evilsocket, risiede nel fatto che la
chiamata getenv() restituisce di già un puntatore (char *).

Di fatto, ho introdotto un memory leak perché il primo puntatore, che ho
inizializzato a zero, viene perso.

Per chi suggeriva infine, andasse fatta una free() sulla variabile envy, prendo
direttamente quello che dice la man page di getenv su macOS.

The getenv() function obtains the current value of the environment variable,
name. The application should not modify the string pointed to by the
getenv() function.

Quindi, se interpreto bene il manuale, non devo fare una free esplicita di quel
puntatore.

Off by one

Solo chi non fa, non falla. Poco male, ho sbagliato e ci sta un po’ di sana e
pubblica gogna. Dopotutto, è tanto tempo che non scrivo codice C ed
effettivamente sono un po’ arrugginito.

Preparatevi però ad un a nuova serie di post periodici, serie che devo
ancora studiare bene ma nella quale metterò un pezzo di codice con un alcune
vulnerabilità. Raccoglierò poi per email, le
risposte al quiz e, il tutto gestito con una ufficiale classifica, i migliori
si aggiudicheranno dei premi, che di volta in volta andremo a mettere in palio.

Enjoy!

Tag:

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.