原理
Gopher是Internet上一个非常有名的信息查找系统,它将Internet上的文件组织成某种索引,很方便地将用户从Internet的一处带到另一处。在WWW出现之前,Gopher是Internet上最主要的信息检索工具,Gopher站点也是最主要的站点,使用tcp70端口。但在WWW出现后,Gopher失去了昔日的辉煌。现在它基本过时,人们很少再使用它;
gopher协议支持发出GET、POST请求:可以先截获get请求包和post请求包,在构成符合gopher协议的请求。gopher协议是ssrf利用中最强大的协议
限制:gopher协议在各个编程语言中的使用限制
–wite-curlwrappers:运用curl工具打开url流
curl使用curl --version查看版本以及支持的协议
Gopher协议格式:
URL:gopher://<host>:<port>/<gopher-path>_后接TCP数据流
- gopher的默认端口是70
- 如果发起post请求,回车换行需要使用%0d%0a,如果多个参数,参数之间的&也需要进行URL编码
Gopher发送请求HTTP GET请求:
使用Gopher协议发送一个请求,环境为:nc起一个监听,curl发送gopher请求
nc启动监听,监听2333端口:nc -lp 2333
使用curl发送http请求,命令为
root@kali ~# curl gopher://192.168.17.129:2333/abcd
此时nc收到的消息为:
root@Ubuntu ~# nc -lp 2333
bcd
可以发现url中的a没有被nc接受到,如果命令变为
root@kali ~# curl gopher://192.168.17.129:2333/_abcd
此时nc收到的消息为:
root@Ubuntu ~# nc -lp 2333
abcd
所以需要在使用gopher协议时在url后加入一个字符(该字符可随意写)
那么如何发送HTTP的请求呢?例如GET请求。此时我们联想到,直接发送一个原始的HTTP包不就可以吗?在gopher协议中发送HTTP的数据,需要以下三步:
1、构造HTTP数据包
2、URL编码、替换回车换行为%0d%0a
3、发送gopher协议
准备一个PHP代码
<?php
echo "Hello ".$_GET["name"]."\n"
?>
一个GET型的HTTP包,如下:
GET /ssrf.php?name=c0tfl0g HTTP/1.1
Host: 192.168.17.1
URL编码后为:
curl gopher://192.168.17.1:80/_GET%20/ssrf.php%3fname=c0tfl0g%20HTTP/1.1%0d%0AHost:%20192.168.17.1%0d%0A
在转换为URL编码时候有这么几个坑
1、问号(?)需要转码为URL编码,也就是%3f
2、回车换行要变为%0d%0a,但如果直接用工具转,可能只会有%0a
3、在HTTP包的最后要加%0d%0a,代表消息结束(具体可研究HTTP包结束)
Gopher发送请求HTTP POST请求:
发送POST请求前,先看下POST数据包的格式
POST /ssrf.php HTTP/1.1
host:192.168.17.1
name=c0tfl0g
那我们将上面的POST数据包进行URL编码并改为gopher协议
curl gopher://192.168.17.1:80/_POST%20/ssrf.php%20HTTP/1.1%0d%0AHost:192.168.17.10d%0A%0d%0Aname=c0tfl0g%0d%0A
ssrf.php的代码为
<?php
echo "Hello ".$_POST["name"]."\n"
?>
使用curl发起gopher的POST请求后,结果为
这里有个疑问:为什么发起了2次请求?为什么会把参数name=Margin当作一个请求?这个地方我调试了很久,发现问题出现在POST请求头中,我之前发POST请求都是直接用脚本,但从来没考虑过哪些参数是POST请求必须的,经过排查,发现有4个参数为必要参数(四个参数的含义不再赘述):
POST /ssrf.php HTTP/1.1
host:192.168.17.1
Content-Type:application/x-www-form-urlencoded
Content-Length:12
name=c0tfl0g
curl gopher://192.168.17.1:80/_POST%20/ssrf.php%20HTTP/1.1%0d%0AHost:192.168.17.1%0d%0AContent-Type:application/x-www-form-urlencoded%0d%0AContent-Length:12%0d%0A%0d%0Aname=c0tfl0g%0d%0A
发现请求正常,OK,那我们现在就介绍完了gopher协议的GET和POST请求。
Gopherus
此工具生成gopher链接,用于利用SSRF并在各种服务器中获取RCE
项目地址:https://github.com/tarunkant/Gopherus
使用方法
安装:
chmod +x install.sh
sudo ./install.sh
python gopherus.py -h
Command | Description |
---|---|
gopherus --help | Help |
gopherus --exploit | Arguments can be : |
–exploit mysql | |
–exploit postgresql | |
–exploit fastcgi | |
–exploit redis | |
–exploit zabbix | |
–exploit pymemcache | |
–exploit rbmemcache | |
–exploit phpmemcache | |
–exploit dmpmemcache | |
–exploit smtp |
参考文章与工具:
https://github.com/firebroo/sec_tools/tree/master/redis-over-gopher
https://xz.aliyun.com/t/5844
https://zhuanlan.zhihu.com/p/112055947