尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

SSRF漏洞详解:从原理到防御,堵死服务端请求伪造的跳板

发布时间:2026/9/29 20:18:50

资讯中心
01
ARTICLE

SSRF漏洞详解:从原理到防御,堵死服务端请求伪造的跳板

SSRF漏洞详解:从原理到防御,堵死服务端请求伪造的跳板
1. 先说清楚为什么一个“能发起网络请求”的功能会变成跳板做安全测试和攻防对抗这么多年我几乎每次遇到“URL回调”“图片抓取”“Webhook推送”这类功能都会下意识多问一句这个请求到底发到哪里去了因为很多开发者只想着“功能能用就行”完全没意识到一个能在服务端发起网络请求的入口一旦没做限制就等于给攻击者递了一把能穿防火墙的钥匙。这就是SSRF服务端请求伪造。我见过最典型的一个场景业务系统部署在内网前端需要从外网某个URL拉取一张图片存到OSS结果后端接口直接接收参数里的URL用curl去请求。攻击者把这个URL改成http://127.0.0.1:6379就能探测内网的Redis改成http://192.168.1.100:8080就能扫内网其他业务的管理后台。更麻烦的是很多内网服务默认信任“同一网络环境”里的机器对外网的攻击层层设防但对内网来的请求几乎不设防——所以一旦这个能发内网请求的功能被利用攻击者相当于拿到了一个“内部可信身份”后面能做的事就完全不是一个量级了。这篇文章我想把SSRF这套东西掰开讲清楚它为什么会存在、http/https/dict/ftp/gopher这些协议在这个场景里分别能干什么、实际测试中怎么判断一个入口有没有风险以及最重要的——作为开发者或运维怎么把它彻底堵死。不管你是写业务代码的还是做安全建设的看完应该都能找到自己能落地的部分。2. 拆解SSRF核心成因与“信任边界”是怎么被打破的2.1 SSRF为什么叫“服务端请求伪造”普通攻击者想访问内网资源通常会被防火墙挡在外面。但SSRF不是直接攻击内网而是“借刀杀人”攻击者构造一个恶意URL让受害服务器的后端代码替他去请求这个URL。因为请求是从受害服务器发起的目标内网服务看到的是来自“自己人”的请求于是信任就建立了。这里有个关键点所有请求都不是攻击者直接发出的而是通过受害服务器中转。攻击者要做的事情只有一个——想办法让受害服务器把请求发到他指定的地址上去。所以严格来说SSRF不是“伪造IP”而是“伪造请求的发起者”。我在实际项目里总结过SSRF高发的位置基本集中在下面几类图片/文件抓取用户传一个图片URL服务端下载后处理。这是最常见的没有之一。URL检测/域名验证有些平台“验证回调URL是否有效”会主动请求用户提交的地址。Webhook通知业务触发事件后往用户配置的地址发POST请求。PDF生成把HTML或远程资源渲染成PDF里面经常带img srchttp://内网地址这种引用。API代理转发后台把请求转发给第三方服务中转地址由用户控制。只要看到参数里有url、uri、link、src、target、callback这类字眼都值得警惕。2.2 “信任内网”为什么风险更大很多内网服务在设计时有一个默认前提能访问到我的请求一定是经过网络准入或者同样在内网环境里的所以可以信任。这个假设在SSRF面前是致命的。举个例子内网有一个MySQL监听在3306端口防火墙策略是“仅允许内网网段访问”。外网攻击者打不进来但如果他找到一个SSRF点让内网的一台Web服务器去连MySQL的3306端口MySQL看到来源地址是内网Web服务器的IP自然放行。攻击者甚至不需要知道MySQL密码如果这条服务用的是老版本、弱口令后面就能通过协议构造直接执行命令。所以“其他服务器信任该内部服务器”这句话本质上是把“网络位置”当成了“安全身份”。SSRF打破的就是这层信任——因为请求的发起者确实是你信任的内网机器但它背后操纵键盘的人根本不是内网用户。2.3 一个最小示例理解全流程假设有一个接口长这样app.route(/fetch_image) def fetch_image(): url request.args.get(url) return requests.get(url).content正常用户传http://example.com/a.jpg服务端去外网抓图没问题。但攻击者传http://127.0.0.1:8080/manager服务端就会去访问本机的8080端口。如果本机正好跑了一个Tomcat管理后台那这个请求就会带着Web服务器的内网IP访问到管理员接口——外网攻击者通过浏览器直接敲这个URL是会被防火墙拦的但服务端替他敲防火墙拦不住。这个例子极简但控制点全在这服务端发起请求时是否校验了目标地址的合法性和协议类型。3. 四种协议里真正危险的是谁http/https、dict、ftp与gopher3.1 http/https协议最基础但也最被滥用http和https是SSRF里最直观的利用方式。攻击者可以读取内网Web页面、访问管理后台、调用内网API接口甚至通过代理隧道把内网页面内容“搬运”出来。对于“无回显”的情况http协议也很有用。比如让受害服务器请求一个攻击者控制的公网服务器通过DNS解析日志、访问日志来判断请求确实发出去了这就是常见的外带检测手段。我在测试时也经常用http://your-server/log?keyxxx这类地址把参数带出去。不过http协议有个特点它只能按Web服务的“规则”去交互。比如内网跑了一个不支持HTTP的协议比如Redis、MySQL你用http去发一个普通GET请求对方只会回一串错误信息没法做深层次利用。这时候就需要看其他协议了。3.2 dict协议比http更“原始”的探测工具dict协议最早是用于字典查询的但它本质上是一个极简的TCP客户端能够往任意主机的任意端口发送一段文本并读取返回内容。在SSRF利用中dict协议的典型价值主要有两个端口探测拿dict://目标IP:端口/去试如果端口开放通常会返回类似220 ...的banner如果端口关闭会报连接失败。这种方式比http更轻量而且能探测到非HTTP端口。简单交互有些服务支持纯文本协议dict可以代替nc/bash轮子发送类似INFO这类指令探测服务类型。但dict也有明显局限性它每条指令只能发一次没有完整的交互握手过程。你想跟Redis做多轮命令交互dict发完第一个命令后就断开了根本没法做成完整的利用链。所以它更适合做“探测”而不是“利用”。3.3 ftp协议能扫描也能读文件但局限同样明显ftp在SSRF里的价值首先还是端口探测。因为ftp服务在端口开放的情况下通常会返回220开头的banner这个反应速度和端口指纹都很好识别。很多内网扫描器都支持用ftp://来探测开放端口。第二个价值是读取文件。如果内网某个FTP服务器允许匿名登录或弱口令登录那么通过SSRF可以指向ftp://user:pass内网IP/文件路径让服务端去拉取FTP上的文件并把内容回显到页面上。这在拿配置文件、密钥文件的时候非常有用。但ftp也做不到复杂的交互。现代FTP有主动被动模式、有用户认证流程很多SSRF实现用的库在处理FTP协议时并不完整经常会出现连接超时或认证失败。所以实际利用时ftp更多是一个“补充协议”真正的高危大户还得看gopher。3.4 gopher协议最危险因为它能构造任意TCP报文gopher历史很老最初是用于分布式文档检索的但它有一个极其特别的能力gopher URL里可以包含任意字节内容并且客户端会把这些内容原样作为TCP数据发送给目标主机。这意味着只要目标端口支持文本协议攻击者就能用gopher构造出完整的协议交互过程。我举个例子你就明白了。Redis默认监听6379端口协议是纯文本的你可以给Redis发送一条命令比如SET key value。如果没有gopherSSRF打Redis最多只能发一条命令效果有限但gopher可以把多条命令拼在一起甚至模拟完整的认证和写入过程这就等于把“拿到一个SSRF”升级成了“可能拿到内网一台机器权限”。同样MySQL、Memcached、FastCGI这类基于文本或简单协议的中间件都在gopher的打击范围内。所以在看SSRF利用面的时候我一直把gopher定义为“最坏情况”——因为它能让攻击者在一个看似不起眼的URL下载功能上直接打通到内网横向移动的链条。协议对比表格方便你快速记忆协议能探测端口能交互能读取文件危险程度http/https是但只针对HTTP服务一般受限于Web逻辑可以通过Web资源中dict是很弱单次命令否中ftp是弱认证流程受限可以需认证中低gopher是强可构造任意文本请求视服务而定高4. 实操视角测试一个SSRF入口时我在关注什么4.1 怎么快速判断一个接口是不是SSRF隐患拿到一个目标我通常不会一上来就扫协议而是先做下面四步找全参数把所有带URL字样的参数收集出来不只是url还有redirect、target、endpoint、host、ip、location等甚至JSON字段里的link、href也要关注。确认是服务端发起的怎么判断最简单是改成一个外部可控的地址观察目标服务器有没有真的去请求。最稳的方法是用自己的公网服务器或者带自定义域名的DNS log服务看有没有收到请求。区分“直接HTTP”还是“SSRF”如果目标服务器只是做一个302跳转那不算SSRF因为请求是浏览器发起的只有当请求是从服务端发出的才是SSRF。测试回显与盲打把URL改成http://127.0.0.1:一些常见端口看返回内容里有没有包含响应体如果没有回显就改用时间延迟或DNS外带去判断。4.2 绕过策略为什么要专门研究很多系统做了基础防护比如检查url是否以http://或https://开头然后就放行了。这种防护形同虚设因为攻击者有一百种方式绕过IP混淆用127.1、0x7f000001、2130706433这种十进制整数、八进制、十六进制写法很多简单的字符串匹配根本识别不出来。域名解析绕过先让服务端解析一个公网域名但该域名在解析时会返回内网IP。只要检查是在“字符串层面”而不是“解析后IP层面”做的就会被绕过去。重定向绕过先请求一个攻击者控制的公网URL该URL返回302 Location: http://192.168.1.1如果服务端跟随重定向就能打到内网。URL解析差异不同库对、#、?、反斜杠的处理不一样比如http://baidu.com127.0.0.1某些库取的是127.0.0.1但字符串校验时以为域名是baidu.com。我见过不少系统“防了跟没防一样”就是因为在白名单里只校验前缀没校验最终请求的目标IP。真正有效的绕过点后面防御部分会讲。4.3 盲打场景下怎么判断是否成功不是所有SSRF都有回显很多时候目标服务端会把请求结果直接丢弃或者响应被包在不可见的地方。这种情况下我建议按下面的优先级收集证据DNS外带让目标请求一个攻击者控制的域名比如http://xxx.dnslog.cn/只要DNS日志里有解析记录基本就能确认SSRF存在。HTTP外带在可控公网服务器上起一个HTTP监听目标请求这个地址时就能看到来源IP、UA、时间这些信息还能帮你判断服务器所在网络环境。时间延迟内网里有些服务响应慢或者可以通过构造不同的端口来对比响应时间间接判断端口是否开放。比如请求一个开放端口可能秒回请求一个黑洞IP可能长时间无响应。错误信息有些框架会把请求异常回显到页面上比如Connection refused或者TTPError根据错误类型也能推断出端口状态。这里要补充一句做测试时一定要遵守授权。SSRF可以探测内网但一旦越界性质就完全不同了。严格在授权范围内测试才是一个从业者的基本底线。5. 防御落地怎么把这个口子彻底堵上5.1 最有效的一条先解析再判断IP很多防御方案都在“字符串过滤”层面较劲结果被各种编码绕过打脸。真正的标准做法是先对目标URL做DNS解析判断最终的IP是否为内网地址如果是就拒绝。不是判断用户输入里有没有192.168而是判断“请求实际会到达的IP”是不是内网。我用Python写过一个简化的校验逻辑思路可以参考import ipaddress import socket from urllib.parse import urlparse def is_private_ip(ip): return ipaddress.ip_address(ip).is_private or ipaddress.ip_address(ip).is_loopback def safe_request(url): host urlparse(url).hostname ip socket.gethostbyname(host) if is_private_ip(ip): raise Exception(blocked internal IP) # 这里还可以防止DNS rebinding需要再次解析并校验 return requests.get(url, timeout3)但要注意只解析一次是不够的。攻击者可以用“DNS Rebinding”手法第一次解析返回公网IP通过校验等真正发起请求时再次解析却返回内网IP。所以更稳妥的做法是解析两次然后对比结果如果不一样就拒绝或者直接使用那些内置了SSRF防护的HTTP客户端库。5.2 协议白名单比黑名单靠谱得多在协议这一层我强烈建议做白名单。默认只允许http和https并且对gopher、dict、ftp、file、tftp等协议一律拒绝。原因很简单——日常业务真的需要用到gopher吗几乎不需要。与其去修gopher的各种诡异编码问题不如直接把它禁用。在代码里就是说解析URL时强校验scheme必须落在允许列表内。不要只是“不允许某些开头”而是“只允许约定好的几种”。ALLOWED_SCHEMES (http, https) scheme urlparse(url).scheme.lower() if scheme not in ALLOWED_SCHEMES: raise Exception(blocked scheme: scheme)5.3 重定向与端口限制服务端发起请求时如果默认跟随重定向那前面做的IP校验也可能被绕开。所以我建议在核心逻辑里关闭自动重定向或者每次都重新校验重定向后的目标。如果业务上确实需要跟随重定向就在每一次跳转之前都做一次完整的“解析协议IP”校验把每一个跳转目标都当作新请求来对待。端口层面也很重要。内网的Redis、MySQL、SSH等端口本来就不应该被Web服务器主动访问做一个端口白名单限制例如只允许80、443、8080等web端口能大幅缩小攻击面。虽然有些协议比如FastCGI能跑在9000端口上但总比一个都不限制强。5.4 网络层防护除了代码还能做什么代码层校验是最后一道关我更希望你在架构层面就先给它降权隔离网络Web服务器所在网段不应该能直接访问内网核心业务网段。把“能发起外网请求的服务”单独放进一个DMZ或者独立子网通过防火墙策略限制它只能访问必要的地址。出网管控限制Web服务器只能通过代理访问外网而不是让后端代码直接用公网IP海阔天空地乱跑。这样做既方便审计也方便在代理层做URL过滤。流量监控为这类服务单独记录“出站请求日志”一旦发现异常内网地址能第一时间报警。我遇到过不少公司代码里各种安全组件都装了但网络架构本身“内网通吃”那就等于把所有安全寄托在开发者不写烂代码上这显然不现实。6. 常见问题与排查技巧实录6.1 为什么SSRF请求经常报“502 Bad Gateway”我在测试的时候经常会看到unexpected status 502 bad gateway这种错误。很多人第一反应是“SSRF打不进去”。其实这个问题分两面看如果请求打到的是一个Web服务但该服务返回异常那么受害服务端在接收上游响应时确实可能表现为502。更常见的情况是你构造的目标服务比如内网某Redis端口根本不理解HTTP请求它返回的内容不是合法HTTP响应于是受害服务端在代理转发时直接报了Bad Gateway。所以看到502别急着放弃反而应该意识到这很可能说明你的请求已经到达了目标端口只是目标服务“不会说HTTP”。这时候改换gopher或dict协议可能就有完全不同的效果。6.2 为什么有时候内网端口开放了但响应超时SSRF请求超时是一个经典困惑点。原因可能是目标主机防火墙开启了“黑洞”策略——对未开放的端口直接丢包而不是返回拒绝连接。这种情况下开放端口反而可能因为服务响应而很快返回未开放端口一直超时。当你发现某个协议迟迟不响应可以先换一个基于“连接是否建立”的判断方法而不依赖响应内容。还有一个坑是“代理依赖”有些后端HTTP库强制走系统代理结果你构造的URL根本没到内网而是被代理服务器拦了。排查时可以看超时时间、报错信息里有没有代理服务器地址确认请求方向。6.3 gopher协议构造时踩过的三个坑gopher虽然强力但实操中真的容易踩坑我记在这里供你参考编码问题gopher URL中很多特殊字符需要URL编码尤其是空格、换行、冒号。如果编码不彻底目标服务收到的报文就不是你想象的那一串。我一般会先把要发送的内容整段构造好再用工具统一做URL编码。端口必须正确gopher只负责“把数据发到某端口”它不管你目标是什么服务。你要是把Redis的数据发到MySQL端口得到的只会是一堆解析错误。服务端库支持度不一很多语言的老版本HTTP库对gopher支持很糟糕甚至根本不支持。所以遇到gopher测试没反应先确认底层库到底认不认识这个协议。6.4 常见问题速查表现象可能原因排查方向请求直接报502目标端口开放但非HTTP服务换dict/gopher继续探测长时间超时目标端口防火墙丢包或走了代理检查请求方向和端口开放特征DNS外带有解析但无HTTP回显SSRF存在目标服务无有效HTTP响应考虑盲打结合时间延迟判断IP校验被绕过只校验字符串未校验解析后的IP增加真实IP解析与二次校验gopher无效果编码错误或底层库不支持确认URL编码及HTTP库对gopher的支持7. 最后分享一点我自己的经验做安全这一行见多了“灭顶之灾往往来的不是大漏洞而是一个看似人畜无害的URL下载功能”。SSRF的可怕之处不在它本身而在于它打破了网络分区里最基础的信任模型。每一次看到url参数我都会本能地想到一句如果这个参数落到坏人手里他能让这台服务器替他去敲多少扇内网的门。我个人在写代码和做审计时已经形成了三条固定习惯分享给你第一凡是会发起服务端请求的接口一律把“默认拒绝”写在最前面——只允许明确允许的协议和明确允许的IP段而不是“不允许明显的坏东西”。这个思路几乎能挡住绝大多数常规攻击。第二不要只依赖代码层防护。网络隔离和出站规则才是最粗的那条腿代码层校验只是锦上添花。把业务服务器的出站权限收窄哪怕代码里有漏网之鱼攻击者也走不出那一步。第三多留测试后门。这里说的后门是“可观测性”。为服务端请求保留完整日志包括完整URL、目标IP、时间戳、响应状态。一旦出了事你能用日志在十分钟内还原攻击路径而不是在服务器上翻半天记录。SSRF不是一个“学一次就会”的东西因为协议更新、库的行为差异、网络环境变化都会让它的边界一直漂移。但只要你抓住“谁发起的请求、发到哪里、经过了几层校验”这三点思路就不会乱。希望这篇内容能帮你在开发或测试的时候少走一些我当年走过的弯路。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。