问题描述
我创建了一个简单的spring Web项目,该项目中只有一个Controller,其代码为:
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注入vuln,如下所示:
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"
但是所有通过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 ;即Tomcat 6.x(6.0.36之后)和7.x(7.0.29之后)。
我一直在跟踪代码,没有发现任何看起来像过滤器的代码。
我做了一些代码挖掘。当Tomcat输出堆栈将响应标头值写入输出流时,它将ASCII控制字符(除TAB外)和DEL转换为空格。这是在public void appendBytes(MessageBytes mb)
类中的AjpMessage
方法中完成的。 (可能还有其他地方。)
如何更改此代码使其容易受到CRLF注入的攻击?
我怀疑 2 你做不到。至少不是Tomcat。
1-CVE指的是特定的CRLF注入攻击,它是由Tomcat错误而不是Web应用程序不安全地使用响应头而引起的。您尝试的注入将无法利用该漏洞。
2-我没有检查是否可以通过标题名称进行注入,但是很难理解为什么普通的Web应用程序需要使用请求参数值作为(或在)响应标题名称。 / sup>
, 例如,Tomcat(9.0.37)使用Http11Processor类准备响应(请参阅其prepareResponse()方法),该响应调用Http11OutputBuffer-请参见sendHeader()方法的实现。它调用专用write()方法,该方法用空格替换换行符。 Undertow和Jetty也有自己的方式来清理标头。