Old school attack! #PlataformaPorElBufferAttack

Hace unos días os propuse un reto a través del canal de Telegram https://telegram.me/Fwhibbit. Para los que no lo hayáis visto o leído en ese momento, si queréis comeros un poco el tarro, deciros que consistía en 42 lineas de código «seguro» que se pueden ver a continuación. No bajes mucho si no quieres leer el spoiler definitivo 🙂

 

Pretendía ser un código bastante seguro en PHP, con una conexión a Mysql. Si que es cierto que faltaban cosillas, como comprobar que los parámetros son string y no arrays, pero no ayudan en la solución.

Dispone de una medida de protección anti-fuerza bruta, que realiza una espera cuando el usuario falla las contraseñas, aunque cabe decir que no lo previene en absoluto ya que la sessión (que es donde se guarda el valor wait) depende de la cookie y se podría realizar una fuerza bruta con cookies inexistentes y cada vez nuevas. Dicho esto, quiero decir que no es el camino a seguir, ni tampoco un SQLi (ya que se hace completamente imposible debido a que todo lo que va a la query pasa por SHA1), ni tampoco un DDOS (no es el objetivo).

Muchos de vosotros habéis ido a enfocaros a estos posibles vectores de ataque y hacéis bien en cierta medida, significa que estáis al corriente de ellos, aunque el código contiene protecciones para ellos precisamente, a lo que se me ha venido a la mente el famoso vídeo que muchos habréis visto.

Pero la realidad a veces es mucho más fácil, mas trivial. Entonces … ¿Cómo saltarnos este problema? ¿Cómo hackear este sitio?…. sé que la solución para muchos será decepcionante, pero es la siguiente …

La seguridad hay varias maneras de enfocarla a la hora de realizar cualquier proyecto pero solo una es la correcta y la que hay que hacer por llevar a cabo.

Seguridad desde la base, seguridad desde tu proyecto o seguridad siempre. No importa lo que hagas, como de seguro sea, si requieres de una capa por debajo que no está securizada.

Entonces, teniendo claro que la seguridad hay que llevarla desde el principio hasta el final. Cualquier proyecto que llamemos «seguro», puede pasar a ser inseguro, atacando a sus pilares. Dicho esto, ¿Por que nadie preguntó por la infraestructura? Ninguna pregunta fue referente a como estaba montado el proyecto, a pesar de que la conexión MYSQL se ve que no es a localhost, es a una ip privada … :D, ahora es cuando vienen las decepciones, pero en cualquier pentesting el primer punto es la recolección de información, antes de decir que algo es imposible, de negarnos en rotundo a que no tiene solución, vamos a recoger información. Como está montado el sitio, que versiones de software tiene, etc… etc…

Por lo que la respuesta correcta a como hackear este sitio, debiera haber sido, no tengo suficiente información para ello 🙂

Pues bien, el ataque que vamos a describir hoy aquí, es un ataque que fue descrito hace mas de 25 años, y se trata de un Tcp Packet Injection 🙂

Nunca olvidéis esta tablita de aquí abajo, se hizo hace muuuuchos años y a mi parecer está mal hecha 🙂 (ahí lo dejo jajaj)

 

Supongamos la siguiente infraestructura:

Un equipo que tiene el sitio web en PHP (seguro y actualizado), el cual se conecta a otro puesto que tiene el sitio Mysql (seguro también y actualizado). Ambos equipos, tienen las tablas arp estáticas. Pero nosotros formamos parte de la red, debido a una penetración previa desde otro vector diferente, o simplemente, por que somos un trabajador con acceso físico a dicha red. ¿Por qué digo que tienen las tablas arp estáticas?, porque si alguno estaba pensando que con un MITM Y ARP SPOOFING, se puede solucionar, esa no es la respuesta que busco tampoco, ya que el sysadmin se leyó en su día la siguiente publicación «Entradas ARP estáticas contra ataques Man in The Middle» jeje.

 

Por medio de un TAP y dos tarjetas de red (descartamos el ataque ARP para hacernos pasar por el Mysql), vamos a falsificar los paquetes enviados para poder decidir cuando hacerlo y cuando no, de una manera mas limpia y sin interferir en la ejecución de la aplicación mas adelante. Supongamos que extrae información importante de la base de datos pasada la fase de login, una vez establezca una cookie de logueado (hemos de presuponer que no conocemos el código, jugaremos sólo con lo que el wireshark nos de)

Para este caso vamos a hacerlo por medio de un TAP, aunque para la prueba de concepto, se usará una máquina virtual, cuyo tráfico pasa por nuestra máquina. Que viene a ser lo mismo, tener la capacidad de recibir (MYSQL) y enviar los paquetes al destino (PHP).

Vamos a realizar lo que se conoce como inyección de tráfico. Un ataque de este tipo se hace prácticamente imposible cuando se trata de una red externa ya que hay que predecir los puertos y el número de secuencia de la trama TCP (Ataque de predicción de secuencia).

Nunca os habéis preguntado ¿por qué dice nmap esto?

