SV.HTTP_SPLIT

Http Response Splitting

This error is reported when a value from an HTTP client or database appears, without validation, in a method that writes to an HTTP header. The SV.XSS.* checkers cover similar attacks.

This checker helps to make sure input validation is used consistently. If the code is designed with specific validation utilities and appropriate annotations are added to a knowledge base file, this checker will report issues for code paths where validation was forgotten. See Tuning Java analysis.

As of release 2023.2, this checker supports Jakarta EE.

Vulnerability and risk

"HTTP Response Splitting" is a technique for attacking applications. It enables various new attacks such as web cache poisoning, cross-user defacement, hijacking pages with sensitive user information and cross-site scripting (XSS). This attack technique, and the attacks that are derived from it, can happen in most web environments and result from an application not rejecting illegal user input such as malicious or unexpected characters.

The essence of HTTP Response Splitting is the attacker's ability to send a single HTTP request that forces the web server to form an output stream, which is then interpreted by the target as two HTTP responses instead of the normal single response. The first response may be partially controlled by the attacker, but this is less important. What is more important is that the attacker completely controls the form of the second response (header). Once this is possible, the attacker can complete the attack by sending two requests through the target. The first one invokes two responses from the web server, and the second request would typically be to some innocent resource on the web server. However, the second request would be matched, by the target, to the second HTTP response, which is fully controlled by the attacker. The attacker therefore tricks the target into believing that a particular resource on the web server (designated by the second request) is the server's HTTP response (server content), while it is in fact data forged by the attacker through the web server -- this is the second response.

Klocwork security vulnerability (SV) checkers identify calls that create potentially dangerous data; these calls are considered unsafe sources. An unsafe source can be any data provided by the user, since the user could be an attacker or has the potential for introducing human error.

Mitigation and prevention

Validate all input data, even when coming from a semi-trusted source such as a database. Especially check for a Carriage Return followed by a Line Feed (CRLF) combination.

Vulnerable code example 1

Copy
    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 reports an SV.HTTP_SPLIT defect at line 7, indicating: 'url' contains data coming from an HTTP request parameter and might be tainted (line 3). This value is used to send an HTTP redirect on line 20.

Vulnerable code example 2

Copy
    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 reports an SV.HTTP_SPLIT defect at line 7, indicating: 'url' contains data coming from an HTTP request parameter and might be tainted (line 3). This value is used to send an HTTP redirect on line 20.

Vulnerable code example 3

Copy
@GetMapping("/vuln")
    public String vuln(HttpServletResponse response, HttpServletRequest request) throws IOException {
        response.sendRedirect(request.getParameter("HIDDEN_URL"));
        return "Response with header using HttpServletResponse";
    }

Klocwork reports an SV.HTTP_SPLIT defect due to data coming from an HTTP request parameter on line 3.

Fixed code examples

You can implement a number of helper methods to validate input for safe use inside header fields.

Restriction: Methods 1 and 2 check only for the presence of newlines. This should be enough to prevent SV.HTTP_SPLIT but depending on how this value is used later, it may not be sufficient.

Method 1

Validate the input string and ensure it does not lead to header splitting hazards.

Copy
    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;
    }

An exception is thrown if the parameter is not safe.

Method 2

Validate the parameter for safety with regard to header splitting attacks.

Copy
    private static boolean validateNoSvHttpSplit(String s) {
        if (s.contains("\r") || s.contains("\n")){
            return false;
        }
        return true;
    }

The message returns true if the parameter is safe to use.

Method 3

Apply custom Java KB to annotate helper functions.

Copy
@Bind("SV.HTTP_SPLIT")
public class WelcomeController {
    private static String validateNoSvHttpSplitOrThrow(@Check String s);
    private static boolean validateNoSvHttpSplit(@CheckTrue String s);
}

Use the annotated helpers to ensure the safety of your parameters.

Copy
    @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";
    }

Extension

This checker can be extended through the Klocwork knowledge base. See Tuning Java analysis for more information.