Els buffers són àrees de memòria reservades per contenir dades, sovint mentre es mouen d'una secció d'un programa a una altra, o entre programes. Els desbordaments de memòria intermèdia sovint es poden desencadenar per entrades mal formades; si hom suposa que totes les entrades seran més petites que una determinada mida i la memòria intermèdia es crea per tenir aquesta mida, aleshores una transacció anòmala que produeixi més dades podria fer que escrigui més enllà del final de la memòria intermèdia. Si això sobreescriu les dades adjacents o el codi executable, això pot provocar un comportament erràtic del programa, com ara errors d'accés a la memòria, resultats incorrectes i bloquejos.[2]
L'explotació del comportament d'un desbordament de memòria intermèdia és una explotació de seguretat ben coneguda. En molts sistemes, la disposició de memòria d'un programa, o del sistema en conjunt, està ben definit. Mitjançant l'enviament de dades dissenyades per provocar un desbordament de memòria intermèdia, és possible escriure en àrees conegudes que contenen codi executable i substituir-lo per codi maliciós o sobreescriure selectivament les dades relatives a l'estat del programa, provocant, per tant, un comportament que no estava previst pel programador original. Els buffers estan molt estesos en el codi del sistema operatiu (SO), de manera que és possible fer atacs que realitzen una escalada de privilegis i obtenir accés il·limitat als recursos de l'ordinador. El famós cuc Morris el 1988 va utilitzar això com una de les seves tècniques d'atac.[3]
Els llenguatges de programació habitualment associats als desbordaments de memòria intermèdia són C i C++, que no proporcionen cap protecció integrada contra l'accés o la sobreescriptura de dades en cap part de la memòria i no comproven automàticament que les dades escrites en una matriu (el tipus de memòria intermèdia integrada) estiguin dins els límits d'aquesta matriu. La comprovació de límits pot evitar desbordaments de memòria intermèdia, però requereix codi i temps de processament addicionals. Els sistemes operatius moderns utilitzen una varietat de tècniques per combatre els desbordaments de memòria intermèdia maliciosos, sobretot mitjançant l'aleatorització de la disposició de la memòria o deixant deliberadament espai entre les memòries intermèdies i cercant accions que escriguin en aquestes àrees ("canaris").
Descripció tècnica
Es produeix un desbordament de la memòria intermèdia quan les dades escrites en una memòria intermèdia també corrompen els valors de les dades de les adreces de memòria adjacents a la memòria intermèdia de destinació a causa d'una comprovació insuficient de límits. Això pot passar quan es copien dades d'una memòria intermèdia a una altra sense comprovar abans que les dades s'ajustin a la memòria intermèdia de destinació.[4]
Exemple
En l'exemple següent expressat en C, un programa té dues variables adjacents a la memòria: un buffer de cadena de 8 bytes de llargada, A, i un nombre enterbig-endian de dos bytes, B.
charA[8]="";unsignedshortB=1979;
Inicialment, A no conté més que zero bytes, i B conté el número 1979.
nom de la variable
A
B
valor
[ cadena nul·la ]
1979
valor hexadecimal
00
00
00
00
00
00
00
00
07
BB
Ara, el programa intenta emmagatzemar la cadena "excessive" amb codificació ASCII al buffer A.
strcpy(A,"excessive");
La cadena "excessive" és de 9 caràcters; incloent el bit buit que requereix al final (null terminator) per tal d'indicar el final de la cadena, ocupa un total de 10 bytes. Recordem, però, que A només pot contenir 8 bytes. En no comprovar la longitud de la cadena, també sobreescriu el valor de B:
nom de la variable
A
B
valor
'e'
'x'
'c'
'e'
's'
's'
'i'
'v'
25856
hexadecimal
65
78
63
65
73
73
69
76
65
00
El valor de B ara s'ha substituït inadvertidament per un nombre format a partir d'una part de la cadena de caràcters. En aquest exemple, "e" seguida d'un byte zero es convertiria en 25856.
De vegades, el sistema operatiu pot detectar l'escriptura de dades més enllà del final de la memòria assignada, i genera un error de segmentació que acaba el procés.
Per evitar que es produeixi el desbordament de la memòria intermèdia en aquest exemple, el call a strcpy es podria substituir per strlcpy, que pren la capacitat màxima de A (incloent el caràcter de terminació nul·la) com a paràmetre addicional i garanteix que no s'excedeix aquesta quantitat de dades:
strlcpy(A,"excessive",sizeof(A));
Quan està disponible, es prefereix la funció de bibliotecastrlcpy sobre strncpy, que no acaba amb nul·la la memòria intermèdia de destinació si la longitud de la cadena d'origen és superior o igual a la mida de la memòria intermèdia (el tercer argument passat a la funció).