0x01 故事背景
在现代 Web 架构中,支付网关往往被视为防守最严密的堡垒。各种 WAF、风控策略和签名校验将外部攻击者拒之门外。但是,如果系统主动向外发起请求呢?
这次我发现的漏洞,正是潜伏在这样一个看似无害的功能里。它不仅能让外部攻击者伪造服务器身份发起请求,甚至还能通过极其微弱的“时间差”,悄无声息地探测目标内网的脆弱服务。这是一场没有回显的盲打,也是一次利用服务器本能反应完成的“内网扫描”。
0x02 信息收集
一切起源于支付模拟器(Payment Simulator)中的一个二维码测试功能。
在浏览 https://sandbox.example-pay.com/v2/qr/index 时,我注意到页面允许开发者输入一个外部的二维码图片 URL,以便平台拉取该图片进行内容解析。
看到 URL 这个词,我的安全直觉(Spider-sense)瞬间就拉满了。任何允许用户输入 URL 并由服务端去抓取的功能,都是潜在的 SSRF (Server-Side Request Forgery) 攻击面。
我立刻打开了 Burp Suite。最初的想法很简单:它会不会对输入的目标地址做限制?如果我让它去访问我控制的服务器,它会乖乖照做吗?
0x03 漏洞利用
先访问目标地址

输入用于验证ssrf的dns接收地址

开始抓包

几秒钟后,我的 Webhook 控制台跳出了一条来自目标服务器的 HTTP GET 请求日志!

本以为到此为止,我已经拿到了一个普通的 SSRF 漏洞证明。然而,接下来的发现推翻了我的假设。当我尝试将 URL 指向 http://127.0.0.1:22 或其他内网私有 IP(如 192.168.x.x)时,前端页面并没有返回任何有用的报错信息,统一提示“QR routed unparsable”(二维码无法解析)。
这是一个典型的 无回显 SSRF (Blind SSRF)。前端不给你看响应内容,怎么证明它能威胁内网呢?
时间差,是破解盲盒的钥匙。
我开始进行基于时间的端口开放测试。我构造了针对特定内网 IP 不同端口的请求,并仔细观察 Burp Suite 右下角的响应时间(Response Time):
- 场景 A(端口未开放): 当我请求一个大概率关闭的端口(比如 http://[内网IP]:25468),由于 TCP 握手直接被拒绝(RST),服务器几乎瞬间返回结果,整个 HTTP 请求耗时约为 10,000 millis (10秒,受系统默认超时影响)。

- 场景 B(端口开放): 当我请求一个大概率开放的端口(比如某些内部常见的中间件端口),服务器的底层 HTTP Client 会成功建立连接,但因为目标端口返回的不是合法的图片数据,解析进程会卡住等待流读取,最终导致耗时大幅增加,可能达到 20,000+ millis。

通过这种时间盲注的方式,我完全可以编写一个自动化脚本,利用这个接口对该平台的内网进行大规模的端口扫描
0x03 漏洞影响
合上电脑前,我仔细评估了这个漏洞的杀伤力。
表面上看,这只是一个“拉取二维码失败”的小 Bug。但在攻击者眼里,这台拥有极高网络权限的支付网关服务器,已经沦为了一台内网跳板机(Pivot)。
- 内网探测与资产刺探: 利用时间差,攻击者可以绘制出目标企业内部的网络拓扑,找出潜藏在内网的 Redis、Elasticsearch、MySQL 等服务。
- 云环境元数据窃取: 如果该服务部署在 AWS 等云环境,攻击者可以通过请求 http://169.254.169.254/latest/meta-data/,极大概率窃取到云主机的临时凭证(STS Tokens),从而接管云环境。
- 内网脆弱服务打击: 即便没有回显,依然可以对内网未授权访问的组件(如 FastJSON 漏洞、Struts2 漏洞)打出 RCE Payload。
一旦支付网关的内网被击穿,随之而来的可能是核心交易数据的泄漏,对于一家金融科技公司而言,这种后果是灾难性的。
0x04 防御与反思
从攻击者的快感中抽离出来,作为技术人员,我们更需要思考 Root Cause(根因)。
SSRF 的本质是信任泛滥。业务代码在接收外部传入的 URL 时,完全信任了该输入的合法性,直接交由 HTTP 库发起请求,而忽略了网络边界的划分。
对于这个高危漏洞,我给出了以下几点修复建议:
- 输入验证与严格白名单(最重要): 绝不能只在前端校验!后端在发起请求前,必须解析目标 URL 的 IP 地址。如果解析出的 IP 属于内网保留地址(如 10.0.0.0/8, 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12 以及 169.254.169.254),应直接阻断请求。
- 禁用不必要的协议: 限制 HTTP Client 只能使用 HTTP 和 HTTPS 协议,禁止 file://、dict://、gopher:// 等可能被用于读取本地文件或构造复杂 TCP 请求的协议。
- 关闭跟随重定向(Follow Redirects): 攻击者经常利用短链接或自己控制的服务器发起 302 重定向到内网 IP 来绕过简单的域名检查。务必在 HTTP 客户端配置中关闭自动重定向,或者在每次重定向时重新进行 IP 黑白名单校验。
- 最小权限架构: 在网络层(如 AWS Security Groups 或 K8s Network Policies)严格限制该支付模拟器容器的 Egress(出站)权限,仅允许其访问必要的外部域名。
这次深夜的挖洞体验让我受益匪浅。安全从来不是单纯的攻防对抗,而是在理解业务逻辑基础上的细节博弈。代码里少了一行 IP 校验,现实中就多了一扇通往核心内网的大门。