[Spring MVC] MultipartResolver, CVE-2023-24998

ASk·2023년 3월 17일
0

Spring MVC

목록 보기
2/2
post-thumbnail

MultipartResolver

Spring 의 multipart file upload 를 위한 인터페이스

MultipartResolver 구현체

CommonsMultipartResolver

  • Apache Commons FileUpload를 사용하는 멀티파트 리졸버
  • multipart 처리를 apache commons fileupload 에게 위임하여 서블릿 컨테이너에
    종속적이지 않도록 처리 가능.
  • 컨테이너간에 최대 이식성 제공

StandardServletMultipartResolver

  • Servlet 3.0+ Part API를 사용하는 표준 멀티파트 리졸버
  • Servlet Container 에게 multipart 처리를 위임
  • 컨테이너에서 설정 및 처리 하므로 잠재적으로 컨테이너별 제한이 있을수 있다.
  • 어플리케이션을 컨테이너 구현차이에 노출 시킬수 있다.
  • 모든 서블릿 컨테이너에서 지원되지 않을 수 있다.

Tomcat 에서의 StandardServletMultipartResolver 사용

Apache Tomcat은 Jakarta Servlet 사양에 정의된 파일 업로드 기능을 제공하기 위해
Apache Commons FileUpload 의 이름이 변경된 패키지 복사본을 사용한다.

상단과 같이 톰캣을 사용할 경우(외장톰캣 또는 Spring Boot 내장 톰캣) StandardServletMultipartResolver 를 사용하면 CommonsMultipartResolver 를 사용한것과 유사하게 Part Api 를 통한 파일 처리시 컨테이너단에서 Apache Commons FileUpload 의 이름이 변경된 패키지 복사본을 사용해 파일을 처리한다.

Tomcat 을 사용한다면 CommonsMultipartResolver 를 사용할 필요가 없다.
단, 배포환경에서 톰캣 버전이 달라지는 경우라면 CommonsMultipartResolver 를 사용할만 하다.

Spring 6.0 에서의 CommonsMultipartResolver

  • Spring Framework 6.0, Servlet5 에서는 apache commons 의 CommonsMultipartResolver 를 더이상 사용할수 없다.
  • Spring Boot 3 부터 MultipartAutoConfiguration 에서 apache commons 관련 코드 삭제
  • 참조: Spring Docs, Multipart Resolver

Commons Fileupload 보안 취약점 CVE-2023-24998

Apache Commons FileUpload에서 발생하는 서비스 거부 취약점 으로서 1.5 버전 이전엔
multipart form 처리시 파일의 수 제한을 두지 않았기 때문에 Dos 공격 가능성이 있는 취약점이다.

제품명영향받는 버전해결 버전
Apache Commons FileUpload1.0-beta-1 ~ 1.41.5
Apache Tomcat11.0.0-M111.0.0-M3
Apache Tomcat10.1.0-M1~ 10.1.410.1.5
Apache Tomcat9.0.0-M1~ 9.0.709.0.71
Apache Tomcat8.5.0~ 8.5.848.5.85

Library 취약점 조치 사항

KISA 보안공지에 따르면 라이브러리 버전 업그레이드만 하면 되는것으로 보이지만 실제 별도 세팅이 필요하며 하단 사항을 공식 도큐먼트에서 확인할 수 있다.

the new configuration option (FileUploadBase#setFileCountMax) is not enabled by default and must be explicitly configured.

Tomcat9(9.0.71) 의 변경 사항

  • Tomcat GitHub Commit
  • tomcat9 (9.0.71, Spring Boot 기준 2.7.8 이상) 의 FileUploadBase 는 상단 커밋에서 수정되었다.

커밋 확인시 하단과 같이 fileCountMax 값을 세팅하였다.
upload.setFileCountMax(maxParameterCount - parameters.size());

fileCountMax 값은 Connector 의 maxParameterCount(default 10,000) - 처리된 파라미터 수

Apache Commons FileUpload 1.5 의 변경 사항

  • org.apache.commons.fileupload.FileUploadBase

365 ~ 368 라인을 보면 전달된 form item 개수와 지정된 fileCountMax 값을 비교하는 코드가 추가되었다.

주의 사항

multipart/form-data 형식에서 Request 로 부터 추출한 FileItem 은 File 형식만 포함하지 않으며
Form 에 전송된 파라미터 모두를 포함한다.

multipart 요청시 파일 3개 form item 10개의 경우 FileItem 13개로 처리된다.

하단 인터페이스 주석에서 확인 가능.

public interface FileItem extends FileItemHeadersSupport

This class represents a file or form item that was received within a multipart/form-data POST request.

프로젝트 적용

CommonsMultipartResolver 사용시

  1. Apache Commons FileUpload 버전 1.5로 변경
  2. CommonsMultipartResolver 커스텀 설정

Apache Commons FileUpload 버전을 올리더라도 CommonsMultipartResolver 의 경우
spring-web 의 코드이므로 headerEncoding 설정을 하지않는다면 fileCountMax 를 세팅하는
부분이 존재하지 않아 별도로 Override 를 해야한다.

public class CommonsMultipartResolverCustom extends CommonsMultipartResolver {

  @Override
  protected FileUpload newFileUpload(FileItemFactory fileItemFactory) {
    FileUpload fileUpload = super.newFileUpload(fileItemFactory);
    fileUpload.setFileSizeMax(1_073_741_824); // 100MB
    fileUpload.setFileCountMax(10_000);
    return fileUpload;
  }

}

@Bean
public CommonsMultipartResolverCustom multipartResolver() {
  return new CommonsMultipartResolverCustom();
}

만약 headerEncoding 설정까지 추가한다면 Override 없이 하단과 같이 세팅도 가능하다.

@Bean
public CommonsMultipartResolver multipartResolver() {
  CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
  multipartResolver.setDefaultEncoding("UTF-8");
  multipartResolver.setMaxUploadSize(1_073_741_824); // 100MB
  multipartResolver.getFileUpload().setFileCountMax(10_000);
  return multipartResolver;
}

StandardServletMultipartResolver 사용시

톰캣을 사용한다면 보안취약점이 패치가 적용된 톰캣 버전을 사용하면 된다.

만약 톰캣버전을 변경할 수 없는 경우라면 Apache Commons FileUpload 1.5
의존성 추가후 CommonsMultipartResolver 를 사용하도록 변경하면 된다.

profile
Backend Developer

0개의 댓글