martes, 12 de septiembre de 2017

Cómo hackear el Registry de Windows remotamente con WinRegMITM


Fileless UAC bypass, un método con el que podemos saltarnos la protección de User Account Control. Este bypass ha sido encontrado por un investigador alemán que prepara su tesis sobre este tipo de debilidades de los sistemas de Windows. Es cierto que Microsoft no lo considera una vulnerabilidad, pero ha decidido parchear algunos ya que pueden ser utilizados por malware para lograr ejecutarse como SYSTEM en el equipo. Al investigarlo en profundidad y entender su funcionamiento, existe la posibilidad de realizar esta técnica de manera remota. Aquí se involucra un protocolo de Windows que hasta la versión Windows 7 venía corriendo por defecto. El protocolo en concreto es el del Registro Remoto de Windows.

Se encuentran varios problemas de seguridad en este protocolo, que permitían no solo realizar un Fileless UAC bypass de manera remota, sino otras muchas cosas como, por ejemplo, forzar las sesiones cifradas del protocolo para que vayan sin cifrar.


Figura 2: WinRegMITM en GitHub

Se desarrolló una herramienta que permite aplicar de manera sencilla todas las técnicas que se encontraron.


WinregMITM: Simple Injection and Remote Fileless Payload Execution

Todo se basa en el protocolo de Registro Remoto de Windows. Este protocolo es utilizado para administrar almacenes jerárquicos de datos de manera remota, y en concreto, se utiliza para administrar el registro de Windows de una máquina remotamente. Si empezamos con el estudio del protocolo, una de las primeras cosas que se puede notar, es que en algunas ocasiones la información de los paquetes va cifrada y en otras ocasiones no. Empecemos centrándonos en el caso de uso en el que el payload de los paquetes va sin cifrar.

Cuando el cliente tiene distinto nombre o contraseña que el del servidor remoto (al que se le van a hacer cambios en el registro), la autenticación que realiza este protocolo se hace de manera manual, solicitado al cliente el usuario y la contraseña, y el payload de los paquetes va sin cifrar. Teniendo esto en cuenta se me planteó la siguiente pregunta, ¿sería posible capturar los paquetes del protocolo, modificarlos y reenviarlos? Todo esto “en el aire”, es decir, el mismo paquete que sale del cliente, es modificado, y es el que llega al servidor, sin que llegue ninguna réplica del mismo antes ni después.

Para comprobar si se realizaba algún tipo de control de integridad. Realizar estas modificaciones en los paquetes se convirtió en algo más complejo de lo que parecía ya que la capa que contiene la información que nos interesa (Remote Registry) se sitúa sobre otras capas complejas, y además no son interpretables por programas de procesamiento de paquetes como Scapy. Con lo cual, el primer problema complejo, es que tenemos que construir nuestro propio módulo que interprete los bytes en bruto de los paquetes para extraer los campos que nos interesen y modificarlos.

Figura 5: Paquete de Windows Remote Registry Service

Una vez realizado esto, llega la siguiente dificultad, una vez modificado un campo de la última capa todos los campos de control de las capas anteriores quedan inconsistentes, con lo que hay que extraer los bytes correspondientes (de la cadena de bytes que representan un paquete) a todos los campos de control de las capas anteriores, interpretarlos y modificarlos para que queden consistentes. Estos campos pueden ser longitudes, checksums, etcétera. Entre todas las capas que hay por encima (IP / TCP / NetBIOS / SMB2 / DCE-RPC ) hay aproximadamente 14 campos de control por extraer y recalcular.

