← Back to Writeups
HTBN/AWeb

Flag Admin v1

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

Flag Admin v1

Platform: Web Kids20 | Category: Web | Type: Challenge | Difficulty: Easy | OS: NA | Author: D3v0o0Nu11 | Date: 2026-03-11 | Status: Solved Techniques: custom_header_injection, js_deobfuscation, modpow_bruteforce

Summary

URL: http://kslweb1.spb.ctf.su/burp/header/

Recon

Port scan

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

Enumeration highlights

  • Event: web-kids20 | ID: 20260311_web_kids20_webburp_header
  • Tags: rc4, burp_suite, http_headers, javascript_obfuscation, modular_exponentiation
  • Indicators: X-Custom-Object header required, obfuscated admin.js, RC4 encrypted string array, challenge-response protocol
  • Source: 20260311_web_kids20_webburp_header.md

Foothold

Vulnerability / Misconfiguration

  1. Custom_header_injection
  2. Js_deobfuscation
  3. Modpow_bruteforce
<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

  • custom_header_injection
  • js_deobfuscation
  • modpow_bruteforce
  • Tags: rc4, burp_suite, http_headers, javascript_obfuscation, modular_exponentiation

Original Writeup

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

Description

"How to add this header?" — The page instructs to send the header X-Custom-Object: flag to get the flag.

URL: http://kslweb1.spb.ctf.su/burp/header/

Analysis

The page contains a "Get the flag" button and a hint about needing to send the X-Custom-Object: flag header. The admin.js file is heavily obfuscated:

  • RC4-encrypted string array
  • Anti-debugging protection
  • String access function b(index, key)

Analysis of the deobfuscated code reveals a challenge-response protocol:

  1. Server returns a challenge (number)
  2. Client must find gamma and beta such that pow(gamma, beta) mod 31337 == challenge
  3. Server verifies the solution and returns the flag ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Solution

Step 1: First request — getting the challenge

POST request to handler.php with parameter method=init and header X-Custom-Object: flag:

POST /burp/header/handler.php HTTP/1.1
Host: kslweb1.spb.ctf.su
X-Custom-Object: flag
Content-Type: application/x-www-form-urlencoded

method=init

Server returns the challenge value (a number).

Step 2: Computing the solution

Modular exponentiation implementation from JS:

def modpow(base, exp, mod=31337):
    if exp == 0:
        return 1
    if exp % 2 == 0:
        t = modpow(base, exp // 2, mod)
        return (t * t) % mod
    else:
        return (modpow(base, exp - 1, mod) * base) % mod

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

Bruteforce gamma (range ~200-400) and beta (range ~200-600):

def find_solution(challenge):
    for gamma in range(200, 400):
        for beta in range(200, 600):
            if modpow(gamma, beta) == challenge:
                return gamma, beta
    return None, None

Step 3: Second request — getting the flag

POST request with the found values:

POST /burp/header/handler.php HTTP/1.1
Host: kslweb1.spb.ctf.su
X-Custom-Object: flag
Content-Type: application/x-www-form-urlencoded
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

method=flag&gamma=<value>&beta=<value>

Full solve script

#!/usr/bin/env python3
import requests

URL = "http://kslweb1.spb.ctf.su/burp/header/handler.php"
HEADERS = {"X-Custom-Object": "flag"}

def modpow(base, exp, mod=31337):
    if exp == 0:
        return 1
    if exp % 2 == 0:
        t = modpow(base, exp // 2, mod)
        return (t * t) % mod
    else:
        return (modpow(base, exp - 1, mod) * base) % mod

def find_solution(challenge):
    for gamma in range(200, 400):
        for beta in range(200, 600):
            if modpow(gamma, beta) == challenge:
                return gamma, beta
    return None, None
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

# Step 1: Get challenge
r = requests.post(URL, headers=HEADERS, data={"method": "init"})
challenge = int(r.text.strip())
print(f"Challenge: {challenge}")

# Step 2: Find solution
gamma, beta = find_solution(challenge)
print(f"Solution: gamma={gamma}, beta={beta}")

# Step 3: Get flag
r = requests.post(URL, headers=HEADERS, data={
    "method": "flag",
    "gamma": gamma,
    "beta": beta
})
print(f"Flag: {r.text}")

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

</details>

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

signed by XESXOR