跳转到帖子

SSRF(Server-Side Request Forgery,服务端请求伪造)并不是简单的“后端可以发 HTTP 请求”这么单一。真正难处理的地方在于:业务通常确实需要访问外部资源,而攻击者能够影响请求目标、解析过程、重定向行为或请求协议。审计时如果只检查参数是否以 http:// 开头,往往会漏掉大量风险。本文以代码审计和防守验证为主线,整理 SSRF 的常见成因、审计思路、验证方法以及修复时容易忽略的边界条件。示例均以本地测试环境或受控回连服务为前提,不涉及对真实内网系统的探测。一、常见业务场景与风险边界以下功能经常出现服务端主动请求外部地址的逻辑:根据 URL 抓取网页标题、生成预览或转换文件。头像、文档、图片等远程资源导入。Webhook、回调地址、第三方接口配置。PDF、Markdown、Office 文档中的远程资源加载。监控系统、代理服务或服务端图片转码接口。风险并不只表现为读取云平台元数据。更常见的问题包括访问本机管理接口、读取内部服务响应、向内部系统发送非预期请求,以及利用出站网络权限扩大影响范围。因此,评估 SSRF 时应同时关注三个维度:请求目标:是否能访问回环地址、私有地址、链路本地地址或内部域名。请求能力:是否支持重定向、非 HTTP 协议、任意端口、自定义请求头和请求体。响应反馈:服务端是否把响应正文、状态码、响应头或错误信息返回给用户。二、代码审计的切入点审计时不要只搜索 requests.get 或 HttpClient。更稳妥的方式是先定位“用户可控字符串如何进入网络请求”,再沿调用链确认是否经过统一校验。常见的入口关键词包括:参数名:url、uri、callback、webhook、image、remote。功能名:预览、导入、同步、抓取、转码、回调、代理。网络 API:URL、URI、HttpClient、fetch、curl、socket。跟随跳转:followRedirects、allow_redirects、RedirectStrategy。重点检查下面几类代码模式:target = request.getParameter('url')
response = httpClient.get(target)
return response.body()这种写法的问题不只是缺少 IP 黑名单,还可能把完整的内部响应直接反射给调用者。即使业务只需要图片或标题,也不应默认把任意响应正文返回。三、URL 校验为什么容易失效很多修复方案只做字符串判断,例如检查 URL 是否包含 127.0.0.1、是否以某个域名开头。这类方案很容易被 URL 解析差异、域名解析变化或重定向绕过。1. 用户名密码和主机名混淆URL 中的 @ 会分隔用户信息和主机部分。安全校验必须使用标准解析器读取真正的主机名,而不是用字符串前缀判断。from urllib.parse import urlsplit

parsed = urlsplit(target)
host = parsed.hostname2. DNS 解析结果与连接目标不一致如果应用先解析域名判断是否为公网地址,随后网络库再次解析并建立连接,就需要考虑 DNS rebinding 等时间差问题。更可靠的做法是在建立连接的同一流程中完成解析、地址过滤和连接,或者由受控的出站代理统一执行。3. 重定向绕过初始校验即使第一跳地址是允许的公网域名,它也可能返回指向内部地址的 30x 响应。默认跟随重定向会让初始校验失去意义。通常应关闭自动重定向;如果业务必须支持重定向,则每一跳都重新解析、校验协议、端口和目标地址,并限制最大跳数。4. IPv4、IPv6 与特殊地址范围过滤规则不能只覆盖常见的 IPv4 私网段,还要处理回环地址、链路本地地址、未指定地址、IPv6 私有地址以及 IPv4 映射地址。Python 中可以使用标准库进行地址分类,避免手工维护不完整的正则表达式。import ipaddress

def is_public_address(address):
ip = ipaddress.ip_address(address)
return not (
ip.is_private or
ip.is_loopback or
ip.is_link_local or
ip.is_unspecified or
ip.is_multicast
)这里的“公网地址”只是一个基础判断,不代表访问一定安全。企业环境中还应根据网络架构额外限制办公网段、管理网段、容器网段以及云厂商保留地址。四、一个相对完整的校验思路下面示例展示防守侧的基本流程,实际项目还应结合统一出口代理、网络 ACL 和应用身份权限进行控制。from urllib.parse import urlsplit
import socket
import ipaddress

ALLOWED_SCHEMES = {'http', 'https'}
ALLOWED_PORTS = {80, 443}

