SV.HTTP_SPLIT
Http 响应拆分
当在写入 HTTP 头的方法中,存在来自 HTTP 客户端或数据库且未经验证的值时,将报告此错误。SV.XSS.* 检查器会涵盖类似攻击。
此检查器可帮助确保一致地使用输入验证。如果使用特定的验证实用工具设计代码,并且将适当的注释添加到知识库文件,则此检查器将针对忘记验证的代码路径报告问题。 请参阅调整 Java 分析。
从 2023.2 版本开始,此检查器将支持 Jakarta EE。
漏洞与风险
“HTTP 响应拆分”是一种攻击应用程序的技术。通过它可以实现各种新的攻击,例如 Web 缓存中毒、跨用户破坏、劫持含有敏感用户信息的页面,以及跨站脚本 (XSS)。大多数 Web 环境中都可能出现这种攻击技术,以及从其衍生出的其他攻击技术,从而导致应用程序不会拒绝非法的用户输入,例如恶意字符或非预期的字符。
HTTP 响应拆分的本质是攻击者可以发送能够强制 Web 服务器形成输出流的单个 HTTP 请求,该请求随后会被目标对象解释为两个 HTTP 响应,而非正常的单个响应。第一个响应可能在部分程度上被攻击者控制,但是这并不是最重要的。更重要的是攻击者可以完全控制第二个响应(标头)的形式。一旦这成为可能,攻击者就可以通过目标对象发送两个请求,从而完成攻击。第一个请求从 Web 服务器调用两个响应,而第二个请求通常会利用 Web 服务器上的某些不设防的资源。但是,目标对象会将第二个请求与第二个 HTTP 响应相匹配,而后者是完全由攻击者控制的。因此攻击者可以欺骗目标对象,使其相信 Web 服务器上的特定资源(由第二个请求指定)是服务器的 HTTP 响应(服务器内容),但实际上这是攻击者通过 Web 服务器伪造的数据,即第二个响应。
Klocwork 安全漏洞 (SV) 检查器可识别可能创建危险数据的调用;这些调用被视为不安全的来源。用户所提供的任何数据都可能是不安全的来源,因为用户可能是攻击者,或者可能引入人为错误。
缓解与预防
验证所有输入数据,即使这些数据来自数据库等不完全受信任的来源。尤其要检查回车后接换行 (CRLF) 的组合。
漏洞代码示例 1
import javax.servlet.http.*;
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String url = req.getParameter("HIDDEN_URL");
if (url.length() == 0) {
generatePage(req, resp);
} else {
resp.sendRedirect(url);
}
}
private void generatePage(HttpServletRequest req, HttpServletResponse resp) throws IOException {
PrintWriter wr = resp.getWriter();
wr.print("Hello, World!");
}
Klocwork 在第 7 行报告 SV.HTTP_SPLIT 缺陷,指出:url 包含来自 HTTP 请求参数的数据,因此可能已被污染(第 3 行)。该值用于在第 20 行中发送 HTTP 重定向。
漏洞代码示例 2
import jakarta.servlet.http.*;
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String url = req.getParameter("HIDDEN_URL");
if (url.length() == 0) {
generatePage(req, resp);
} else {
resp.sendRedirect(url);
}
}
private void generatePage(HttpServletRequest req, HttpServletResponse resp) throws IOException {
PrintWriter wr = resp.getWriter();
wr.print("Hello, World!");
}
Klocwork 在第 7 行报告 SV.HTTP_SPLIT 缺陷,指出:url 包含来自 HTTP 请求参数的数据,因此可能已被污染(第 3 行)。该值用于在第 20 行中发送 HTTP 重定向。
漏洞代码示例 3
@GetMapping("/vuln")
public String vuln(HttpServletResponse response, HttpServletRequest request) throws IOException {
response.sendRedirect(request.getParameter("HIDDEN_URL"));
return "Response with header using HttpServletResponse";
}
Klocwork 报告了 SV.HTTP_SPLIT 缺陷,因为数据来自 HTTP 请求参数(第 3 行)。
修正代码示例
您可以通过实现许多帮助程序方法来验证输入,以便在标头字段内安全使用。
Restriction: 方法 1 和 2 仅检查是否存在换行符。这应该足以防止 SV.HTTP_SPLIT,但根据此值之后的使用方式,此方法可能并不完善。
方法 1
验证输入字符串并确保它不会导致标头拆分风险。
private static String validateNoSvHttpSplitOrThrow(String s) throws IllegalArgumentException{
if (s.contains("\r") || s.contains("\n")){
throw new IllegalArgumentException("unexpected SV.HTTP_SPLIT hazard");
}
return s;
}
如果参数不安全,将会引发异常。
方法 2
针对标头拆分攻击,验证参数的安全性。
private static boolean validateNoSvHttpSplit(String s) {
if (s.contains("\r") || s.contains("\n")){
return false;
}
return true;
}
如果参数可以安全使用,消息将返回 true。
方法 3
应用自定义 Java KB 来注释帮助程序函数。
@Bind("SV.HTTP_SPLIT")
public class WelcomeController {
private static String validateNoSvHttpSplitOrThrow(@Check String s);
private static boolean validateNoSvHttpSplit(@CheckTrue String s);
}
使用带注释的帮助程序来确保参数的安全性。
@GetMapping("/checked_except")
public String checkedExcept(HttpServletResponse response, HttpServletRequest request) throws IOException {
response.sendRedirect(validateNoSvHttpSplitOrThrow(request.getParameter("HIDDEN_URL")));
return "Response with header using HttpServletResponse";
}
@GetMapping("/checked_except")
public String checkedExcept2(HttpServletResponse response, HttpServletRequest request) throws IOException {
String hidden_url = request.getParameter("HIDDEN_URL");
validateNoSvHttpSplitOrThrow(hidden_url);
response.sendRedirect(hidden_url);
return "Response with header using HttpServletResponse";
}
@GetMapping("/checked_bool")
public String checkedBool(HttpServletResponse response, HttpServletRequest request) throws IOException {
String hidden_url = request.getParameter("HIDDEN_URL");
if (validateNoSvHttpSplit(hidden_url)) {
response.sendRedirect(validateNoSvHttpSplitOrThrow(hidden_url));
}else{
return "do something else";
}
return "Response with header using HttpServletResponse";
}
外部指导
扩展
此检查器可通过 Klocwork 知识库进行扩展。有关详情,请参阅调整 Java 分析。