Control Center PRO 6.2.9 – Local Stack Based Buffer Overflow (SEH) – From reversing to zero day

INTRODUCCIÓN

Hola a todos el día de hoy, vamos hablar sobre una vulnerabilidad de día cero que identifiqué sobre un producto de la empresa webgate, en uno de sus productos pro llamado Control Center Pro v6.2.9, este producto esta destinado hacer usado para conectar las cámaras de tipo videovigilancia y dvr en red, que ofrece está misma empresa, o en su defecto otras que se puedan conectar de la misma forma, y otra infinidad de cosas.

 ¿A QUÉ NOS ENFRENTAMOS?

En esta publicación en particular vamos a tratar el tema de recreación de la sobre escritura de SEH (Structure Exception Handler), lucharemos con alguna restricción de badchars o caracteres malos y ejecutaremos código remoto.

LO QUE NECESITAMOS

Para resolver este software necesitamos de las siguientes herramientas:

  • Immunity Debugger y/o Ida Free
  • Un editor de código (SublimeText/PycharmCommunity/VisualStudioCode)
  • Windows 10 PRO N o XP SP3
  • El ejecutable de Control Center Pro v6.2.9

Todo esto pueden encontrarlo desde mi repositorio, aquí.

REVERSANDO Y ENCONTRANDO EL FALLO

Lo primero será instalar el programa y buscar el formulario de creación de usuarios ubicada en Menu -> settings -> User Account -> Add.

Para probar si es vulnerable voy hacer algo muy sencillo, voy a generar con python una cadena de 40000 mil A’es y la pegaré en el campo username/Nombre, colocaré en id de usuario el valor 2, contraseña el valor 3 y confirmar contraseña tambien 3.

Una vez realizada la acción mencionada anteriormente vemos que nuestro software se crasheo y si analizamos los registros y el SEH vemos cosas interesantes.

Efectivamente, podemos ver que hemos sobreescrito el SEH que es mucho mejor para crear un exploit más seguro, pasemos a buscar la zona donde esta el fallo.
Aca podemos hacer uso de la función TimeTravel de WindbgPreview o ir a las strings y buscar información que haga referencia a agregar usuario o actualizar, para mi caso si se animan a que les enseñe como usar el Time Travel de WindbgPreview pueden dejar un comentario y en el próximo tutorial de seguro lo haremos, mientras tanto iré a buscar referencias a strings o funciones que concuerden con el módulo del fallo, crear usuario.

En mi caso voy a usar IDA para el ejercicio estático y veo que en el módulo imports si escribo UpdateData encuentro lo siguiente:

Si damos doble click y buscamos las referencias vemos que hay demasiadas, hay momentos en que usar el TimeTravel es lo mejor para estos casos.

Lo que yo hice fue tracear todas las llamadas poniendo breakpoints en ellas y pegando mis A’es en el formulario hasta llegar a la siguiente función.

Una vez identificado esta función pongo un breakpoint en 0x00879A4A y voy a esa llamada y nos encontraremos con lo siguiente.

Antes de que nuestras A’es entren en acción vemos que se inicializa unas estructuras al parecer con unos tamaños fijos, veamos más adelante que se aclara un poco esto.

Vemos que con la funcion lea obtenemos el puntero hacia la ubicación de la string del id_usuario en donde podemos observar que hay un desplazamiento de ebx+354h, se parece mucho a las inicializaciones que habíamos observado anteriormente.

Lo que voy hacer es crearme una estructura en IDA del tamaño 0x500 y agregaré estos datos para verlos de forma más ordenada, quedandome de la siguiente forma.

seguimos traceando y vemos que hace lo mismo para los campos de la contraseña en los offsets siguientes:

  • ebx+34Ch => password 1
  • ebx+350h => password 2

Reemplazo ese offset por la estructura que creé como en el paso anterior, quedandome ahora asi.

Seguimos traceando y vemos lo siguiente, se obtiene el puntero a la string user_id, se llama a la función GetBuffer y se guarda en ECX el tamaño de la string, en mi caso 3, en EAX queda guardado el puntero a la string user_id.

El puntero hacia el string user_id, en EAX mi caso es: 0x0B21FFA8
El puntero de preparación para apuntar a mi buffer destino en EDX es: 0x083BE134

Luego podemos ver que hay una operación matemática sub eax, edx que al final se resume en copiar mi string_id byte a byte en :

  • mov [edx+eax], cl

si hacemos las cuentas en python de la siguiente forma:

  • hex(0x083BE1340x0B21FFA8) = -0x2e61e74 luego hex(0x0b21ffa8 + (-0x2e61e74)) = 0x83be134

Que me parece una barbarie hacer esto por que si se fijan es el mismo valor que esta en EDX donde al final se copiará nuestra string user_id.

