En esta segunda parte vamos a ver como se puede usar un stack overflow para ejecutar código malicioso. No quiere decir que vayamos a ser capaces de hacerlo, sino de entender el mecanismo y tener más fácil crear código seguro. Que por algo esto este post esta en Ciberseguridad Básica 🙂 Los Hackeos serios los dejamos para verdaderos expertos.
¿Como se guardan los datos en el Stack?
Vamos a ver como quedan los datos que teníamos en nuestra función ya vista en el primer post de la serie: Buffer Overflow para negados Parte -I.
[code language=»c»]
#include <stdio.h>
#include <strings.h>
int main(int argc, char *argv[]){
int puede_pasar = 0;
char password[12];
char passwordGuardado[12] = "SIoNOoES";
gets (password);
if (strncmp(password, passwordGuardado, 6) == 0){
puede_pasar = 1;
}
if (puede_pasar == 0){
printf("Ehhhh!! ¿que haces tu aqui?");
} else {
printf("Yeah!!! Hola megasuperUsuario!");
}
[/code]
Ok, los datos que vemos en esta función quedarían el stack de la siguiente manera:
- argc : 4 bytes.
- argv : 4 bytes.
- dirección retorno: 4 bytes.
- puede_pasar : 4 bytes.
- password : 12 bytes.
- passwordGuardado : 12 bytes.
Los datos se asignan desde las direcciones superiores hasta las inferiores, en cambio, cuando les damos valor es al contrario, se asignan desde abajo. Por esos las variables que se desbordan (Overflow) sobreescriben las de arriba, que son las que se han definido en el código justo antes que ellas.
Si recordáis en el ejemplo anterior, al poner un valor con una longitud superior a 12 bytes en password, se sobreescribia el valor de puede_pasar.
En este caso la clave está en poder modificar el contenido de dirección retorno, que es la dirección desde la que se ha llamado a la función y a la que se devuelve el control del flujo del programa una vez finalizada la función.
El funcionamiento continúa siendo muy similar, y el problema es exactamente el mismo. Todo lo que asignemos que sea mayor de 12 bytes a la variable password, se irá escribiendo en partes de memoria que no le corresponden. Primero ocupará la memoria de la variable puede_pasar, y si superamos su espacio empezaremos a ocupar la dirección de retorno. Es tan sencillo como pasar como parametro la dirección que ocupa en la memoria el código que queremos ejecutar. En este caso esta dirección tendría que estar a partir del 16avo byte de la variable password.
A preocuparse por los Overflow.
Como programadores tendríamos que comprobar siempre la longitud de cualquier entrada que permitamos a nuestro programa.
Como Responsables técnicos tenemos que actuar como evangelizadores para que nuestros desarrolladores asuman la multitud de agujeritos que se pueden dejar por un código bien escrito pero descuidado.
Si somos gestores de proyectos tenemos que traspasar esta preocupación a nuestros proveedores. ¿Pero qué hay del código standard? O lo que es peor ¿del semi standard? Si, ese código que es un nicho de mercado, que se usa en todo tu sector, pero no es popular, es decir, no lo conoce la mayoría de la población. Este es el software más peligroso. Sobretodo si nuestro sector es uno de los golosos, medios de pago, banca, fintech, sanidad, inversión, etc etc… Muchos de los ataques van contra el software que producen estas empresas, a veces descubriendo los Zero Days (vulnerabilidades desconocidas por el fabricante) otras con un Topo. Estas empresas medianas no tienen la capacidad de las grandes ni su presupuesto, y no sabemos las condiciones laborales de sus programadores.
Y así podríamos continuar con toda la escala jerárquica de cualquier organigrama empresarial. Poco a poco se va tomando consciencia y ahora muy poca gente le lleva la contraria al departamento de seguridad, o le pone palos en la rueda. Pero contunamos sin preocuparnos por código que no es nuestro, nos parece perfecto que en nuestros sistemas tengamos código corriendo de una empresa que paga 600 euros a un ingeniero subcontratado. Algún día alguien le dará un poquito (o mucho mucho) más para liarnos una buena.
Espero que ahora estemos todos un poco mas concienciados. 🙂 o Preocupados!