Integer overflow

 

Le vulnerabilità dovute ad errori di tipo integer overflow si basano su una delle caratteristiche fondamentali dell’aritmetica dei calcolatori e sono le più difficili da sfruttare.

Nel linguaggio C, che prenderemo come esempio, ci sono diversi tipi di interi e ciascun tipo è rappresentato da una variabile con un certo numero di bit. Ad esempio, su una piattaforma Win32:

-         int è un intero a 32 bit

-         short è un intero a 16 bit

Ciascun intero può avere un valore massimo pari a 2(dimensione in bit) – 1.

Mostriamo di seguito un esempio di funzione soggetta ad una vulnerabilità di tipo integer overflow:

 

 

Il controllo effettuato nel test dell’if non tiene conto di un possibile integer overflow.

Infatti il risultato dell’operazione len1 + len2 (che dovrebbe essere un intero, in quanto somma di due variabili intere), potrebbe essere un numero troppo grande (a causa dei valori addendi) per essere rappresentato con una variabile intera. Ciò potrebbe portare ad una cattiva rappresentazione di tale valore somma che potrebbe superare il test, quando in realtà i buffer passati in argomento sono troppo grandi per essere memorizzati nel buffer buff.

Per rendere più chiaro il rischio di un attacco, forniamo il seguente esempio.

Supponiamo che siano necessari 32 bit per rappresentare una variabile di tipo int, ovvero come len1 e len2. Supponiamo, poi, che i valori passati in input alla funzione siano tali da avere:

len1 = len2 = 2147483648 = 231

L’operazione di somma

len1 + len2

avrà quindi come risultato il valore

2147483648 + 2147483648 = 4294967296 = 232

È proprio qui che si genera il tanto paventato integer overflow.

Il valore risultato della somma è troppo grande per essere memorizzato in una varabile di tipo int (che, sotto le ipotesi precedenti, può assumere tutti i valori da 0 a 232 – 1); sarebbero infatti necessari 33 bit alla sua rappresentazione corretta.

Cosa succede quindi al programma?

Il valore corretto viene troncato a 32 bit: nel nostro caso 4294967296 diventa 0 che finisce col superare agevolmente il test dell’if e le due operazioni di memcpy vanno a sovrascrivere una zona di memoria superiore a quella allocata.

In conclusione, alla funzione memcpy viene consentita la sovrascrittura dello stack ricadendo così nel più classico buffer overflow sullo stack del processo.