Luego podemos observar que toma el puntero de inicio de la contraseña 2 y lo guarda en ECX, y hace lo mismo con un offset de la misma estructura [ebx+0D8h] y lo guarda en EDX, por suerte creamos una estructura anteriormente lo cual nos va a servir para no perdernos.
En las siguientes imagenes podemos apreciar las distancias que hay entre user_id y password es de 0x40, algo muy similar a la función de inicialización de las estructuras.

Continuamos traceando, y vemos el mismo proceso para el campo correo

Bueno ya podemos ir sacando conclusiones de aca en adelante, nos faltaria el campo username y description, si sacamos conclusiones vemos que no se valida los tamaño de lo que insertemos en los campos en ningun lado, y si pegamos muchas A’es en nuestro campo username por ejemplo, romperia los datos del siguiente campo por lo cual si se operara con lo que sigue lo unico que encontraran seran A’es, pero mejor veamoslo y no concluyamos todavia.

Vemos que el puntero destino para los datos del username esta encima del mail, osea siguiendo el orden del formulario, pero como sabemos que no hay una restriccion de copia en estas areas lo que siga despues del area de username sera sobre escrito con mis A’es asi que ya sabemos de donde y como se desencadena la vulnerabilidad.

PROGRAMANDO NUESTRO EXPLOIT

Bueno, ya comprendimos la vulnerabilidad desde el vector estático y dinámico, ahora empieza la parte más divertida, la creacion de nuestro exploit, vamos hacer lo siguiente:

  • Crear nuestra plantilla base en python que genere una cadena de 40000 caracteres, las cuales las 1000 primeras seran un patron para ubicar la porcion exacta que sobreescribe los registros, y el SEH
  • Esta informacion generada la exportaremos a un archivo donde luego copiaremos la data a nuestro campo y veremos su comportamiento.

Ejecutamos nuestro exploit y abrimos el contenido de nuestro archivo generado.

Voy a correr mi programa, y luego voy a pegar mi payload en el campo username y veamos que sucede…

Hemos sobre escrito el SEH con la cadena 2Aw3 si buscamos esta cadena en nuestro archivo generado vemos que corresponde al tamaño 672, sabemos que la lista del SEH es de 8 bytes si lo restamos nos quedaria: (672-8 = 664) luego ya sabemos el offset para nuestro exploit, vamos a modificar nuestra plantilla base, quedandonos de la siguiente forma.

Al ejecutar el exploit y copiar los datos generados obtenemos lo siguiente, sobreescribiendo exitosamente la cadena SEH con nuestros datos.

Algo muy importante es verificar los caracteres malos o «bad chars» que no debe contener mi exploit, ya que esto cortaria el flujo de nuestro payload, lo que harémos sera generar un payload que valla desde 0x01 a 0xFF y la pegaremos en mi exploit como si fuera mi shellcode y veremos si existen badchars, normalmente en todo exploit se descartan los bytes 0x00, 0x0a, 0x0d, 0xff, por ser terminadores de string, pero no todos los casos son asi, por eso voy a probarlos todos excepto el 0x00 para ver que bytes puedo utilizar, quedando nuestra plantilla de exploit de la siguiente manera.

Al copiar mi payload en el campo username podemos ver que el registro ESI apunta a parte de mi exploit, le doy jump in hex en mi IDA, si analizamos podemos identificar que el byte 0x0a es un badchar ya que venia la cadena de flujo desde 0x01 y despues de 0x09 vemos que sigue un 0x00, eso nos indica que hay algo raro ahi, ademas no continua nuestro flujo, eliminemos 0x0a de nuestra shellcode y ejecutemos nuevamente.

vemos que 0x0d tambien es un bad char, asi que lo quitamos de nuestro shellcode en el exploit, y lo volvemos a lanzar.

En la imagen anterior podemos apreciar que no podemos usar bytes >= a 0x80 ya que los convierte en 0x3f y esto puede tener mucho sentido ya que es un campo de username y caracteres mayores o iguales a 0x80 en la tabla ascii no son caracteres muy comunes para asignarlo como nombres.

En resumen como bad chars o caracteres malos tenemos, 0x00, 0x0a, 0x0d y los mayores o iguales a 0x80.
Esto nos va a limitar un poco con la generacion de shellcode ya que hay demasiados caracteres malos, lo que haremos será trabajar con una shellcode encodeada a traves de metasploit en alpha_mixed y adicionalmente nosotros le diremos en que registro empieza nuestra shellcode, por que si no le indicamos el encoder de metasploit va utilizar unas instrucciones que tienen caracteres que no son permitidos por nuestro programa, pero antes busquemos nuestro gadget pop-pop-ret, ya he explicado mucho como buscarlos asi que no me detendre ahi, para mi caso tengo mi gadget que es el siguiente:

0x0258107E pop edi # pop esi # retn lib_VoiceEngine_dll32.dll 3 8 one-reg, stack edi, esi nonull, ascii

