파일 업로드에서 진짜로 막아야 하는 것 일곱 가지
"이미지만 올려 주세요"라고 적어 두는 걸로는 아무것도 막지 못합니다. 실제로 들어오는 공격은 이런 식입니다.
- 이름만 사진: shell.php를 shell.jpg로 바꿔 올리고 나중에 주소로 불러 실행
- 속에만 코드: 진짜 JPG 뒤에 코드를 붙임. 겉보기엔 정상 사진
- 이름에 장난: ../../index.php 같은 이름으로 다른 폴더 파일을 덮어쓰기
- 용량 폭탄과 픽셀 폭탄: 디스크를 채우거나, 가로세로 3만짜리 작은 파일로 메모리를 터뜨림
그래서 이렇게 겹쳐 막았습니다.
1. 진짜 업로드된 파일이 맞는지 확인
2. 용량 상한
3. 가로세로가 읽히는 진짜 이미지인지 확인
4. JPG·PNG·WEBP만 허용 (SVG는 안에 코드가 들어가므로 제외)
5. 파일 속 내용과 확장자가 맞는지 재확인
6. 파일 이름을 서버가 새로 짓기. 올린 사람이 준 이름은 통째로 버림
7. 이미지를 다시 그려서 저장. 붙어 있던 코드가 이 과정에서 사라짐
여기에 더해 업로드 폴더 자체에서 코드 실행을 꺼 둡니다. 앞의 일곱이 다 뚫려도 그 파일은 실행되지 않고 그냥 내려받아집니다.
실제로 진짜 JPEG 뒤에 코드를 붙인 파일을 만들어 올려 봤습니다. 7번에서 코드가 사라지는 걸 확인했습니다. 만들었으면 직접 공격해 보는 게 확실합니다.
- 이름만 사진: shell.php를 shell.jpg로 바꿔 올리고 나중에 주소로 불러 실행
- 속에만 코드: 진짜 JPG 뒤에 코드를 붙임. 겉보기엔 정상 사진
- 이름에 장난: ../../index.php 같은 이름으로 다른 폴더 파일을 덮어쓰기
- 용량 폭탄과 픽셀 폭탄: 디스크를 채우거나, 가로세로 3만짜리 작은 파일로 메모리를 터뜨림
그래서 이렇게 겹쳐 막았습니다.
1. 진짜 업로드된 파일이 맞는지 확인
2. 용량 상한
3. 가로세로가 읽히는 진짜 이미지인지 확인
4. JPG·PNG·WEBP만 허용 (SVG는 안에 코드가 들어가므로 제외)
5. 파일 속 내용과 확장자가 맞는지 재확인
6. 파일 이름을 서버가 새로 짓기. 올린 사람이 준 이름은 통째로 버림
7. 이미지를 다시 그려서 저장. 붙어 있던 코드가 이 과정에서 사라짐
여기에 더해 업로드 폴더 자체에서 코드 실행을 꺼 둡니다. 앞의 일곱이 다 뚫려도 그 파일은 실행되지 않고 그냥 내려받아집니다.
실제로 진짜 JPEG 뒤에 코드를 붙인 파일을 만들어 올려 봤습니다. 7번에서 코드가 사라지는 걸 확인했습니다. 만들었으면 직접 공격해 보는 게 확실합니다.