Proxy
hackthebox
A custom HTTP proxy written in Go that forwards requests to an internal Node.js backend. The goal is to exploit vulnerabilities to achieve command injection and read the flag.
$ ls tags/ techniques/
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
Proxy - HackTheBox
Description
A custom HTTP proxy written in Go that forwards requests to an internal Node.js backend. The goal is to exploit vulnerabilities to achieve command injection and read the flag.
Architecture:
- Go Proxy (port 1337): Custom HTTP proxy with SSRF protections and URL filtering
- Node.js Backend (port 5000): Express app with
ip-wrapperpackage that has command injection vulnerability in/flushInterfaceendpoint
Analysis
Architecture Overview
The challenge presents a multi-layered architecture requiring multiple bypass techniques:
[Attacker] --> [Go Proxy :1337] --> [Node.js Backend :5000]
| |
- SSRF blacklist - /flushInterface
- URL filter - Command injection
- Body filter in ip-wrapper
Vulnerability Chain
To exploit this challenge, we need to bypass multiple security layers:
- SSRF Protection - Blacklist of internal IP addresses
- URL Filter - Blocks requests to
/flushinterface - Body Filter - Blocks dangerous characters in request body
- Backend Validation - Validates interface name format
1. SSRF Blacklist Analysis
The Go proxy blacklists common internal IP patterns in the Host header:
localhost0.0.0.0127.(prefix)172.(prefix)192.(prefix)10.(prefix)
Key observation: The blacklist checks for 192. (with dot), but DNS wildcard services like nip.io use dashes.
2. URL Filter Analysis
The proxy uses strings.ToLower() to normalize URLs before checking for blocked patterns:
if strings.Contains(strings.ToLower(url), "flushinterface") { // Block request }
Key observation: Go's strings.ToLower() uses simple ASCII lowercasing, not Unicode-aware case folding.
3. Body Parsing Vulnerability
The proxy splits the request body on \r\n\r\n:
bodySplit = strings.Split(requestBytes, "\r\n\r\n") // Only validates bodySplit[1] (first body segment)
Key observation: If we send multiple body segments, only the first is validated, but ALL raw bytes are forwarded to the backend.
...
$ grep --similar
Similar writeups
- [web][free]DoxPit— hackthebox
- [web][free]Dusty Alleys— hackthebox
- [web][free]Desires— HackTheBox
- [web][Pro]Lab 406 — PingRelay — Prototype Pollution to SSRF via CRLF Header Injection— hackadvisor
- [web][free]Tiny Web smol— gpnctf