1. 从漏洞第一现场说起:SSRF 的本质拆解
先说一个我常用的比喻:如果普通 Web 漏洞是“你被骗着交了密码”,那 SSRF(Server-Side Request Forgery,服务端请求伪造)就是“你被骗着替别人跑腿送信”。攻击者并不直接接触内网,而是通过一个“会出外勤”的服务端功能,让它去请求攻击者指定的地址。而这个功能恰恰是很多系统里最不起眼、但也最容易被忽略的部分:比如 URL 参数、图片裁剪、网页截图、PDF 导出、Webhook 回调、页面转码等等。
在我接触过的项目里,SSRF 之所以难修、难挖,是因为它不像 SQL 注入那样有一个相对固定的“注入点”。它是一个逻辑型漏洞,隐藏在“服务端有没有按你的意思去发请求”这条链路里。它可能出现在:
- 用户提交一个网址,服务器去抓取并生成封面;
- 用户提交一个 IP,服务器去查询“主机状态”;
- 用户提交一段 SVG/HTML,服务器去无头浏览器渲染;
- 用户提交一个回调地址,服务器用来接收事件通知。
判断一个点是否可能存在 SSRF,核心就一句话:服务端是否接收任何一个“会被当作地址/目标”的输入,并主动发起了网络请求。如果答案是“是”,那这就是需要重点排查的候选位。
而深度利用方面,SSRF 的价值也分层级。最基础的是读取内网未授权接口、访问云元数据服务,进一步则是配合 Gopher 这类协议打 Redis、打 MySQL、打应用层未授权服务,再往上,如果响应不可见,还可以通过各种带外信号把“看不到”变成“看得到”。下面我逐一拆解,最后放一个完整的实操靶场流程。
1.1 SSRF 为什么危险:服务端替你发请求
很多刚上手的朋友会有一个疑问:“不就是让服务器访问了一个地址吗?有什么不能访问的?”问题在于,服务器和你不一样,它在网络里的位置很特别。
第一,服务端是内网的一部分。它可能可以访问10.x.x.x、172.16.x.x这类内网网段。而这些地址对于外部攻击者来说往往不可达。如果服务端没有做严格的访问限制,你就能用“它替你请求”的方式,去看内网里的东西。
第二,服务端可能持有本地云角色凭证。现代云环境下,几乎每个计算实例都有一个“元数据服务”,一般在类似169.254.169.254的地址。如果 SSRF 能打出这个地址,就可以拿到临时凭证。这就不是“看一眼内网”那么简单了,而是拿到一个能够在云环境内横向移动的身份。
第三,服务端可以到达的不仅仅有 HTTP 服务。Gopher、Dict、FTP、LDAP 这类协议注册的端口也可能被命中。很多内网数据库、缓存、消息队列默认没有强认证,一旦被 SSRF 组合打穿,后果远大于一个普通信息泄露。
这也是为什么很多企业把 SSRF 视为高危甚至严重级别漏洞。它不只是一个“请求跳转”,而是攻击者拿到了“服务端的网络身份”作为代理。在授权测试中,遇到 SSRF 时,我的习惯是先判断“我能让服务器往哪打”,再判断“我能拿到什么响应”,最后才考虑“怎么利用”。
1.2 三种典型形态:有回显、半回显、无回显
SSRF 的利用方式很大程度取决于你能否看到响应内容。我在实际测试时会把情况分成三类:
- 有回显形态:服务器把你请求的响应内容直接渲染在页面上。比如网页截图服务截取目标页面,或图片代理把目标图片返回给用户。这个形态最好用,可以直接读取内网页面的内容。但要注意,所谓“回显”也不是百分百完整,有各种编码、转义问题。
- 半回显形态:服务器不把完整响应返回,但会暴露一些信息,比如报错里包含响应状态码、响应头,或者某个业务逻辑会因响应内容不同而出现差异。这种形态需要仔细“审问”服务器,通过错误信息、状态码差异来一点点还原内部情况。
- 无回显形态:服务器发出请求,但你没有看到任何结果。端口探测的“时间差”是你为数不多的信号。实际上,无回显是渗透测试中非常常见的情况,很多业务系统在抓取 URL 之后只返回一个 OK,或者什么都不返回。
认清形态很重要,因为它决定了后续的打法。我见过不少测试者拿一个无回显的 SSRF 去验证 Redis 攻击,结果发现半天没有回包就以为失败了,实际上载荷可能已经执行成功,只是没有回显而已。后面我会专门讲无回显形态下怎么建立“盲信号通道”。
1.3 攻击面在哪里:从参数到逻辑的排查路径
测试 SSRF 不是漫无目的地随便翻参数。我一般按两条路径去排查。
第一条是找“URL 型参数”。通篇扫描所有输入参数,凡是可以填一个网址、域名、IP、端口的参数,都可能是候选。比如?url=、?src=、?target=、?callback=、?redirect=、?page=等等。即使是 JSON 包里嵌套的子字段,也可能被服务端拿去请求,所以不能只看查询字符串。
第二条是找“文件处理型逻辑”。比如头像上传时,如果允许传“图片 URL”,服务器先下载再处理,那就是一个很典型的 SSRF 位。还有 PDF 生成器,如果可以把一个外部链接“导入”成页面,那服务端就会去访问那个链接。这些功能在功能测试时往往不容易被注意到,反而是安全测试的高优先级目标。
除此之外,301/302 跳转也是一个容易被忽略的扩展点。很多开发者只校验了第一个请求的域名,但实际上服务端可能跟着跳转,而被跳转到的地址完全不受最初校验的限制。我在实际测试中遇到过只校验www.example.com的情况,但如果让服务器访问www.example.com,它跳转到了内网或云元数据地址,校验就被绕过了。这属于“校验了入口,却没有校验出口”的经典缺陷。
2. Gopher 伪协议:把攻击面拉满的协议技巧
如果 SSRF 只能发 HTTP 请求,那它的攻击面其实是受限的。因为 HTTP 请求需要服务端有对应的应用逻辑去处理,否则很难扩大战果。但 Gopher 协议的存在,把这件事的层次拉高了不少。这也是很多新手在入门 SSRF 时觉得最“卡”的一个知识点,所以有必要单独讲清楚。
2.1 为什么偏偏是 Gopher
Gopher 是一个非常古老的协议,比 HTTP 还要早。它的核心特点非常“朴素”:Gopher 客户端会把 URL 里 path 部分对应的数据,原封不动地发送给目标服务器。注意,是原始的字节流,没有任何一层封装、转义或者协议内转换。
正因为有这个“透明传输”特性,Gopher 在 SSRF 利用中的价值变成了:你可以用它“伪造”任意基于 TCP 的文本协议请求。HTTP 只是其中之一,Redis 的 RESP 命令、MySQL 的握手包、Memcached 的文本协议、SMTP 的命令,只要目标端口开放并且协议是文本型的,理论上都可以通过 Gopher 去“代打”。
我举一个直观的例子。Redis 默认监听 6379,很多内网环境里它没有设置密码,或者只绑定内网网卡。攻击者的外部主机无法直接访问,但是 SSRF 所在的服务端可以。那么通过 Gopher 构造一个 Redis 命令序列,就能让服务端去“执行”这些命令。最常见的是往目标网站目录写入一个 webshell,或者把公钥写入目标主机的authorized_keys,从而直接获得服务器权限。这个链路的中间人,就是 Gopher 协议。
所以 Gopher 的意义不是“多了一种协议可打”,而是它把“SSRF 只能打 HTTP 功能”扩展到了“SSRF 可以打几乎任何 TCP 服务”。攻击面一下子开阔了很多,这在授权测试中尤其值得关注。
2.2 构造 Gopher 载荷的完整思路
既然 Gopher 的核心是“原样发送”,那构造载荷的关键就是让发送出去的字节流符合目标服务协议的格式。我这里以打 Redis 为例,给出完整的构造思路。
Redis 是一个文本协议,客户端和服务器之间通过*和$组成的数组格式来传递命令。比如SET mykey myvalue这个命令,在 RESP 协议里长这样:
*3 $3 SET $5 mykey $7 myvalue每行末尾需要用\r\n分隔。如果我要让 Gopher 替我去发这段数据,就需要把它套进 Gopher URL 的格式里。标准格式是:
gopher://目标IP:端口/_后面跟着要发送的数据_是一个常见的分隔符,实际发送时它会被替换成空字符串,后面的数据会原样发送给目标。然后需要把所有控制字符做 URL 编码:
SET mykey myvalue经过切分和编码之后,大概是:
gopher://127.0.0.1:6379/_*3%0d%0a$3%0d%0aSET%0d%0a$5%0d%0amykey%0d%0a$7%0d%0amyvalue%0d%0a注意,%0d%0a就是\r\n的 URL 编码。这里有个非常容易踩坑的点:HTTP URL 本身也会对特殊字符做编码,如果整条 Gopher URL 作为参数传给 SSRF 时,就容易出现二次编码问题。也就是说,目标代码里如果用了urlparse或类似组件处理参数,你精心构造的%0d%0a可能会被再编码一次,变成%250d%250a,那 Redis 收到的就不是换行,而是一串无意义的字符。
我建议的实操顺序是:先在本地用模拟环境把 Gopher 载荷测试通过,再放进 SSRF 参数里做整体调试。具体做法后面实操环节我会展开。这里先把构造思路说清楚:协议原文 → 按协议格式换行 → URL 编码 → 拼接 Gopher URL。每一步都要知道自己在做什么,而不是只会用现成脚本。
2.3 协议白名单下的取舍与变通
不少系统会做协议白名单,只允许http和https,那就意味着直接用 Gopher 这条路被封死了。但这不等于 SSRF 束手无策,我总结了几种常见的变通思路。
一种是利用 HTTP 的 30x 跳转。有些系统的协议白名单只检查初始请求的 scheme,并没有阻止后续的跳转。如果目标服务端跟随 301/302,那你完全可以把一个允许的 HTTP 网址做成跳转器,让它最终跳到gopher://地址。我见过一些实现里对跳转次数和目标协议没有做二次限制,这样就轻松绕过了入口校验。
另一种是正确的协议构造。有些服务端会用“按端口推断协议”的方式做白名单,比如只允许 80 和 443 端口。但 Redis 默认是 6379 端口,那可以把 Redis 的端口手动改成 80 或者 443,不少自建环境里真的会这么配置。还有一个思路是使用dict://协议,它能够向指定端口发送“空格分隔的命令”,在探测一些简单协议的端口时非常好用,缺点是它不适合复杂命令,因为协议层本身对数据格式有封装,不能完全替代 Gopher。
另外一种在较新环境中常见的手法,是借助有漏洞的 HTTP 层服务来“中转”。有些内网应用本身存在“二次 SSRF”,它会把收到的某个参数当作下一个请求目标。这时从入口进入后,通过这个应用再跳出去,就形成了链式利用。整个链路看起来比较曲折,但在真实环境中并不罕见。
3. 无回显利用:看不见响应时怎么打
我觉得这一节是最有实操价值的部分。很多人学 SSRF 时看的都是“有回显直接读文件”的爽文案例,一遇到无回显就不知道怎么办了。其实无回显并不是死胡同,而是要换一套信息提取思路:把“看响应”变为“看副作用”。核心原则是:想办法让服务器在发起请求之后,留下某种你能观察到的“痕迹”。下面几种方式是我实测中反复用到的。
3.1 带外判断通道:DNS 日志与外部请求
最常见的无回显判断手段是“带外通道”,英文一般叫 OOB(Out-of-Band)。原理非常简单:让 SSRF 发起一个请求到一个你能够控制日志的外部域名,然后你观察这个域名是否收到了 DNS 解析请求或 HTTP 请求。
比如,我有一台自己控制的服务器,配置好某个域名oob.example的子域名解析记录。只要 SSRF 发出请求访问probe1.oob.example,我的 DNS 服务器上就会留下一条解析记录。不管响应是否回显,这一条记录就足以告诉我:服务端确实发出了请求,而且请求携带的路径、参数、所在 IP 全都暴露在 DNS 日志里。
无回显场景下判断网络连通性,我习惯先打一次 DNS 解析,再打一次 HTTP 请求:
- 如果只收到 DNS 解析记录,说明服务端至少做了 DNS 解析,可能后续连接被网络策略拦截;
- 如果还收到了 HTTP 请求,说明服务端真正发起了 TCP 连接,甚至发送了完整 HTTP 请求;
- 如果连 DNS 解析都没有,那就要怀疑参数本身没有被服务端当作 URL 处理,或者参数名不对。
带外通道不仅能用于判断漏洞存在,也能用于数据外带。比如在内网读到的文件内容,可以通过把内容作为域名/子域名的前缀拼接到带外域名上,再通过 DNS 解析记录把内容带回来。比如目标内网有个文件叫/etc/passwd,你把它读出来,然后把第一个字符作为子域前缀请求一次,DNS 日志里就能看到。虽然一次只能带一点数据,但在无回显场景下,这就是一条可靠的数据通路。
3.2 时间差测量:用响应时长当“眼睛”
除了带外通道,时间差是另一种非常实用的盲信号。很多协议在连接不同端口或发送不同数据时,响应时间有明显差异。这种差异可以被当作一种“二进制信号”来使用:是/否、通/不通、匹配/不匹配。
比如我想探测内网某个 IP 的端口开放情况,可以直接构造一个带有连接超时差异的请求。如果端口开放,服务端会在短时间内返回某种协议响应(比如 RST 或完整握手);如果端口不通,服务端需要等待 TCP 超时才会返回错误。这个时间差有时候差几百毫秒,在多次测量下会比较明显。
再比如通过 SSRF 访问一个内网 URL,如果路径存在且响应内容大,耗时相对长一些;如果路径不存在返回 404,耗时就会短。这种差异看起来很小,但放在自动化里做多轮测量,就能比较稳定地判断目标路径是否存在。
时间差测试需要注意的是:网络抖动可能带来很多噪声。我一般会连续测量 5 次以上,取中位数,而不是看单次结果。另外,如果目标服务端本身有缓存层,第一次请求和后续请求的耗时差异很大,那就要特别注意控制变量,尽量保证同一个请求被同等处理。
3.3 盲打与少回显:利用错误信息、内容差异与测信道
无回显的另一种“变体”是少回显,也就是服务器不会返回完整响应,但会返回状态码、响应时间、报错信息、甚至Content-Length的差异。这个“少回显”经常被忽视,但它其实是很好的探测信号。
举个例子。目标有一个网页截图服务,它在截图失败时返回的错误信息里可能包含目标服务器的响应码:比如upstream connect error: Connection refused和upstream connect error: 404 Not Found,这两者返回的错误描述是不同的。虽然你没有拿到目标页面的正文,但状态码已经告诉了你目标服务是否开放、路径是否存在。把这些信息组合起来,完全可以在无回显条件下完成一次比较完整的资产盘活。
另外,还有一种偏测信道的思路,那就是“布尔条件 + 时间差”组合。打个比方:先让服务端去做一次请求,如果这个请求的响应里包含某个特定字符串,那么服务端继续执行一个耗时操作(比如 SLEEP 几秒);如果不包含,则立刻返回。这样看起来服务端完全没有回显内容,但你通过响应时长的长短,就能推断出目标响应的内容特征。这在利用某些 HTTP 客户端库的“自定义请求后处理逻辑”时能够实现。
这类思路在实战中不一定每次都成立,因为需要目标代码里存在“根据响应内容做不同处理”的逻辑。但作为排查链路的一部分,我通常会在初步判断出目标是一个无回显 SSRF 时,先验证它是否支持这种“条件差异”。往往在深入测试几个点之后,会发现原本以为的“无回显”其实存在一个非常窄的信息通道。
3.4 收集信息的替代手段:从日志与流量反推
还有一种经常被忽略的手段:利用目标系统本身的日志、监控、审计能力来反推攻击效果。比如 SSRF 打到了内网的 Redis,虽然没有回显,但如果你后续能看一眼 Redis 的日志,或者目标站点能通过某种方式暴露出被写入的文件访问情况,那么就相当于间接回显了。
真实场景中,我遇到过一种情况:SSRF 无回显,但是目标站点会定期把某些内网服务的数据聚合到一个页面上。我通过 SSRF 修改了内网某个服务的数据,然后去刷新聚合页面,发现内容变了。这就等于用“目标自身的业务页面”作为回显通道。
这个思路总结成一句话:不要只盯着“当前请求的响应”,要把“请求产生的后果”当成一种信号来源。在无回显场景下,这个“后果”可能是:
- 目标页面的内容发生变化;
- 目标系统的日志里多了一条记录;
- 目标服务的状态发生变化(比如端口关闭、进程退出);
- 目标文件系统里多了一个文件;
- 目标数据库里多了一条数据。
这些后果只要有一个能被你观察到,无回显就等于被打开了口子。实际测试时,我甚至会故意去打一些“无害修改型”的请求,然后观察目标是否出现可见变化,以此建立通道。
4. 实操演练:一个最小靶场的完整复现
前面讲了很多理论,但 SSRF 这种东西,光看原理是学不会的。我在这里搭一个最小的可重复实验环境,把从探测到利用到盲打的全过程走一遍。你可以按照这个流程在自己本机复现,作为学习的基础场景。
4.1 搭建可控的环境与靶标模拟
我不会直接说明某个商业产品的配置,而是用一个自己写的最小服务来模拟脆弱点。这样你能清楚看到每一层是怎么处理的,也方便后续改造成其他协议。
为了安全,我把所有实验限制在本地回环地址127.0.0.1和自定义内网地址段内,不涉及任何外部真实系统。靶场结构大致是三台“逻辑机”:
- 一台模拟“边缘应用”,对外提供一个 URL 抓取接口;
- 一台模拟“内网 Redis 服务”,端口 6379,没有密码,绑定在自定义内网网段;
- 一台模拟“带外日志平台”,接收 DNS/HTTP 请求,用于无回显观察。
边缘应用的简化逻辑可以这样描述:接收?target=参数,把它交给 HTTP 客户端去请求,然后返回响应内容的前 200 字节。这就是一个典型的“有回显” SSRF。后续我会再加一层“只返回 OK”的逻辑,模拟无回显。
创建环境时,我用 vagrant 或者本地容器方式启动三台“逻辑机”,并自定义虚拟网段。这里的关键是让边缘应用可以访问到 Redis 所在的内网网段,同时又不能从外部直接访问。这样才符合 SSRF 的真实场景。
4.2 从探测到利用的完整流程
第一步:确认参数是否可被利用。我的习惯是先打一个自己可控的 HTTP 服务。如果边缘应用返回了你 HTTP 服务响应里的特征内容,那就说明这个参数确实能被服务端请求。如果返回的是空白或 OK,也不代表没有,要继续用带外通道确认。
请求示例: [边缘应用]/?target=http://myhost/oob_test_123 观察:myhost 上是否收到 /oob_test_123 的请求?第二步:探测端口与协议。在确认参数可控后,尝试访问内网地址。先探测 Redis 端口是否开放:
请求示例: [边缘应用]/?target=http://127.0.0.1:6379 观察:响应内容里是否包含 Redis 版本、错误信息等。如果这里拿到的是Connection refused,那就说明端口不通;如果返回的是 Redis 的-ERR unknown command之类的信息,说明端口开放。
第三步:构造 Gopher 载荷并发送。以写入一个 webshell 为例,我需要构造一段 RESP 命令序列。先选定一个可以写入的绝对路径。Redis 的写文件一般用CONFIG SET dir和CONFIG SET dbfilename,然后通过SET命令触发写盘。那么 RESP 序列大致是:
*4 $6 CONFIG $3 SET $3 dir $13 /www/wwwroot/然后再构造一个写入内容的命令。整个过程需要在本地先用脚本生成 Gopher URL,然后放进边缘应用的目标参数里。注意,这一步一定要先本地模拟验证,因为一旦写入路径不对或内容格式不对,就会破坏 Redis 数据,影响后续实验。
第四步:确认利用结果。有回显场景下,直接尝试访问 webshell 即可。无回显场景下,我会用一个“再探测”的手段:如果写入成功,Redis 的响应会发生变化,或者目标 Web 服务器会出现新的文件,这个变化可以通过再次请求边缘应用的某个功能来间接观察。
4.3 几个反复踩过的坑与排查手册
这里整理一些我实操过程中踩过、也帮别人排查过的典型坑,以表格形式列出来,方便对照。
| 现象 | 可能原因 | 排查思路 |
|---|---|---|
| Gopher 发出去后目标无反应 | 载荷中换行符被二次编码 | 检查 URL 编码是否为%0d%0a,而不是%250d%250a;在本地模拟先测试载荷 |
| 带外只收到 DNS 没收到 HTTP | 服务端做了协议限制或网络策略 | 确认目标实现是否能真正发起 HTTP 请求;尝试换端口、换协议 |
| 打 Redis 后 Redis 拒绝连接 | 写盘命令导致 Redis 进程崩溃 | 查看 Redis 日志;确认写入路径有写权限;优先用更轻量的命令验证连通性 |
| 无回显判断不出漏洞 | 参数名不对,或服务端做了 URL 解码后的校验 | 先用多个参数名批量测试,再配合带外通道确认 |
| 服务端跟随跳转导致校验绕过失败 | 开发者在校验后没有控制跳转 | 利用这一点构造中间跳转地址,指向内网目标 |
在无回显场景下,最需要耐心。我的做法是每做一个操作前,先想清楚:如果这个操作成功,会产生什么样的可观察副作用?如果没有,这个操作就不值得做。宁可慢一点,也不要到处乱试,否则很容易在对目标系统造成不可逆影响的同时,一点有效信号都拿不到。
5. 防御视角:为什么修复常常不到位
很多人以为 SSRF 的修复很简单:加个黑名单、限制 IP 段、校验 URL 就行。但实际操作中,修复遗漏点非常多。我见过的失败案例大致有这几类。
5.1 常见过滤方案的漏洞点
第一类是“黑名单校验”,这是最脆弱的。很多系统只拦了127.0.0.1、localhost,但完全忽略了127.0.0.0/8整个网段、IPv6 地址、十进制/十六进制 IP 写法、短域名、DNS 重绑定等变体。例如2130706433就是127.0.0.1的十进制表示,不少黑名单根本识别不出来。同样,[::1]也是回环地址,如果解析器支持 IPv6,黑名单形同虚设。
第二类是“域名白名单校验,但没校验跳转”。这是非常常见的情况。入口判定域名合法,但请求发出后跟随了 301/302,跳转到一个完全不合法的高风险地址。如果实现里没有对每一次跳转做校验,这个白名单就是个摆设。
第三类是“只校验了 scheme,没校验资源位置”。比如允许file://或dict://,那问题就大了。前文提到的 Gopher 之所以能打出效果,往往就是因为 scheme 校验不完整。
5.2 分层防御的组合拳设计
与其依赖单一修复点,我更推荐分层防御,每一层都承担一部分职责,即使某一层被绕过,后续层仍然能够兜底。
第一层是入口校验:对用户输入的 URL 做完整的 scheme、host、端口白名单。这一层目标是拦截明显不合规的请求。第二层是出口控制:把服务端发起请求的能力限制在一个可控的网络区域,比如通过防火墙或安全组,只允许边缘应用访问特定的目标服务。这样即使 SSRF 存在,攻击者也很难打通到敏感资产。第三层是应用层对响应的处理:不在页面里直接透传服务端响应内容,限制响应长度、过滤错误信息,降低利用者拿到有效信息的可能性。
另外我特别推荐在架构层面尽量减少“无脑请求外部 URL”的功能。比如网页截图服务、PDF 导出服务这类高危险功能,如果一定要做,最好在一个独立的环境中运行,不带云凭证,网络访问权限最小化,并且设置严格的资源配额和请求超时。很多时候,SSRF 之所以造成严重破坏,并不是因为漏洞本身多高级,而是因为出问题的服务本身权限太大、位置太核心。
5.3 修复后如何验漏
修复不是改完代码就完事,还需要验证。我建议在修复后做一轮针对性的回归测试,重点覆盖以下场景:
- 常见回环地址变体:
127.0.0.1、127.0.0.2、0.0.0.0、[::1]、十进制 IP、十六进制 IP; - DNS 重绑定:绑定一个域名,第一次解析返回白名单地址,第二次解析返回内网地址;
- 30x 跳转:白名单域名跳到内网地址;
- 协议变体:
gopher://、dict://、file://、ftp://; - 非标准端口:把内网服务映射到 80/443 端口;
- 半回显信息泄露:确认错误信息里不包含目标响应状态码或头信息。
每一步都要实际打一遍,确认防护确实挡住了。不要只写一个单元测试就收工,因为 SSRF 涉及的外部解析、DNS 重绑定、网络拓扑等因素很难完全靠单元测试覆盖。实战验证才是更可靠的检验方式。
我在实际项目里的体会是:SSRF 是一个越深入研究越会觉得它“无底”的方向,它不像某些漏洞一样有固定的答案和模板,而是要充分理解业务逻辑、网络环境、协议栈以及服务端的使用方式。很多人学了几天就觉得会了,可一到真实环境就发现根本没有回显、协议也被限制,这时功夫就体现在你对协议细节和盲信号通道的把握上。如果你把这篇文章里的方法吃透,至少再去遇到“无回显”的场景时,不会一下子就放弃了。
另外再分享一个小建议:测试 SSRF 时,每打一个目标前,先在本地做一个同构模拟环境,把请求原样重放一遍,观察目标程序的行为。这样你不仅知道漏洞怎么打,还能理解为什么打不通、卡在哪一层。很多高级技巧其实都是在“本地重放 + 真实环境对比”的过程中悟出来的。