TCP Sequence Prediction: Difficulty=263 (Good luck!)
IP ID Sequence Generation: Randomized

Al ser una red local y poder capturar el tráfico de la misma, es pan comido, aparte tenemos las dos siguientes ventajas:

  • Tras la verificación del usuario, no se realizan mas consultas, con devolver una fila falsa, valdría.
  • La falsa seguridad que proporciona el tiempo de espera de la fuerza bruta, nos proporciona una ventana de tiempo mayor para nuestro ataque, haciendo más fácil la inyección de tráfico (¿nadie se preguntó por que no estaba antes de crear la conexión, sino después?)
  • El PHP por defecto cierra la conexión y no la reutiliza para futuras consultas, ya estaríamos logueados, y no tendríamos que interceder, una vez nos logeara ya podríamos acceder a la web con normalidad sin mas interceptaciones (En el caso de que se guardara una cookie de logueo, que por resumir el ejemplo no se hizo).

Entonces la idea del ataque es la siguiente.

  1. Fallamos 2 o 3 veces para obligar a realizar la espera al servidor.
  2. Siempre usando la cookie asignada, ya que es la que nos mantendrá la sesión activa y realizará la espera.
  3. Esnifamos los paquetes y capturamos el número de secuencia del servidor MYSQL.
  4. Inyectamos la fila falsa y desconectamos.

Hecho esto, en el servidor, solo habrá 2 paquetes duplicados, con igual número de secuencia, pero se descartará el original y válido por llegar después.

Tan solo el envió de un paquete de una fila con un 1, nos dará el acceso que buscamos. Esto es gracias, en parte, a que Mysql (y la inmensa mayoría de software) funciona con buffers, da igual que le mandes la respuesta antes que la pregunta. El no irá a leer la respuesta hasta haber formulado su pregunta (el SELECT), ¿es curioso no?, te voy devolver las filas que me vas a pedir, sin habérmelas pedido todavía, pero tu, en lugar de preguntarte, What the fuck?, vas a decir… ¡uy que majo, gracias!

¿Simple no?, pues manos a la obra 😀

Me configuro el laboratorio de la forma explicada y tras realizar una prueba, se puede ver lo siguiente:

 

Tras pasar el tiempo de espera el tráfico pasa a ser así:

 

 

Como podéis ver la ventana de tiempo, facilita la capacidad de inyectar tráfico. De no disponer de dicha espera tendríamos un Race Condition, la cosa se complicaría un poco más y seguramente habría que estresar al MYSQL para ralentizarlo y ganar esos milisegundos que necesitamos para enviar primero.

Vamos a ponernos con ello, para ello he utilizado el sniffer de Xploit (aun en pañales), que utiliza a su vez el SharpPcap. Ya se puede apreciar que la consulta SQL realizada por la web es la siguiente:

SELECT 1 FROM users WHERE user="12dea96fec20593566ab75692c9949596833adc9" 
AND pass="9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684" LIMIT 1

Me creo una tabla parecida a la que se ve en la consulta y hago la query para coger el payload que necesitaré enviar para hacer el positivo. Tener en cuenta que el código era visible, pero el ataque se haría sin conocerlo previamente, solo esnifando el tráfico.

 

 

Capturo el Payload de una respuesta positiva (hago un «SELECT 1» ya que es el mismo resultado que espera la aplicación)

 

 

Ya tenemos el payload ahora solo queda inyectarlo

0x01,0x00,0x00,0x01,0x01,0x17,0x00,0x00,0x02,0x03,0x64,0x65,0x66,0x00,0x00,
0x00,0x01,0x31,0x00,0x0c,0x3f,0x00,0x01,0x00,0x00,0x00,0x08,0x81,0x00,0x00,
0x00,0x00,0x05,0x00,0x00,0x03,0xfe,0x00,0x00,0x02,0x00,0x02,0x00,0x00,0x04,
0x01,0x31,0x05,0x00,0x00,0x05,0xfe,0x00,0x00,0x02,0x00

Utilizando este sencillo script https://github.com/shargon/Fwhibbit/blob/master/OldSchoolAttack/OldSchoolAttack.cs

Ya podemos ponernos manos a la  obra y realizar el ataque 🙂

 

Os pongo el enlace al pcap aquí, para que veáis el tráfico generado durante el proceso y como la respuesta al SELECT es enviada antes que el propio SELECT, https://github.com/shargon/Fwhibbit/blob/master/OldSchoolAttack/mysql.pcapng

 

 

Y esto es todo, ya nos daría acceso a la web porque hemos inyectado un logeo positivo, para después dejar con normalidad funcionar el sitio web. Espero no haberos defraudado mucho en la solución del acertijo, ya que reconozco que iba con trampa 😛

Dicho esto, por que no crear un ataque denominado «Buffer attack», ataque que consiste en escribir en un buffer, previamente a la respuesta esperada 🙂 ¡igual se me va la olla ya!

Un saludo y ¡feliz año nuevo! 🙂