Spring/대용량 파일 전송

[7] 대용량 파일 전송 시스템 개발 - 파일 확장자 변조 검증, Tika

carrotweb 2026. 8. 23. 01:01
728x90
반응형

모든 청크 데이터(이진 데이터)를 다 받은 후 내부의 바이트를 읽어 파일 형식(MIME Type)과 파일 확장자가 같은지 비교할 수 있습니다. 검증을 통해 악성 스크립트나 해킹 실행 파일이 문서 파일이나 이미지 파일로 위장해 서버로 업로드되는 것을 원천적으로 차단할 수 있어 보안이 강화됩니다.

 

아파치 티카(Apache Tika, https://tika.apache.org/)

Tika는 다양한 파일에서 메타데이터와 텍스트를 감지하고 추출하는 라이브러리

콘텐츠 유형 감지(파일 시작 부분 근처에서 특수("magic") 바이트 패턴을 찾아 파일 유형을 감지)

 

1. Tika를 사용하기 위해 pom.xml에 추가합니다.

[Maven]
<!-- https://mvnrepository.com/artifact/org.apache.tika/tika-core -->
<dependency>
    <groupId>org.apache.tika</groupId>
    <artifactId>tika-core</artifactId>
    <version>3.0.0</version>
</dependency>

[Gradle]
org.apache.tika:tika-core

 

2. 파일의 MIME Type을 식별하여 파일의 확장자가 변조되었는지 확인합니다.

// 파일 MIME 타입과 파일 확장자의 MIME 타입 비교
Tika tika = new Tika();
String mimeType = tika.detect(tempFile);
if (isFileMineType(tempFileExtension, mimeType)) {
    :
}

 

파일 확장자별 MIME 타입

.doc	application/msword
.docx	application/vnd.openxmlformats-officedocument.wordprocessingml.document
.xls	application/vnd.ms-excel
.xlsx	application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
.ppt	application/vnd.ms-powerpoint
.pptx	application/vnd.openxmlformats-officedocument.presentationml.presentation
.pdf	application/pdf
.bmp	image/bmp
.gif	image/gif
.jpg, .jpeg	image/jpeg
.png	image/png
.avi	video/x-msvideo
.mp3	audio/mpeg
.mp4	video/mp4
.mpeg	video/mpeg
.oga	audio/ogg
.ogv	video/ogg
.wav	audio/wav
.weba	audio/webm
.webm	video/webm
.webp	image/webp
.zip	application/zip, application/x-zip-compressed

 

파일 확장자에 대응하는 MIME Type와 Tika.detect에서 받은 MIME Type를 비교합니다.

/**
 * 파일 확장자와 파일 MIME Type를 비교합니다.
 * @param fileExtension 파일 확장자
 * @param MIMEType 파일 MIME Type
 * @return 비교 결과
 */
private boolean isFileMineType(String fileExtension, String MIMEType) {
    boolean result = false;

    String[] fileExtArray = {"doc", "docx", "xls", "xlsx", "ppt", "pptx", "pdf",
            "bmp", "gif", "jpg", "jpeg", "png",
            "avi", "mp3", "mp4", "mov", "mpeg", "oga", "ogv", "wav", "weba", "webm", "webp",
            "zip"};
    String[] MIMETypeArray = {"application/msword",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
            "application/vnd.ms-excel",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
            "application/vnd.ms-powerpoint",
            "application/vnd.openxmlformats-officedocument.presentationml.presentation",
            "application/pdf",
            "image/bmp", "image/gif", "image/jpeg", "image/jpeg", "image/png",
            "video/x-msvideo", "audio/mpeg", "video/mp4", "video/quicktime", "video/mpeg", "audio/ogg",
            "video/ogg", "audio/wav", "audio/webm", "video/webm", "image/webp",
            "application/zip,application/x-zip-compressed"};

    List<String> fileExtList = new ArrayList<>(Arrays.asList(fileExtArray));
    int pos = fileExtList.indexOf(fileExtension.toLowerCase());
    if (pos != -1) {
        String fileMIMEType = MIMETypeArray[pos];
        String[] fileMIMETypeArray = fileMIMEType.split(",");
        for (int index = 0; index < fileMIMETypeArray.length; index++) {
            if (fileMIMETypeArray[index].equals(MIMEType)) {
                result = true;
                break;
            }
        }
    }

    return result;
}

 

 

728x90
반응형