准则

服务器端请求伪造

当用户能使应用程序向攻击者确定的域发出 HTTP 请求时,就会出现服务器端请求伪造漏洞。如果应用程序可以访问专用/内部网络,攻击者也可以使应用程序向内部服务器发出请求。 

我们将通过一些例子来进一步了解它的实际效果。

考虑一种应用程序接口,它可以从用户处获取 URL 并生成用户提供的 URL 的图片,例如用于预览或导出页面。 

ts
let url = request.params.url;

let response = http.get(url);
let render = response.render();

return render.export();

由于 URL 参数由用户控制,攻击者可以随心所欲地访问任何 URL。在某些情况下,根据用于访问 URL 的库,甚至可以使用 "file://"方案访问本地文件。  

在 AWS 上托管时,滥用 SSRF 漏洞的一种常见方式是使用该漏洞访问 AWS 元数据 API,其中可能包含 AWS API 的凭据。这可能导致进一步访问账户内的其他 AWS 资源,可想而知,这并不理想。

缓解

缓解 SSRF 漏洞有时非常棘手,这在很大程度上取决于相关代码试图实现的目标。根据不同的要求,可以采取不同的缓解措施。

避免用户自定义 URL

在某些情况下,您可能能够以一种不依赖于用户提供任意 URL 的方式实现某项功能。如果有可能的话,这是降低 SSRF 风险的最有效方法。

最小化能力 

如果您要实现 PDF 导出功能,可能会倾向于简单地使用无头浏览器并对页面进行截图。考虑到浏览器的复杂性以及浏览器暴露的大量功能和攻击面,这种做法并不总是可取的。

为手头的工作使用合适的工具非常重要。在某些情况下,一个简单的 HTTP 客户端就足够了。总有些事情可以做,以尽量减少功能,从而减少可用的攻击面/载体。例如 HTTP 客户端:

  • 禁用以下重定向功能
  • 禁用 HTTPS 以外的所有方案

存在一些隐患

重定向和 iframe

防止在私有资源(IP 地址或内部主机名)上使用 SSRF 的常见方法是解析用户提供的 URL,并使用 "拒绝列表 "来阻止对敏感资源的访问。

值得注意的是,这种方法在大多数情况下并不有效,因为在客户端遵循 HTTP 重定向、HTML/JavaScript 重定向或可以呈现 iframe 等复杂元素的情况下,可以绕过这种方法。

攻击者可以通过 HTTP 301/302、HTML Meta 重定向、在加载时使用 Javascript 设置当前 URL 或嵌入显示内部资源的 iframe 等方式,将 URL 提供给托管页面的易受攻击应用程序,该页面会重定向到敏感资源。这实际上绕过了验证原始 URL 的任何尝试。 

DNS 重绑定
另一种 "类型 "的重定向也可以通过 DNS 完成。防止 SSRF 攻击的一种常见方法是采取以下措施:

  1. 解析所提供的 URL
  2. 获取主机名,并进行 DNS 查询
  3. 如果 URL 解析到内部/私有 IP,则拒绝该 URL;如果 URL 解析到公共 IP,则接受该 URL

由于容易受到 "DNS 重绑定 "的影响,这种方法实际上并不有效。DNS 重绑定之所以有效,是因为当远程主机关闭 TCP 连接时,大多数网络协议栈(如 Linux 和 Windows 的协议栈)的标准行为。
当远程主机强行关闭连接时,它会在进行另一次 DNS 查询以重新解析 IP 地址后尝试重新连接。 

这样,攻击者就可以进行以下操作:

  1. 为 "rebinding.attacker.com "创建一个 DNS 条目,该条目包含一个公共 IP 地址和一个开放的 HTTP 端口,且 TTL(Time-to-live)极短。
  2. 向有漏洞的应用程序提交 URL(例如:https://rebinding.attacker.com/)。它会检查以确保解析的 IP 不是私有 IP(其实不是),然后在认为安全的情况下继续执行请求的操作
  3. 一旦建立 HTTP 连接,"rebinding.acker.com "的 DNS 条目就会更改为内部 IP 地址
  4. HTTP 连接被强制关闭
  5. 这将导致应用程序重新解析 "rebinding.attacker.com "的 IP 地址,该地址现在指向一个内部 IP 地址
  6. 由于 IP 解析保护已经发生,而且 DNS 条目的重新解析和重新连接都是在内核中进行的,因此应用程序不会意识到 IP 已发生变化这一事实。

这实际上绕过了防止提供解析到私人 IP 地址的 URL 的保护措施。 

IPv4 与 IPv6

绕过 "拒绝列表 "的另一种常见方法是使用 IPv6。由于所有 IPv4 地址都可以用 IPv6 地址来表示,因此通常可以通过使用 IPv6 地址来绕过拒绝列表,该地址也可以映射到想要访问的 IPv4 地址。