Está en la página 1de 8

DESCRIPCIÓN BREVE

En este documento se recogen todos los métodos y


procedimientos utilizados para llevar a cabo un
desbordamiento de la pila mediante el programa

PRÁCTICA DE “deseos_alt.c”. Además, se propone una variante


del código para solventar los problemas de
seguridad relativo al uso de funciones inseguras.

BUFFER Luis Muñiz García


Máster Propio en Seguridad en la Información y
Comunicaciones (X edición).

OVERFLOW
Resolución de ejercicios propuestos.
Contenido
Ejercicio 1. ..................................................................................................................................... 2
Ejercicio 2. .................................................................................................................................... 2
Ejercicio 3. ..................................................................................................................................... 3
Ejercicio 4. ..................................................................................................................................... 3
Ejercicio 5. ..................................................................................................................................... 3
Ejercicio 6. ..................................................................................................................................... 4
Ejercicio 7. ..................................................................................................................................... 4
Ejercicio 8. ..................................................................................................................................... 4
Ejercicio 9. ..................................................................................................................................... 4
Ejercicio 10. ................................................................................................................................... 5
Ejercicio 11. ................................................................................................................................... 5
Ejercicio 13. ................................................................................................................................... 6

1
Ejercicio 1.
Compruebe el resultado que se obtiene cuando se llama directamente a ./deseos-alt y se
le pasa los mismos caracteres de entrada.

Esto es lo que sale:

No sale “AA” porque “runbin.sh” es quien se encarga de formatear la entrada para que
reciba los caracteres ASCII asociados a los caracteres hexadecimales de la entrada.

Ejercicio 2.
El script runbin.sh tiene el siguiente código:
while read -r line; do echo -e $line; done | ./deseos-alt

Explique el funcionamiento de esta línea.

El script realiza las siguientes acciones:

1. Lee líneas de entrada de algún origen desconocido y las almacena en la variable "line"
usando el comando "read". El modificador "-r" se utiliza para evitar que se interpreten
caracteres de escape en las líneas leídas, lo que permite leer las líneas tal y como están
(lo cual explica el suceso del apartado anterior).
2. Ejecuta el comando "echo -e $line" para imprimir en la salida estándar las líneas
leídas. El modificador "-e" se utiliza para interpretar caracteres de escape en las líneas,
lo que permite imprimir caracteres especiales como tabulaciones o saltos de línea de
manera adecuada.
3. Pasa la salida del comando "echo -e $line" como entrada al programa compilado
"deseos-alt" mediante el operador de tubería "|" en la línea siguiente.

En resumidas cuentas, este script está leyendo líneas de entrada, imprimiéndolas con caracteres
de escape interpretados, y pasando la salida al programa "deseos-alt" compilado.

2
Ejercicio 3.
Realice un resumen de cómo funciona la aplicación: qué se hace en la función principal del
programa, que hace cada una de las funciones que están definidas en el programa, cuando
son llamadas cada una de ellas. Describa también los diferentes punteros que se definen en el
programa y qué utilidad tienen dentro de la aplicación.

El programa "deseos-alt.c" es una aplicación que implementa un sistema para manejar una lista
de deseos. Se desglosa en las siguientes funciones:

• main: Es el punto de entrada del programa y es responsable de gestionar el flujo de


ejecución del programa. En un bucle infinito, muestra un saludo y espera la entrada del
usuario. Luego, lee la entrada del usuario, llama a la función correspondiente según la
opción seleccionada por el usuario (mediante un arreglo de punteros a funciones
llamado "ptrs"), y repite el proceso hasta que se rompe el bucle.
• Funciones de gestión de deseos: El programa define tres funciones principales para
gestionar los deseos: "get_wisdom()", "put_wisdom()" y "pat_on_back()". Estas
funciones se encargan de leer los deseos almacenados en una lista enlazada, agregar
nuevos deseos a la lista y mostrar un mensaje de felicitación cuando consigues
averiguar la posición en la pila para poder llamar a dicha función respectivamente.
• Estructura de datos: El programa utiliza una estructura de datos llamada "WisdomList"
para representar los deseos. Esta estructura tiene un puntero al siguiente elemento de
la lista ("next") y un arreglo de caracteres para almacenar los datos del deseo ("data").
Los punteros "head" y "l" se utilizan para apuntar a la cabeza de la lista y a los elementos
individuales de la lista respectivamente. Básicamente, es una lista enlazada.
• Punteros a funciones: El programa utiliza un array de punteros a funciones llamado
"ptrs" para gestionar las llamadas a las funciones de manejo de deseos. Cada elemento
del array contiene el puntero a una función específica. Cuando el usuario selecciona
una opción, el programa utiliza el valor ingresado como índice para acceder al arreglo
"ptrs" y llamar a la función correspondiente.

Ejercicio 4.
En el programa hay una overflow de la pila. ¿Cuál es el nombre de la variable que referencia
el buffer afectado?

El buffer afectado por el desbordamiento de pila se encuentra en la función "put_wisdom()". El


nombre de la variable que referencia este buffer es "wis", que es un array de caracteres de
tamaño "DATA_SIZE" (cuyo valor de MACROS es concretamente de 128 B). Este límite queda
definido al comienzo de la función con la declaración "char wis[DATA_SIZE] = {0};". Es este buffer
el que se llena con la entrada del usuario en la función "gets(wis)", lo cual puede causar un
desbordamiento de pila si la entrada del usuario es más larga que el tamaño del buffer
"DATA_SIZE".

