게시글, 결재 문서 등 첨부파일을 업로드가 가능한 페이지 일 경우, 업로드가 가능한 파일 확장자를 화이트 리스트로 관리하거나, 업로드가 불가능한 파일 확장자를 블랙 리스트로 관리하여야 한다.
1. 첨부파일 업로드를 제한해야하는 확장자
- 업로드가 불가능한 확장자를 블랙리스트로 관리하여, 클라이언트 및 서버측에서 모두 체크하여 업로드를 막아야 한다.
확장자 명 | 비고 | 확장자명 | 비고 |
.exe | 실행파일 | .dll | dll 파일 |
.jsp | jsp 파일 | .jspx | jspx 파일 |
.php | php 파일 | .asp | asp 파일 |
.aspx | aspx 파일 | .java | java 파일 |
.bat | bat 파일 | .pdb | pdb 파일 |
.vbs | vbs 파일 | ||
2. 파일 변조 체크 로직
- 자바스크립트
function fileCheck(fileName){
const filter = ['jpg', 'png', 'jpeg', 'svg', 'heic', 'gif', 'tiff']
const fileExt = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length).toLowercase();
//해당 확장자에 포함되지 않으면 return false
filter.map(e => {
if(e != fileExt) {
alert('이미지 확장자만 업로드할 수 있습니다.')
return false
}
})
}
- Spring Apache Tika 사용
html 파일 하나를 생성하고 파일 이름을 변경하여 확장자를 png로 변경을 한다.
그리고 파일 업로드를 진행하면 1단계에서 작성한 자바스크립트에서 png 이미지 파일이라 인식을 하여 업로드가 정상적으로 진행이 된다.
만일 악의적으로 스크립트를 작성하여 파일을 업로드하게 된다면 권한을 가지게 된다는 등 공격을 당할 수 있다고 한다.
이를 어떤 식으로 예방하면 되는지 아래 코드를 확인해보자.
업로드한 파일은 'test.html'로 처음 생성하여 'test.png'로 이름을 바꿔주었다.
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>2.9.1</version>
</dependency>
tika dependency를 추가하고 maven update를 진행해준다.
https://mvnrepository.com/artifact/org.apache.tika/tika-core
@PostMapping("/file-upload")
public ResponseEntity fileUpload(@RequestParam("file")MultipartFile uploadFile) {
fileService.fileUpload(uploadFile);
return ResponseEntity.ok().build();
}
Controller에서 MultipartFile로 파일을 받고 Service로 넘겨준다.
@Service
public class FileServiceImpl implements FileService {
@Override
public void fileUpload(MultipartFile uploadFile) {
try(InputStream inputStream = uploadFile.getInputStream()) {
System.out.println("Content Type : " + uploadFile.getContentType());
if(!uploadFile.isEmpty()) {
boolean isValid = FileUtils.validImgFile(inputStream);
if(!isValid) {
// exception 처리
System.out.println("이미지 파일만 업로드 가능합니다.");
}
// 업로드 로직
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileUtils 에 확장자 체크 기능을 만들어주었다.
public class FileUtils {
private static final Tika tika = new Tika();
public static boolean validImgFile(InputStream inputStream) {
try {
List<String> notValidTypeList = Arrays.asList("image/jpeg", "image/pjpeg", "image/png", "image/gif", "image/bmp", "image/x-windows-bmp");
String mimeType = tika.detect(inputStream);
System.out.println("MimeType : " + mimeType);
boolean isValid = notValidTypeList.stream().anyMatch(notValidType -> notValidType.equalsIgnoreCase(mimeType));
return isValid;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
}
FileUtils에 tika를 이용하여 mime type을 체크해준다.
개발자가 알고 있는 파일 확장자보다 정말 많은 파일 확장자들이 있다.
그래서 확장자를 체크할 때는 업로드 할 수 없는 확장자를 체크하는 것보다 업로드가 가능한 파일의 확장자를 체크하는 것이 더 좋다.
위의 코드 또한 notValidTypeList로 (변수명은 white라는 단어를 사용하는 것이 더 좋을듯하다) 이미지 파일의 mime type을 선언해주었다.
여러 확장자의 mime type이 어떤 것인지는 아래 사이트를 참고하였다.
'보안' 카테고리의 다른 글
[보안] 보안취약점 - 파일 업로드&다운로드 취약점 (악성코드 및 바이러스 검사) (2) | 2023.12.20 |
---|
댓글