Este gadget cumple con mis requisitos, no contiene ningun caracter malo, armo mi exploit nuevamente y pruebo…

Podemos ver que el SEH esta sobre escrito con nuestro gadget, le pongo un breakpoint a mi gadget y paso la excepción.

Vemos que pasando la excepción tomamos control del programa, ahora lo que haremos sera hacer un salto hacia adelante y ver como ejecutar nuestra shellcode, como tenemos la restricción de caracteres malos, vamos a usar un salto condicional como en los articulos pasados, solo que esta vez si sera positivo, para eso usaré el siguiente gadget:

inc edx
inc edx
ja 0xc

Que resumido a opcodes seria: «\x42\x42\x77\x08», estas pequeñas instrucciones cumplen los requisitos de no tener bad chars asi que adelante, mi exploit quedaria asi:

Al saltar la excepción nos encontramos con nuestro gadget, funcionando perfectamente.

Seria fácil para nosotros poner nuestra shellcode seguidamente, pero por los caracteres malos no va hacer posible, veamos la shellcode que genera metasploit encodeada en alpha_mixed sin indicarle un registro, para eso usare el siguiente comando, y analicémosla.

sudo ./msfvenom -p windows/meterpreter/bind_tcp LPORT=4444 -e x86/alpha_mixed EXITFUNC=seh -f c -b ‘\x00\x0a\x0d’

Vemos que al inicio de nuestra shellcode hay unos opcodes que no son soportados por nuestro programa, estas instrucciones iniciales lo que hacen en realidad es buscar el registro hacia donde apunta nuestra shellcode, pero si nosotros usamos el parametro BufferRegister y le indicamos en que registro esta apuntando nuestra shellcode ya no se usaran dichos opcodes y tendremos una shellcode totalmente funcional para nuestro programa, el unico problema es que no hay ningun registro que este apuntando a nuestra shellcode por lo que nos toca preparar un registro y hacerlo que apunte a nuestro shellcode, analicemos nuestros registros.

Vemos que en mi caso el registro ESP apunta a 0x07D2CB10, que esta mas abajo de mi shellcode, si bajamos un poco podemos ver que mi shellcode esta ubicada en la siguiente dirección, en mi caso 0x07D2E350.


Entonces si restamos ambas direcciones tenemos una distancia de:

hex(0x07D2CB10 – 0x07D2E350) = ‘-0x1840’

Entonces lo que debemos hacer es sumarle a ESP 0x1840 y quedara apuntando al inicio de mi shellcode, para eso usaremos las siguientes instrucciones, teniendo en cuenta nuevamente la restricción de caracteres, prepararemos el registro ESP en EAX, sumaremos la distancia y lo guardaremos nuevamente en ESP sin usar caracteres malos, en mi ejemplo le sumare 0x1834 con los ajustes de alineación, quedandome asi.

push   esp
pop    eax
add    ax,0x1834
push   eax
pop    esp

Traducido a opcodes seria: «\x54\x58\x66\x05\x34\x18\x50\x5C»

Modificamos nuevamente nuestro exploit quedando de la siguiente manera.

Lo ejecutamos y probamos haber que sucede.

Vemos que EAX esta apuntando al inicio de nuestra shellcode asi que ya una vez ejecutado el push eax pop esp, ESP quedaria listo para que apunte a mi shellcode y como EIP esta apuntando al inicio de mi shellcode cuando empiece a ejecutarla ya se ejecutara sin problemas por que le hemos dicho que nuestra shellcode esta apuntando en ESP, genial generemos nuestro shellcode y ejecutemos codigo.

Una vez generada la shellcode voy a mi exploit lo modifico quedandome de la siguiente forma.

Ejecutamos el exploit, pegamos el contenido en la caja username y tenemos ejecución de codigo de forma exitosa…

AGRADECIMIENTOS

Quiero agradecer al maestro ricardo narvaja de crackslatinos por las sugerencias que me brindó cuando le hice algún par de preguntas sobre el tema, de esta vulnerabilidad.
Tambien al maestro @apuromafo de crackslatinos que saco de su tiempo para ayudarme a entender un poco sobre como funciona la pila y su alineación, que de verdad fue de gran ayuda.
y finalmente al team de @PeruCrackerS.

CONCLUSIÓN

Finalmente hemos ejecutado código remoto sobre la aplicación, despues de un analisis profundo sobre ella, espero que hayan llegado conmigo hasta estas últimas palabras, este artículo estuvo un poco largo pero quizás muy completo, si te gusto el artículo, puedes compartirlo con tus amigos e invitarme un cafe desde aquí.

Agradezco a todos por seguir mis entradas y leer esto que comparto, abrazos.

happy hacking, Cracking and exploiting…
@sasaga92

Deja un comentario

Web construida con WordPress.com.

Subir ↑