Una vez modificados los campos de información que nos interesan, y recalculados los campos de control de las capas anteriores, uno podría pensar que el paquete está listo para ser reenviado al servidor remoto y que acepte el valor insertado por el atacante, pero esto no es así. Existe un factor que yo también pasé por alto la primera vez, y que me hizo comerme la cabeza unos días. En una sesión TCP/IP, se intercambian un conjunto de números de secuencia, y el cómputo de estos números de secuencia se basa en el tamaño del paquete, en concreto, en la siguiente expresión:
Next sequence number = Actual sequence number + TCP payload length (*)
(*) TCP payload length = length(IP) – length(IP.header) – length(TCP.header)
Con lo cual, si modificamos el tamaño del paquete en la mitad de la comunicación entre el cliente y el servidor, y cambiamos su tamaño, los números de secuencia empezarán a quedar inconsistentes y en consecuencia se romperá la sesión.

Para solucionar esto, lo que hice fue construir un algoritmo de corrección de estos números de secuencia, que una vez modificada la longitud de un paquete, fuera recalculando “en el aire” los números de secuencia para el cliente y el servidor de antes y después de modificar dicho paquete. De esta forma, cuando modifiquemos el tamaño de un paquete, iniciaremos una sesión TCP/IP simulada por mi algoritmo que mantendrá la conexión estable.

Figura 6: Aplicación de correcciones en la sesión TCP

Una vez tuve todo esto realizado, puede comprobar como no se hacía ningún control de integridad del contenido de los paquetes, y por lo tanto, se podían modificar a tu antojo, permitiendo entre otras cosas, la inserción remota de código en el registro de la máquina de la víctima, que puede provocar el compromiso de la misma con máximos privilegios, como se puede ver en el siguiente vídeo.

Figura 7: WinregMITM: Simple Injection and Remote Fileless Payload Execution

Por último, encontramos otra cosa muy interesante en relación al cifrado de la información que realiza el protocolo. Como hemos explicado, en ciertas ocasiones el protocolo cifra el payload de los paquetes que se intercambian, en concreto esto se realiza cuando tanto el cliente como el servidor que se están comunicando tienen el mismo usuario y contraseña. En la siguiente capturas del proceso de autenticación a nivel de paquete podemos comparar el paquete de una sesión cifrada y de una sin cifrar.

Figura 8: Paquete de autenticación sin cifrar
Figura 9: Paquete de autenticación cifrada

Podemos ver que la única diferencia radica en la respuesta a un paquete OpenKey por parte del servidor. En una conexión sin cifrar, el usuario no tiene permisos y le responde un fault, en una conexión cifrada le responde un success. Si inspeccionamos un poco más en profundidad el contenido de este paquete

Figura 10: Detalles del paquete

Podemos observar que las capas que cambian no contienen ningún tipo de información que identifiquen ese usuario concreto o esa sesión en concreta, todo eso está en capas superiores. Por lo tanto, ¿qúe sucedería si extraemos la capa DCE/RPC de un paquete fault y la sustituimos “en el aire” en una sesión que se supone que debe ir cifrada, por la capa DCE/RPC de la respuesta success? El resultado es que el usuario no nota absolutamente nada, pero la autenticación se realiza de manera distinta y el payload de los paquetes comienza a ir sin cifrar, como puede verse en el siguiente vídeo,

Figura 11: PoC de cómo se puede eliminar el cifrado con WinRegMITM

Como se puede ver en el video, adicionalmente al proceso de forzar la autenticación para que vaya sin cifrar, le añadí una característica a la herramienta para que permitiera romper una conexión en curso entre el cliente y el servidor, obligando al usuario a volver a autenticarse y en ese momento poder forzar que la sesión vaya sin cifrar.


Conclusión

Como conclusión, primero hay que indicar que la herramienta puede ser descargada de aquí, y se debe avisar de que este protocolo es utilizado comúnmente en algunas empresas para gestionar el registro de manera más cómoda, incluso si miras en tu ordenador corporativo, puede que el servicio este corriendo. Debido a los problemas presentados, esto puede poner en riesgo la seguridad de tu información, con lo cual, yo recomendaría desactivarlo o añadir otra capa de protección que permita garantizar la confidencialidad e integridad de los paquetes que se intercambian. Una medida más que debes tener en cuenta para fortificar tu Windows.