跳转到帖子

SSRF(Server-Side Request Forgery,服务端请求伪造)并不是简单的“让服务器访问一个 URL”。在真实项目中,漏洞往往出现在图片抓取、Webhook、文档预览、远程资源导入、监控探针等功能里。攻击者能够影响请求目标后,风险取决于服务端网络位置、请求凭据、重定向处理方式以及云环境的出网策略。这类问题的难点通常不在于发现一个可以访问的地址,而在于确认:应用究竟如何解析 URL,DNS 解析发生在哪里,是否允许重定向,是否会自动携带内部凭据,以及网络侧有没有第二道限制。本文以防守和授权测试为前提,整理一套适合代码审计、复现和修复验证的排查方法。一、典型场景与风险边界常见入口包括以下几类:用户提交图片或附件地址,服务端负责下载并保存。Webhook、回调地址或第三方集成配置。Markdown、富文本或文档服务中的远程资源抓取。URL 预览、网页截图、PDF 转换和链接安全扫描。代理接口、健康检查接口和内部服务连通性检测。风险不一定表现为直接读取敏感数据。即使响应内容不可见,服务端仍可能因为请求内部地址而产生盲 SSRF,造成内网端口探测、管理接口访问、内部任务触发或审计数据污染。因此评估时应把“能否发出请求”和“能否读取响应”分开判断。授权测试建议只在隔离环境或明确授权的资产范围内进行。不要把生产环境的云元数据地址、内部管理面板或真实凭据作为验证目标。二、先从代码路径还原请求行为审计时不要只搜索 requests.get、curl 或 http.Client。更有效的做法是从用户可控参数向下追踪,建立一条完整的数据流:输入点:参数、JSON 字段、HTTP Header、数据库配置或消息队列内容。规范化:是否自动补全协议、去除空格、解码 URL 或拼接路径。解析:使用了哪个 URL 解析库,是否校验用户名、端口和 IPv6 格式。网络请求:是否允许 HTTP、HTTPS、Unix Socket、代理协议或其他 scheme。响应处理:是否跟随 30x,是否把响应写入本地,是否解析 XML、HTML 或图片。错误处理:网络错误、超时和重定向异常是否向用户泄露内部信息。很多修复只在控制器入口增加一个正则判断,但后续代码可能再次对地址进行拼接或解码,导致校验对象和实际请求对象不一致。建议在最终发起请求前再次执行统一校验,并把校验后的结构化结果传给网络层,而不是继续传递原始字符串。三、用受控环境确认是否存在 SSRF验证时可以在本地或测试网段启动一个简单的观测服务,让应用访问一个明确的测试地址。观测服务只记录请求时间、来源地址、方法、路径和必要的请求头,不返回敏感内容。python3 -m http.server 18080 --bind 127.0.0.1然后在测试应用中提交类似下面的地址: 指向的是应用所在网络命名空间,而不是测试人员的电脑。为了确认请求确实来自目标服务,可以使用授权范围内的测试域名或团队提供的 HTTP 观测服务,并在 URL 路径中加入随机标识。验证结果至少应记录以下信息:请求是否到达观测服务。来源 IP 和实际解析出的目标地址。应用使用的 HTTP 方法、请求头和超时时间。是否自动跟随重定向。响应状态码、响应体大小以及错误信息是否回显。四、URL 校验中最容易出错的几个点1. 只检查字符串前缀类似 url.startswith(' 的判断不可靠。域名边界、用户名字段、大小写、端口和编码都可能导致校验结果与实际目标不一致。应先使用标准库解析 URL,再分别检查 scheme、hostname、port 和 path。2. 忽略用户名和密码字段URL 可以包含用户信息部分。应用若只是截取字符串或拼接主机名,可能把看似可信的文本误当成目标域名。安全策略通常应直接拒绝包含用户名和密码的 URL,除非业务确实需要,并且有独立的凭据管理方案。3. 只过滤常见 IPv4 私网段除了 RFC1918 地址,还需要关注回环地址、链路本地地址、保留地址、IPv6 回环地址以及 IPv4-mapped IPv6 地址。不要把字符串形式的地址交给黑名单正则判断,应使用成熟的 IP 解析库。4. DNS 解析与实际连接之间存在时间差如果代码先解析域名、校验解析结果,再把原始域名交给 HTTP 客户端连接,期间可能发生 DNS 变化,形成校验和连接目标不一致的问题。更稳妥的方式是使用受控出站代理,或者在网络层对最终连接地址进行再次限制。对于高风险场景,还应限制 DNS 解析器、禁止访问内部 DNS,并对每次连接进行审计。5. 忽略重定向初始地址可能是公网域名,但服务端跟随 30x 后进入了不应访问的网络。修复时可以默认禁止跨主机重定向;如果业务必须支持重定向,应对每一跳重新执行 scheme、域名、解析地址和端口校验,并设置最大跳数。五、一个防守侧的校验示例下面的示例仅用于说明校验思路,实际项目还需要结合业务允许的域名、端口和网络架构进行调整。示例拒绝非 HTTP 协议、用户信息、非标准端口以及解析到非公网地址的目标。from ipaddress import ip_address
from urllib.parse import urlparse
import socket

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

def resolve_public_ips(hostname):
records = socket.getaddrinfo(
hostname,
None,
type=socket.SOCK_STREAM
)
result = set()
for item in records:
result.add(ip_address(item[4][0]))
return result

def validate_remote_url(raw_url):
parsed = urlparse(raw_url)

if parsed.scheme.lower() not in ALLOWED_SCHEMES:
raise ValueError('unsupported scheme')

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

if not parsed.hostname:
raise ValueError('missing hostname')

try:
port = parsed.port or (443 if parsed.scheme.lower() == 'https' else 80)
except ValueError:
raise ValueError('invalid port')

if port not in ALLOWED_PORTS:
raise ValueError('port is not allowed')

addresses = resolve_public_ips(parsed.hostname)
if not addresses:
raise ValueError('hostname does not resolve')

if any(not addr.is_global for addr in addresses):
raise ValueError('non-public address is not allowed')

return parsed这个示例有两个重要限制。第一,is_global 不能替代完整的企业网络策略,公网可路由地址并不代表业务上允许访问。第二,应用层解析仍可能受到 DNS 竞态影响,因此不能把这段代码当作唯一防线。生产环境更建议配合出站代理、云网络策略和防火墙规则。六、重定向、代理和响应处理的防护要点默认关闭自动重定向;必须支持时,限制最大跳数,并对每一跳重新校验。只允许业务所需的 HTTP 方法,通常不需要开放任意方法。禁止客户端代理配置覆盖服务端的安全策略,避免通过环境变量或用户输入改变出站路径。设置连接超时、读取超时、响应大小上限和整体请求时间上限。不要直接把远程响应体拼接到 HTML、模板、XML 解析器或命令行参数中。对压缩包、图片、文档等内容做类型和大小检查,避免 SSRF 与资源耗尽、解析器漏洞叠加。错误信息不要返回完整的内部地址、DNS 结果、连接栈或响应头。七、网络侧的纵深防护应用层校验存在遗漏是现实情况,因此出站网络控制非常重要。常见做法是让业务服务不能直接访问任意地址,而是统一经由出站代理。代理可以维护域名白名单、端口白名单、DNS 解析策略和请求审计。在云环境中,还应从网络层限制业务子网访问管理面、控制面和不必要的内部服务。对于不需要访问互联网的服务,默认禁止公网出站,只为特定依赖开放目标地址。日志侧应关联应用请求 ID、目标域名、解析地址、最终连接地址、响应状态和耗时,便于识别异常访问模式。层面建议代码统一解析和校验 URL,限制协议、端口、域名和重定向。网络默认拒绝不必要的出站访问,使用代理或防火墙实施白名单。运行环境减少实例权限,避免应用进程拥有不必要的云服务凭据。监控记录目标、解析结果、重定向链和异常响应,建立告警基线。测试覆盖 IPv4、IPv6、DNS 变化、重定向、异常端口和编码边界。八、复测清单修复后不要只测试一个公网地址。建议在隔离环境准备以下用例,并确认应用的日志和网络策略与预期一致:正常的 HTTPS 公网地址可以按业务要求访问。HTTP、HTTPS 以外的协议被拒绝。回环地址、私网地址、链路本地地址和 IPv6 本地地址被拒绝。非标准端口、缺失主机名和包含用户信息的 URL 被拒绝。公网地址重定向到受限地址时请求被中止。DNS 解析返回多个地址,其中任意地址不符合策略时整体失败。超大响应、慢连接和过多重定向不会拖垮工作线程。错误响应不会泄露内部网络信息。总结SSRF 的修复不能依赖一个正则或一份黑名单。可靠的处理链路应当是:明确业务允许访问的目标范围,使用标准库解析 URL,在最终连接前校验解析结果,限制协议、端口和重定向,再通过出站代理和网络策略提供第二道防线。从审计角度看,最有价值的工作不是收集尽可能多的绕过样例,而是还原应用从输入到连接的完整行为,并验证修复是否覆盖了解析、DNS、重定向、响应处理和网络出口。这样得到的结论更稳定,也更容易转化为长期有效的工程措施。

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

0篇意见

推荐意见

没有意见。

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