SV.SSRF.URI

URI 基于失效的用户输入。

SV.SSRF.URI 检查器会标记以下情况:Java Web 服务器应用程序收到来自上游组件的 URL 或类似请求并检索此 URL 的内容,但未充分确保将请求发送到预期目标。

从 2023.2 版本开始,此检查器将支持 Jakarta EE。

漏洞与风险

服务器端请求伪造 (SSRF) 这种攻击载体会滥用应用程序,来与外部或内部网络或者计算机本身进行交互。促成这种载体的原因之一是对不同类型的 URL 处理不当,例如:

  • 外部服务器上的图像文件,例如,用户输入其头像图片的 URL,供应用程序下载和使用。
  • 自定义 Webhook,用户在其中指定 Webhook 处理程序或回调 URL。
  • 内部请求,请求与另一个服务进行交互以提供特定函数。经常会发送用户数据以进行处理,如果处理不当,可能会导致注入攻击。

请注意,SSRF 并非仅限于 HTTP 协议。第一个请求通常为 HTTP,但是如果应用程序本身执行第二个请求,它可能会使用其他协议(例如 FTP、SMB、SMTP)或方案(例如 file://、phar://、gopher://、data://、dict:// 等)。

如果应用程序容易遭受 XML 外部实体 (XXE) 注入,那么它可能会被利用以执行 SSRF 攻击

缓解与预防

确保所提供的 IP 地址属于已识别的可信应用程序的 IP 地址。

漏洞代码示例

复制
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;

public class SV_SSRF_URI_POSITIVE_JAKARTA {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException,URISyntaxException, InterruptedException {
        HttpClient client = HttpClient.newHttpClient();
        String url = req.getParameter("uri");
        URI uri = new URI(url);
        // BAD: a request parameter is incorporated without validation into a Http request
        HttpRequest r = HttpRequest.newBuilder(uri).build();
        client.send(r, null);
    }
}

在此示例中,通过使用 req.getParameter("uri") 从 HttpServletRequest 中提取的 String URL 参数正用于 HttpRequest 连接,但未经过验证。Klocwork 在第 13 行报告了缺陷,指出“失效的用户输入被用作 URI 对象的一部分”。

修正代码示例

复制
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;

public class SV_SSRF_URI_POSITIVE_JAKARTA {
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, URISyntaxException, InterruptedException {
      HttpClient client = HttpClient.newHttpClient();

      // GOOD: the request parameter is validated against a known fixed string or valid source of IP address
      String url = req.getParameter("uri");
      if (VALID_URI.equals(url)) {
       URI uri = new URI(url);
       HttpRequest r = HttpRequest.newBuilder(uri).build();
       client.send(r, null);
     }
  }

在此修正示例中,Klocwork 不再报告缺陷,因为使用 req.getParameter("uri") 从 HttpServletRequest 中提取的 URL 参数在用于 HttpRequest 连接之前,已针对可信的 URL 进行了验证。

安全培训

应用程序安全培训材料由 Secure Code Warrior 提供。

扩展

可调整此检查器,以检查用户是否经过授权以访问项目中使用的受保护的 API。可以通过在 .jkb 文件中使用 @CheckerParam 选项来进行此操作。有关详情,请参阅调整 Java 分析。