def resolve_public(host):
results = socket.getaddrinfo(host, None, type=socket.SOCK_STREAM)
addresses = set()

for item in results:
address = item[4][0]
ip = ipaddress.ip_address(address)
if (
ip.is_private or
ip.is_loopback or
ip.is_link_local or
ip.is_unspecified or
ip.is_multicast
):
raise ValueError('destination address is not allowed')
addresses.add(address)

if not addresses:
raise ValueError('host has no valid address')
return addresses

def validate_target(target):
parsed = urlsplit(target)

if parsed.scheme not in ALLOWED_SCHEMES:
raise ValueError('scheme is not allowed')

if not parsed.hostname:
raise ValueError('host is required')

if parsed.username or parsed.password:
raise ValueError('userinfo is not allowed')

port = parsed.port or (443 if parsed.scheme == 'https' else 80)
if port not in ALLOWED_PORTS:
raise ValueError('port is not allowed')

resolve_public(parsed.hostname)
return parsed这段代码仍然不能单独解决 DNS 竞争问题,也没有实现连接时绑定已校验地址。生产环境更推荐把出站请求交给专门的 egress proxy,由代理负责 DNS 解析、目标地址过滤、连接超时、响应大小和审计日志,应用侧只提交经过格式校验的目标。五、验证修复时应该检查什么安全验证不建议直接探测真实内网服务。可以在本地启动一个受控 HTTP 服务,准备以下测试场景:正常公网测试域名:确认业务功能没有被误伤。本机回环地址和本地监听端口:确认请求被拦截。私有网段和链路本地地址:确认地址分类完整。解析到不同地址的测试域名:确认解析结果会参与校验。返回重定向的受控服务:确认重定向不会绕过策略。非 HTTP 协议和带用户信息的 URL:确认协议和格式限制有效。超大响应、慢响应和连接失败:确认超时、大小限制和错误处理正常。验证时重点观察三类结果:请求是否真正发出、应用向用户暴露了多少响应信息、日志是否记录了目标域名、解析地址、拒绝原因和请求耗时。不要把“返回 400”作为唯一判断标准,有些实现虽然返回错误,但后台已经完成了对受限目标的请求。六、常被忽略的防护细节限制协议。通常只开放业务确实需要的 https,不要让底层网络库自动支持文件、FTP、Gopher 或本地套接字等协议。限制端口。只开放必要的 80 和 443,避免使用任意端口访问内部管理服务。关闭自动重定向。必须支持时,对每一跳执行完整校验。限制请求头。不要把用户输入直接复制到授权、主机或内部路由相关请求头中。限制响应。设置连接超时、读取超时、最大响应体、最大重定向次数和最大下载时间。避免回显敏感内容。对于图片预览等功能,返回经过处理的业务结果,而不是原始响应正文和完整响应头。使用网络层兜底。应用校验存在遗漏时,出站防火墙、代理 ACL 和云网络策略仍应阻断不必要的内部访问。记录拒绝事件。日志中保留请求来源、业务接口、规范化后的目标、解析地址和拒绝原因,但不要记录可能包含凭据的完整 URL。七、审计报告如何描述问题一份可执行的 SSRF 报告至少应包含以下内容:项目说明入口与影响范围指出具体接口、参数、调用链以及是否需要登录。成因说明用户输入如何进入网络请求,缺少哪些校验或网络限制。安全影响区分盲 SSRF、可回显 SSRF、重定向风险和出站能力风险。验证证据使用受控域名或本地测试服务,记录请求是否到达,不采集真实敏感数据。修复建议给出协议、端口、解析、重定向、超时、响应和网络出口等具体措施。总结SSRF 防护的核心不是维护一份越来越长的黑名单,而是建立一条完整的出站请求安全链:严格解析 URL,限制协议和端口,解析并校验最终地址,控制重定向,限制请求和响应资源,并通过网络出口策略做最终兜底。从审计角度看,最值得优先检查的是“用户可控 URL + 服务端请求 + 自动跟随重定向 + 原始响应回显”这条组合链路。只要把这几个环节拆开验证,再配合受控环境测试,通常就能较快判断问题的真实风险和修复是否有效。

服务器与云环境安全示意图
服务器、云资产与权限边界梳理示意

0篇意见

推荐意见

没有意见。

游客
抱歉,你的帖子内容包括我们不允许的字词。请编辑你的帖子,删除下面高亮的屏蔽字。
添加意见…