服务端请求伪造
当用户能够诱导应用程序向攻击者指定的域名发起 HTTP 请求时,就会产生服务端请求伪造(SSRF)漏洞。如果应用程序有权访问私有或内部网络,攻击者甚至可以利用该漏洞让应用程序向内部服务器发起请求。
我们将通过一些示例深入探讨这一漏洞,帮助您更好地理解其实际表现。
假设有一个 API,它接收用户提供的 URL 并生成该网页的图片,例如用于页面预览或导出功能。
ts
let url = request.params.url;
let response = http.get(url);
let render = response.render();
return render.export();
由于 URL 参数由用户控制,攻击者可以借此访问任何他们想要的 URL。在某些情况下,根据所使用的访问库,甚至可以使用“file://”协议读取本地文件。
在 AWS 环境中,滥用 SSRF 漏洞的一种常见方式是访问 AWS 元数据 API,其中可能包含 AWS API 的凭证。这可能导致攻击者进一步获取账户内其他 AWS 资源的访问权限,显然,这是我们极力避免的情况。
缓解措施
缓解 SSRF 漏洞有时非常棘手,很大程度上取决于代码的具体实现目标。根据业务需求,可以采取不同的缓解策略。
避免使用用户指定的 URL
在某些情况下,您可以优化功能实现,使其无需依赖用户提供的任意 URL。如果可行,这是缓解 SSRF 风险最有效的方法。
最小化功能权限
如果您正在实现 PDF 导出功能,可能会倾向于直接使用无头浏览器(headless browser)对页面进行截图。但考虑到浏览器的复杂性及其暴露的大量功能和攻击面,这种做法并不总是明智的。
针对具体任务选择合适的工具至关重要。在某些情况下,简单的 HTTP 客户端就足够了。我们总能采取措施来最小化功能权限,从而减少攻击面和攻击向量。例如,对于 HTTP 客户端:
- 禁止自动跳转(Redirects)
- 仅允许 HTTPS 协议,禁用其他所有协议
潜在的陷阱
重定向与 iframe
针对私有资源(如 IP 地址或内部主机名)防范 SSRF 的一种常见做法是:解析用户提供的 URL,并使用“黑名单”来阻止对敏感资源的访问。
值得注意的是,这种方法在大多数情况下并不奏效,因为如果客户端支持 HTTP 重定向、HTML/JavaScript 重定向,或者能够渲染 iframe 等复杂元素,攻击者便可以轻松绕过这些限制。
攻击者可以向存在漏洞的应用程序提供一个 URL,该页面会通过 HTTP 301/302 重定向、HTML Meta 重定向、在加载时通过 JavaScript 设置当前 URL,或嵌入显示内部资源的 iframe,从而重定向到敏感资源。这实际上绕过了对原始 URL 进行验证的任何尝试。
DNS 重绑定
另一种“类型”的重定向也可以通过 DNS 实现。防止 SSRF 攻击的一种常见方法是执行以下操作:
- 解析提供的 URL
- 获取主机名并进行 DNS 查询
- 如果解析结果为内部/私有 IP,则拒绝该 URL;如果是公网 IP,则接受该 URL
由于容易受到“DNS 重绑定”攻击,这种方法实际上并不有效。DNS 重绑定的原理是利用大多数网络栈(如 Linux 和 Windows 的网络栈)在远程主机关闭 TCP 连接时的标准行为。
当远程主机强制关闭连接时,系统会尝试再次进行 DNS 查询以重新解析 IP 地址,然后重新连接。
这使得攻击者能够执行以下操作:
- 为 `rebinding.attacker.com` 创建一个 DNS 条目,指向一个具有开放 HTTP 端口且 TTL(生存时间)非常短的公网 IP 地址
- 将该 URL(例如:https://rebinding.attacker.com/)提交给存在漏洞的应用程序。应用程序会检查解析出的 IP 是否为私有 IP,确认不是后,便认为该请求是安全的并继续执行操作
- 一旦建立 HTTP 连接,将 “rebinding.attacker.com” 的 DNS 条目更改为内部 IP 地址
- 强制关闭 HTTP 连接
- 这会导致应用程序重新解析 “rebinding.attacker.com” 的 IP 地址,而此时该地址已指向内部 IP
- 由于 IP 解析保护检查已经完成,且 DNS 条目的重新解析和重新连接均在内核中发生,应用程序并未察觉到 IP 已经更改
这有效地绕过了针对解析为私有 IP 地址的 URL 的保护措施。
IPv4 与 IPv6
绕过“黑名单”的另一种常见方法是使用 IPv6。由于所有 IPv4 地址都可以用 IPv6 地址表示,因此通常可以通过使用一个映射到目标 IPv4 地址的 IPv6 地址来绕过黑名单。
实用安全编码
探索安全编码指南,了解并缓解 OWASP Top 10 等软件漏洞,并通过引导式训练任务在真实的应用程序模拟中进行实践。