security-breach-ruin
security-breach-ruin
Platform: Umdctf | Category: Network | Type: Challenge | Difficulty: Medium | OS: NA | Author: D3v0o0Nu11 | Date: 2026-04-25 | Status: Solved Techniques: arp_spoofing, median_based_bruteforce, mitm_packet_capture, tcp_length_oracle
Summary
Task: source code and shell access exposed an internal HTTPS dashboard where attacker-controlled filter text and the secret flag were gzip-compressed into the same JSON response. Solution: become on-path with bidirectional ARP spoofing, measure encrypted response sizes, and brute-force the flag with a BREACH-style length oracle.
Recon
Port scan
nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
| Port | Service | Version | Notes |
|---|---|---|---|
| <PORT> | <SVC> | <VER> | <notes> |
Enumeration highlights
- Event:
umdctf| ID:20260425_umdctf_security_breach_ruin - Tags: side_channel, mitm, gzip, https, arp_spoofing, compression_oracle, breach
- Indicators: secret and attacker-controlled input are compressed into the same response, an internal client polls the target endpoint at high frequency, HTTPS traffic is only reachable after becoming on-path with ARP spoofing, the correct guess produces slightly shorter encrypted responses
- Source:
20260425_umdctf_security_breach_ruin.md
Foothold
Vulnerability / Misconfiguration
- Arp_spoofing
- Median_based_bruteforce
- Mitm_packet_capture
- Tcp_length_oracle
<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
- N/A for challenge-type writeup; see exploitation above.
- Flag obtained via challenge solve.
<command>
Flags
| Flag | Location | Value |
|---|---|---|
| flag | REDACTED |
Key Takeaways / Lessons
- arp_spoofing
- median_based_bruteforce
- mitm_packet_capture
- tcp_length_oracle
- Tags: side_channel, mitm, gzip, https, arp_spoofing, compression_oracle, breach
Original Writeup
<details><summary>Click to expand original content</summary>Description
Recover the flag from the internal HTTPS dashboard using the provided source code and shell access on
10.0.0.3.
The challenge gave server.py, admin.py, and a shell on 10.0.0.3. A local helper exploit script also exists at tasks/umdctf/security-breach-ruin/solve.py.
Analysis
Reading the source showed a classic BREACH-style compression side channel. The server returned gzip-compressed JSON from /api/dashboard:
{"filter":"<attacker>","flag":"<secret>"}
The attacker controlled latest_suggestion through POST /api/suggestions, and the admin polled /api/dashboard over HTTPS about every 50 ms with Accept-Encoding including gzip. That meant a correct flag prefix inside filter should compress better against flag, making the encrypted response slightly shorter.
The first obstacle was visibility. Shell access was only on 10.0.0.3, and direct sniffing failed because unicast traffic between 10.0.0.1 (admin) and 10.0.0.2 (server) was not naturally visible from our host.
Exploit Summary
I used bidirectional ARP spoofing to become the man in the middle:
arpspoof -t 10.0.0.1 10.0.0.2 arpspoof -t 10.0.0.2 10.0.0.1
With IP forwarding already enabled, tcpdump could then capture the inbound HTTPS packets. The oracle was built by summing server -> admin TCP payload lengths between consecutive admin -> server request packets. When the guessed prefix was correct, gzip achieved a better match and the encrypted response became smaller.
To recover the flag reliably, I brute-forced characters from [a-z0-9_}] starting from the known prefix UMDCTF{. Because packet sizes were noisy, each candidate was measured across repeated admin polls and ranked by median response length.
Solution
- Read
server.pyandadmin.pyand identify the gzip compression oracle in/api/dashboard. - Notice that plain packet sniffing on
10.0.0.3does not reveal the10.0.0.1 <-> 10.0.0.2HTTPS flow. - Launch ARP spoofing in both directions so the admin and server route traffic through the player host.
- Capture inbound packets with
tcpdumpwhile repeatedly submitting candidate prefixes throughPOST /api/suggestions. - For each guess, sum the
server -> adminTCP payload sizes until the next admin poll begins. - Choose the candidate with the smallest median size, append it to the known prefix, and repeat until
}is found.
</details>#!/usr/bin/env python3 # See tasks/umdctf/security-breach-ruin/solve.py
Auto-tracked: saved to WriteUps; run
/xesor-reviseto fold lessons into XESXor_Methodology.md.
signed by XESXOR