在 Java 中防止服务器端请求伪造

信息安全 爪哇 ssrf
2021-08-10 02:47:20

该应用程序允许用户为其个人资料图片指定 URL。它从 URL 中获取数据并将其保存在服务器上。但是,该应用程序容易受到服务器端请求伪造 (SSRF) 的攻击——您可以指定 URL file:///etc/passwd,也可以访问本地 HTTP 服务,例如http://localhost:8080/.

解决此问题的最佳方法是什么?我的一些想法:

  • 将 URL 协议限制为 HTTP 和 HTTPS。
  • DNS 查找主机名并检查它不是本地地址。
  • 禁用重定向。

这似乎是一个好的开始——尽管 DNS 查找存在 TOCTOU 问题(实际上可能没问题,因为本地 DNS 会缓存)。

我的另一个想法是将代理放置在受限制的网段中,在那里它只能看到 Internet,并通过它发送请求。

我在网上查了这个,但是资料不多。这篇文章很不错。

1个回答

这是我目前正在使用的代码:

if(!url.getProtocol().startsWith("http"))
    throw new Exception();
InetAddress inetAddress = InetAddress.getByName(url.getHost());
if(inetAddress.isAnyLocalAddress() || inetAddress.isLoopbackAddress() || inetAddress.isLinkLocalAddress())
    throw new Exception();
HttpURLConnection conn = (HttpURLConnection)(url.openConnection());
conn.setInstanceFollowRedirects(false);
conn.connect();
IOUtils.copy(conn.getInputStream(), out);

它强制执行 HTTP 或 HTTPS,禁止本地地址,并禁用重定向。但是,它仍然存在 TOCTOU(检查时间,使用时间)缺陷。