Ejercicio 5.
Considere el buffer que ha identificado en el ejercicio anterior. ¿Cuál es la línea de código que
puede provocar el desbordamiento del buffer?.

Línea 64 (función “put_wisdom()”): r = (int)gets(wis);

La explicación se encuentra en el apartado anterior.

3
Ejercicio 6.
Hay otra vulnerabilidad, no relacionada con la anterior, que afecta a una tabla, que no está
en la pila, y que se puede indexar fuera de sus límites (lo cual, entendiéndolo en sentido
amplio, es una clase de buffer overflow). ¿Qué variable contiene esta tabla o buffer?

La variable “data” definida en el struct “_WisdomList”.

Ejercicio 7.
Considere el buffer que acaba de identificar. ¿qué línea de código puede provocar ese
desbordamiento de buffer?

En la línea 70, con la función “strcpy()”, que es otra de las funciones no seguras ya que no estás
limitándole el tamaño del buffer. Si los datos de origen exceden el tamaño del array de destino,
podría causar un desbordamiento de buffer y afectar a la tabla.

Ejercicio 8.
Determine la dirección de los siguientes elementos (la dirección que ocupan en memoria, no
el valor que contienen) que se definen en el programa (muestra las direcciones en
hexadecimal):

• buf
• ptrs
• write_secret
• p (la variable local definida dentro del main)

buf 0xbfffef30
ptrs 0x4040d8
write_secret 0x401209
p 0xbffff32c

Ejercicio 9.
¿Qué entrada debemos proporcionar al programa de forma que prtr[s] lea (y entonces intente
ejecutar) el contenido de la variable local p en vez del puntero a función almacenado en el
buffer apuntado por ptrs? Puede determinar la respuesta realizando una pequeña operación
matemática con las direcciones que ha obtenido en el ejercicio anterior (tenga cuidado que
tiene en cuenta el tamaño del puntero cuando haga la aritmética de punteros). Si lo calcula
correctamente, terminará ejecutando la función pat_on_back. Dé la respuesta como un entero
sin signo.

𝑑𝑖𝑟𝑝 − 𝑑𝑖𝑟𝑝𝑡𝑟𝑠 0𝑥𝐵𝐹𝐹𝐹𝐹32𝐶 (𝐻𝐸𝑋) − 0𝑥4040𝐷8(𝐻𝐸𝑋) 0𝑥𝐵𝐹𝐵𝐹𝐵254(𝐻𝐸𝑋)


= =
4 4 4
= 0𝑥2𝐹𝐸𝐹𝐸𝐶95(𝐻𝐸𝑋) → 804252821(DEC)

4
Ejercicio 10.
¿Qué valor debemos escribir de forma que prts[s] lea (e intente ejecutar) comenzando desde
el byte número 65 en buf, esto es buf[64]? Responda a la cuestión suministrando un valor
entero.

804252578

Ejercicio 11.
La cadena que nos vas a permitir explotar la vulnerabilidad de inyección de código comentada
anteriormente tendrá la siguiente forma:

NUMEJER10\x00CARACTERESDERELLENO\xEE\xEE\xEE\xEE

Donde:

- NUMEJER10: el valor entero determinado en el Ejercicio10.

- CARACTERESDERELLENO: cualquier cadena de caracteres que va a actuar derelleno para


llegar hasta la posición 65 de buf.

- \xEE\xEE\xEE\xEE: la dirección de la función a la que queremos saltar (en el caso de este


ejercicio la función write_secret). Tener en cuenta que la codificación de la dirección debe ser
Little endian. Consideremos ahora la otra vulnerabilidad que habíamos identificado de
desbordamiento de buffer en la pila. Vamos a provocar un overflow en la variable wis en la
pila. Podemos hacer esto eligiendo la opción 2 para llamar a la función put_wisdom, y
entonces escribir suficientes byte para sobreescribir la dirección de retorno de la función,
reemplazándola con la dirección de la función write_secret. Para obtener respuesta a lo que
se va a solicitar, es conveniente que usemos los siguientes dos comandos de gdb:

- backtrace: imprime la pila de llamadas de funciones en el punto de ejecución donde se


encuentra el programa en el momento de la ejecución.

5
- x: comando el cual realiza un volcado hexadecimal de los bytes que se le indiquen a partir de
una determinada dirección. Por ejemplo si escribimos: x/48xw $esp se imprimirían 48 palabras
(por la w), en formato hexadecimal (por la x), comenzando en la dirección de memoria
almacenada en el registro $esp.

Obtenemos la dirección mediante el gdb:

A continuación, probamos por fuerza bruta el número de Bytes para saltar a esa zona de
memoria.

804252578\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x09\x12\x40

Es decir, necesitaremos 54 caracteres (432 Bytes.)

Ejercicio 13.
Modifique el programa de forma que las vulnerabilidades que hemos explotado se solucionen.
Para ello utilice las funciones seguras que se han visto en la introducción teórica. A
continuación, verifique que todas las operaciones que hemos realizado con anterioridad ya no
conllevan ningún problema de seguridad.

6
Se han solventado todos los problemas relativos al uso de funciones inseguras, ya no podemos
acceder a la llamada secreta de la función con la clave, directamente se detiene la ejecución del
hilo principal.

Como añadido, se recomendaría compilar eliminando la desprotección de la pila con la opción


-fno-stack-protector para una mayor seguridad en el código.

También podría gustarte