CodeQL 文档

禁用 Netty HTTP 标头验证

ID: java/netty-http-request-or-response-splitting
Kind: problem
Security severity: 6.1
Severity: error
Precision: high
Tags:
   - security
   - external/cwe/cwe-93
   - external/cwe/cwe-113
Query suites:
   - java-code-scanning.qls
   - java-security-extended.qls
   - java-security-and-quality.qls

单击以在 CodeQL 存储库中查看查询

将用户输入(例如,HTTP 请求参数)直接写入 HTTP 标头可能会导致 HTTP 请求拆分或响应拆分漏洞。

HTTP 响应拆分可能导致 XSS 和缓存中毒等漏洞。

HTTP 请求拆分允许攻击者将其他 HTTP 请求注入到客户端的传出套接字连接中。这可能允许攻击者执行类似 SSRF 的攻击。

在 servlet 容器的上下文中,如果用户输入包含空行,并且 servlet 容器不转义空行,则远程用户可能导致响应变为两个单独的响应。然后,远程用户可以控制一个或多个响应,这也是 HTTP 响应拆分。

建议

以与防范跨站脚本相同的方式防范 HTTP 标头拆分。在将任何数据传递到 HTTP 标头之前,请检查数据中是否有特殊字符,或转义存在的任何特殊字符。

如果代码直接调用 Netty API,请确保将 validateHeaders 参数设置为 true

示例

以下示例显示了以两种不同方式将“name”参数写入 cookie 的情况。第一种方式直接将其写入 cookie,因此容易受到响应拆分攻击。第二种方式首先删除所有特殊字符,从而避免了潜在问题。

public class ResponseSplitting extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
	throws ServletException, IOException {
		// BAD: setting a cookie with an unvalidated parameter
		Cookie cookie = new Cookie("name", request.getParameter("name"));
		response.addCookie(cookie);

		// GOOD: remove special characters before putting them in the header
		String name = removeSpecial(request.getParameter("name"));
		Cookie cookie2 = new Cookie("name", name);
		response.addCookie(cookie2);
	}

	private static String removeSpecial(String str) {
		return str.replaceAll("[^a-zA-Z ]", "");
	}
}

示例

以下示例展示了使用带有 HTTP 响应拆分验证配置的“netty”库。第二种方法将在使用参数构建 HTTP 响应之前验证这些参数。

import io.netty.handler.codec.http.DefaultHttpHeaders;

public class ResponseSplitting {
    // BAD: Disables the internal response splitting verification
    private final DefaultHttpHeaders badHeaders = new DefaultHttpHeaders(false);

    // GOOD: Verifies headers passed don't contain CRLF characters
    private final DefaultHttpHeaders goodHeaders = new DefaultHttpHeaders();

    // BAD: Disables the internal response splitting verification
    private final DefaultHttpResponse badResponse = new DefaultHttpResponse(version, httpResponseStatus, false);

    // GOOD: Verifies headers passed don't contain CRLF characters
    private final DefaultHttpResponse goodResponse = new DefaultHttpResponse(version, httpResponseStatus);
}

示例

以下示例展示了使用带有 HTTP 请求拆分验证配置的 netty 库。示例中推荐的第二种方法将在使用参数构建 HTTP 请求之前验证这些参数。

public class NettyRequestSplitting {
    // BAD: Disables the internal request splitting verification
    private final DefaultHttpHeaders badHeaders = new DefaultHttpHeaders(false);

    // GOOD: Verifies headers passed don't contain CRLF characters
    private final DefaultHttpHeaders goodHeaders = new DefaultHttpHeaders();

    // BAD: Disables the internal request splitting verification
    private final DefaultHttpRequest badRequest = new DefaultHttpRequest(httpVersion, method, uri, false);

    // GOOD: Verifies headers passed don't contain CRLF characters
    private final DefaultHttpRequest goodResponse = new DefaultHttpRequest(httpVersion, method, uri);
}

参考

  • ©GitHub, Inc.
  • 条款
  • 隐私