通过CVE-2023-24998了解上传的可能隐患
Apache Commons FileUpload场景
条件1: (影响版本)
<!-- Apache Commons FileUpload --><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.4</version></dependency>
条件2: (业务场景)如下使用场景是否对上传文件数量
和大小进行
校验和限制
1、调用org.apache.commons.fileupload
的地方
2、对commons-fileupload
二次封装的场景
Apache Tomcat场景
条件1: (影响版本)
条件2: (业务场景)如下使用场景是否对上传文件数量
和大小进行
校验和限制
1、调用org.apache.tomcat.util.http.fileupload
SpringBoot场景
1、服务使用spring-boot-starter-web包或者spring-boot-starter-tomcat
2、tomcat-embed-core的版本受影响
防御建议
1、禁用文件上传功能
1、在 Spring Boot 应用中,如果你想要禁用文件上传功能
spring.servlet.multipart.enabled=false
2、配置Multipart解析器的最大文件大小为0:
# application.propertiesspring.servlet.multipart.max-file-size=0Bspring.servlet.multipart.max-request-size=0B
3、禁用自动配置的Multipart解析器:
@SpringBootApplication(exclude = {MultipartAutoConfiguration.class})public class YourApplication {// ...}
4、业务上禁用
@Componentpublic class FileUploadFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;if (ServletFileUpload.isMultipartContent(req)) {// 拒绝请求并返回错误信息((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN, "File uploads are not allowed.");} else {chain.doFilter(request, response);}}// ... 其他 Filter 方法}
2、上传接口的业务对 上传文件数量
和大小
进校校验
1、业务层直接校验
@PostMapping("/upload")public ResponseEntity<?> handleFileUpload(@RequestParam("files") MultipartFile[] files) {// 检查文件数量是否超过限制if (files.length > MAX_FILE_COUNT) {throw new IllegalArgumentException("Too many files uploaded.");}for (MultipartFile file : files) {// 对每个文件进行大小检查if (file.getSize() > SINGLE_FILE_MAX_SIZE_IN_BYTES) {throw new IllegalArgumentException("File size exceeds the limit.");}// ... 处理文件上传逻辑 ...}// ...}
2、通过过滤器filter,
在Spring框架中,通常建议使用Spring自身的CommonsMultipartResolver
或者MultipartProperties
进行配置,而不是直接在过滤器中处理。
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.stereotype.Component;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;@Component
public class FileUploadFilter implements Filter {private static final int MAX_FILE_SIZE = 1048576; // 设置最大文件大小为1MB@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;// 检查是否为multipart/form-data类型的请求if (ServletFileUpload.isMultipartContent(httpRequest)) {// 使用Apache Commons FileUpload库解析请求ServletFileUpload upload = new ServletFileUpload();// 设置单个文件的最大大小upload.setSizeMax(MAX_FILE_SIZE);// 在这里可以尝试解析请求,并获取所有上传的文件项(FileItem)// 然后根据需要检查数量或抛出异常阻止进一步处理// 注意:这个例子只演示了如何设置最大文件大小,实际的文件数量限制需要手动遍历并计数// ...// 如果你希望允许继续进行,不在此处进行文件数量限制,则直接调用filter chainchain.doFilter(request, response);} else {// 对于非multipart请求,直接通过filter chainchain.doFilter(request, response);}}// ... 其他Filter接口实现方法
}
3、MultipartProperties
MultipartProperties
是Spring Boot的内部类,它封装了所有与多部分(multipart)请求处理相关的属性。通过在 application.properties 或 application.yml 中设置相关属性,你可以轻松地控制上传文件的大小限制等。
# 设置最大单个文件大小为10MB
spring.servlet.multipart.max-file-size=10MB
# 设置整个请求的最大大小为20MB
spring.servlet.multipart.max-request-size=20MB
# 设置临时目录
spring.servlet.multipart.location=/tmp
[Q&A] MultipartProperties 直接配置就可以生效吗?
是的,MultipartProperties 是Spring Boot自动配置的一部分,用于设置多部分(multipart)请求处理的相关属性。上述配置无需额外编写Java代码即可生效,Spring Boot将根据这些配置自动调整上传文件大小限制。这意味着你不需要手动创建 CommonsMultipartResolver 或 StandardServletMultipartResolver 的bean来实现这些功能,因为Spring Boot已经为你做好了这部分的集成和自动化配置。
4、CommonsMultipartResolver
在较早版本的Spring MVC中,我们通常会自定义一个 CommonsMultipartResolver
的bean来处理文件上传。但在Spring Boot 2.x之后,推荐使用内建的 StandardServletMultipartResolver,因为Spring Boot已经将其自动配置好并与Servlet标准API集成。
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;import javax.servlet.MultipartConfigElement;@Configuration
public class FileUploadConfig {@Bean(name = "multipartResolver")public CommonsMultipartResolver multipartResolver() {CommonsMultipartResolver resolver = new CommonsMultipartResolver();// 设置最大文件大小(以字节为单位)resolver.setMaxUploadSize(10485760); // 10MBreturn resolver;}// 对于Spring Boot 2.x以上版本,若要调整全局multipart配置,可以通过以下方式:@Beanpublic MultipartConfigElement multipartConfigElement() {MultipartConfigFactory factory = new MultipartConfigFactory();factory.setMaxFileSize("10MB"); // 单个文件最大大小factory.setMaxRequestSize("20MB"); // 整个请求最大大小return factory.createMultipartConfig();}
}
5、StandardServletMultipartResolver
在Spring Boot中,StandardServletMultipartResolver
是用于处理multipart请求(如文件上传)的默认解析器。由于Spring Boot已经自动配置了它,通常情况下你不需要手动创建这个bean。但是如果你想自定义其属性,可以在Spring配置类中进行如下配置:
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;import javax.servlet.MultipartConfigElement;@Configuration
public class FileUploadConfig {@Beanpublic MultipartResolver multipartResolver() {StandardServletMultipartResolver resolver = new StandardServletMultipartResolver();// 通过MultipartConfigElement进一步定制上传限制resolver.setResolveLazily(true); // 可选:延迟解析multipart请求,默认为falsereturn resolver;}// 设置全局multipart配置(例如最大文件大小和整个请求的最大大小)@Beanpublic MultipartConfigElement multipartConfigElement() {MultipartConfigFactory factory = new MultipartConfigFactory();factory.setMaxFileSize("10MB"); // 单个文件最大大小factory.setMaxRequestSize("20MB"); // 整个请求最大大小return factory.createMultipartConfig();}
}注意:
StandardServletMultipartResolver 类本身并不直接提供设置单个文件或整个请求大小的方法。
而是通过 MultipartConfigElement 进行配置,该配置会应用到所有的multipart解析。
3、如果使用tomcat作容器场景,可修改配置文件server.xml
<Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443"maxPostSize="10485760" /> <!-- 10 MB --> 即10 * 1024 * 1024字节
[Ref] Apache Commons FileUpload & Apache Tomcat拒绝服务漏洞预警(CVE-2023-24998)