Recently, I have seen many interview experiences from experts, all asking about knowledge of the Gopher protocol’s attack surface. I previously used Gopher to exploit SSRF vulnerabilities but only at a basic level and wasn’t very familiar with it. (Today, I’ll summarize it while in an online class, as I’m quite the expert in skipping classes.)
What is the Gopher Protocol
The Gopher protocol is an ancient yet powerful protocol, which can be understood as the predecessor to the HTTP protocol. It can integrate and send multiple data packets. Via the Gopher protocol, one can attack internal network services like FTP, Telnet, Redis, Memcache, and also perform GET and POST requests.
Often in SSRF scenarios, we are unable to transmit POST data using the HTTP protocol, necessitating the use of the Gopher protocol to initiate POST requests.
The format for the Gopher protocol is as follows:
gopher://:/_
defaults to 70
Multiple requests should be separated with carriage return and line feed using %0d%0a. If there are multiple parameters, the & symbol should also be URL encoded.
However, usage of the Gopher protocol is limited in various programming languages.
Language |
Support Status |
---|---|
PHP |
–write-curlwrappers and PHP version must be at least 5.3 |
Java |
Less than JDK 1.7 |
Curl |
Not supported in lower versions |
Perl |
Supported |
ASP.NET |
Less than version 3 |
Sending Requests with Gopher
Curl
To get familiar with Gopher, I send a Gopher request using curl from my machine to my virtual machine.
Finally, the virtual machine starts nc to listen and receive messages.
Check the curl version to see if it supports the Gopher protocol.


Sending HTTP GET Requests via Gopher Protocol
When sending requests, Gopher requires URL encoding.
I prepare the following local PHP code
HTTP access and packet capture

HTTP GET packet details are as follows
GET /testg.php?name=xxx HTTP/1.1
Host: 10.211.55.2
Directly encode the data in Burpsuite for convenience.
Ensure to append %0d%0a at the end to signify the termination.

Burpsuite encoding results
%47%45%54%20%2f%74%65%73%74%67%2e%70%68%70%3f%6e%61%6d%65%3d%78%78%78%20%48%54%54%50%2f%31%2e%31%0d%0a%48%6f%73%74%3a%20%31%30%2e%32%31%31%2e%35%35%2e%32
Add %0d%0a manually at the end.
Convert to Gopher
curl gopher://10.211.55.2:80/_%47%45%54%20%2f%74%65%73%74%67%2e%70%68%70%3f%6e%61%6d%65%3d%78%78%78%20%48%54%54%50%2f%31%2e%31%0d%0a%48%6f%73%74%3a%20%31%30%2e%32%31%31%2e%35%35%2e%32%0d%0a

Sending HTTP POST Requests via Gopher Protocol
Here is the modified local code
When transmitting POST requests with the Gopher protocol, it is necessary to include these four elements along with a POST parameter.

Convert to Gopher
curl gopher://10.211.55.2:80/_%50%4f%53%54%20%2f%74%65%73%74%67%2e%70%68%70%20%48%54%54%50%2f%31%2e%31%0d%0a%48%6f%73%74%3a%20%31%30%2e%32%31%31%2e%35%35%2e%32%0d%0a%43%6f%6e%74%65%6e%74%2d%54%79%70%65%3a%20%61%70%70%6c%69%63%61%74%69%6f%6e%2f%78%2d%77%77%77%2d%66%6f%72%6d%2d%75%72%6c%65%6e%63%6f%64%65%64%0d%0a%43%6f%6e%74%65%6e%74%2d%4c%65%6e%67%74%68%3a%20%38%0d%0a%0d%0a%6e%61%6d%65%3d%78%78%78%0d%0a

SSRF Attacks Using the Gopher Protocol
Here is a question from CTFshow, exploiting the Gopher protocol to solve a question where there is an SSRF vulnerability.
Accessing MySQL With No Password
Regarding MySQL with no password
When MySQL client connects and logs into the server, there are two situations: requires password authentication and does not require password authentication. When password authentication is needed, it uses a challenge-response mode, where the server sends a salt, which the client uses to encrypt the password and then verifies; when no password authentication is required, TCP/IP data packets can be sent directly. Therefore, logging in and operating MySQL in non-interactive mode can only occur in the absence of password authentication and authorization. In this article, we exploit the SSRF vulnerability to attack MySQL under these unauthorized conditions.
An explanation of the problem-solving process.
Usually, attacking internal network applications via SSRF mainly involves protocols, with Gopher being a common choice.
Whether attacking Redis, MySQL, or FTP with Gopher, these attacks are primarily based on the TCP protocol. This relates to the basic format of the Gopher protocol, which we discussed earlier.
To attack MySQL, one needs to understand the TCP data stream used in MySQL communication to know how to communicate with MySQL. This can be analyzed using Wireshark packet capture, which we will discuss later.
https://github.com/tarunkant/Gopherus
This tool contains common Gopher packet format constructions for applications, with the principle being packet capture analysis using Wireshark, followed by scripting.

The payload is pasted into the returl parameter, and the content after the _ character in the generated POC must be URL encoded, as PHP decodes received POST or GET request data once.


Next is locating the flag.


Wireshark Capturing Raw 3306 Data Packets
Next, we’ll perform a local packet capture to demonstrate the tool’s principle.
Capture the TCP data stream when communicating with MySQL; here, we create a local MySQL user without a password
CREATE USER 'Sch0lar'@'localhost';
GRANT USAGE ON *.* TO 'Sch0lar'@'localhost';
GRANT ALL ON *.* TO 'Sch0lar'@'localhost';
Next, use tcpdump to capture the raw 3306 authentication packets:
# lo loopback interface card -w write pcapng packets
tcpdump -i lo port 3306 -w mysql.pcapng
Immediately connect to MySQL locally to test the commands
Then stop tcpdump and use Wireshark to open the mysql.pcapng
packet, trace the TCP stream, and filter out data sent to 3306:

There’s a pitfall when capturing packets. Normally, I couldn’t capture packets in Wireshark, and after researching a bit, I found the default SSL secure connection mode was likely causing us to be unable to capture packets,
--ssl-mode=disabled
disables SSL secure connection mode
Reconnect and capture packets.
(I read blogs from big names like Guo Guang and others, and they didn’t add --ssl-mode=disabled
and could still capture packets) Perhaps it’s due to MySQL version—higher versions might default to SSL secure connection.

Save as raw data and generate Gopher data stream

Generate Gopher data stream using the following script
import sys
def results(s):
a=[s[i:i+2] for i in range(0,len(s),2)]
return "curl gopher://127.0.0.1:3306/_%"+"%".join(a)
if __name__=="__main__":
s=sys.argv[1]
print(results(s))

This is roughly the workflow.
DatabaseCloud Database SQL ServerSQLLinuxProgramming Algorithms