mtfly
mtfly

Reputation: 35

How can i change this code to be vulnerable of CRLF injection?

I create a simple spring web project, and there is only one Controller in the project, its code is:

package com.example.sbtest.controller;

import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MainController {
  @RequestMapping("/crlf")
  @ResponseBody
  public void CRLFInjectVuln(HttpServletResponse response, @RequestParam("id") String id) {
    response.addHeader("test", id);
  }
}

Then i tried to trigger the CRLF inject vuln with curl like these commands:

curl -vvvv "http://127.0.0.1:8080/crlf" --data "id=x\r\nLocation:%20https://www.google.com"
curl -vvvv "http://127.0.0.1:8080/crlf" --data "id=x%0d%0aLocation:%20https://www.google.com"

But all of them returned as through the CRLF was replaced to space:

HTTP/1.1 200 
Cookies:   Location: https://www.google.com
Content-Length: 0
Date: Mon, 31 Aug 2020 09:27:58 GMT


So, how could i write a piece of code that are vulnerable of CRLF injection? Could it because of the Tomcat or the Spring filtered my input parameter, so this didn't work? But i tracked down all the way through the code, didn't get any code seem like a filter.


My pom.xml file is:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>sbtest</artifactId>
    <version>0.1</version>
    <name>sbtest</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Upvotes: 2

Views: 2305

Answers (2)

t.olev
t.olev

Reputation: 143

Tomcat (9.0.37), for example, uses the Http11Processor class to prepare the response (see its prepareResponse() method) which calls Http11OutputBuffer - see the sendHeader() method implementation. It calls the private write() method which substitute the new line characters with space. Undertow and Jetty have their own ways to sanitize the headers too.

Upvotes: 0

Stephen C
Stephen C

Reputation: 719386

Could it because of the Tomcat or the Spring filtered my input parameter, so this didn't work?

According to https://security.stackexchange.com/questions/172908/vulnerable-crlf-environment, the answer is yes for some versions of Tomcat.

In fact, probably for all versions of Tomcat since CVE-2012-3544 was fixed1; i.e. Tomcat 6.x after 6.0.36 and 7.x after 7.0.29.

I tracked down all the way through the code, didn't get any code seem like a filter.

I did some code digging. When the Tomcat output stack writes response header values to the output stream, it converts ASCII control characters (apart from TAB) and DEL into spaces. This is done in the public void appendBytes(MessageBytes mb) method in the AjpMessage class. (And possibly other places as well.)

How can I change this code to be vulnerable of CRLF injection?

I suspect2 that you can't. At least not with Tomcat.


1 - The CVE refers to a specific CRLF injection attack that was made possible by a Tomcat bug, not by a webapp's unsafe use of response headers. Your attempted injection would not have worked to exploit that bug.

2 - I didn't check whether injection might be possible via the header name, but it is hard to see why a normal webapp would need to use request parameter values as (or in) response header names.

Upvotes: 1

Related Questions