我创建了一个简单的spring-web项目,该项目中只有一个控制器,其代码为:
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);
}
}
然后我试着用curl触发CRLF注入漏洞,就像以下命令一样:
curl -vvvv "http://127.0.0.1:8080/crlf" --data "id=xrnLocation:%20https://www.google.com"
curl -vvvv "http://127.0.0.1:8080/crlf" --data "id=x%0d%0aLocation:%20https://www.google.com"
但他们都通过CRLF返回了太空:
HTTP/1.1 200
Cookies: Location: https://www.google.com
Content-Length: 0
Date: Mon, 31 Aug 2020 09:27:58 GMT
那么,我该如何编写一段易受CRLF注入攻击的代码呢?是不是因为Tomcat或Spring过滤了我的输入参数,所以这不起作用?但我一直在追踪代码,没有得到任何看起来像过滤器的代码。
我的pom.xml文件是:
<?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>
是不是因为Tomcat或Spring过滤了我的输入参数,所以这不起作用?
根据https://security.stackexchange.com/questions/172908/vulnerable-crlf-environment,对于Tomcat的某些版本,答案是肯定的。
事实上,自CVE-2012-3544被修复以来,可能适用于Tomcat的所有版本1;即6.0.36之后的Tomcat 6.x和7.0.29之后的Tomcat 7.x。
我一直在追踪代码,没有得到任何看起来像过滤器的代码。
我做了一些代码挖掘。当Tomcat输出堆栈将响应头值写入输出流时,它将ASCII控制字符(除了TAB(和DEL转换为空格。这是在AjpMessage
类的public void appendBytes(MessageBytes mb)
方法中完成的。(可能还有其他地方。(
如何将此代码更改为易受CRLF注入攻击?
我怀疑2你做不到。至少Tomcat没有。
1-CVE指的是一种特定的CRLF注入攻击,它是由Tomcat错误而非Web应用程序对响应标头的不安全使用造成的。您尝试的注入不会利用该漏洞
2-我没有检查是否可以通过标头名称进行注入,但很难理解为什么一个普通的Web应用程序需要使用请求参数值作为(或在(响应标头名称
Tomcat(9.0.37(使用Http11Processor类来准备调用Http11OutputBuffer的响应(请参阅其prepareResponse((方法(-请参阅sendHeader((方法实现。它调用private write((方法,该方法用空格替换换行符。Undertow和Jetty也有自己的消毒方式。