업로드 파일의 세 가지 얼굴
제공된 PixelPet 계정으로 아바타 업로드 기능을 블랙박스 점검하세요. 브라우저 개발자 도구나 로컬 프록시에서 자신의 업로드 요청을 관찰·변경할 수 있습니다. 실행 코드가 아닌 의뢰용 무해 표식만 담긴 비이미지 파일이 이미지로 승인되는지 확인하고 저장 승인 영수증을 확보하세요.
의뢰 배경
픽셀펫은 반려동물 프로필 서비스의 아바타 업로더를 새로 만들었습니다. 콘텐츠 모니터링에서 이미지로 승인된 파일 하나가 실제로는 이미지 디코더가 읽을 수 없는 형식이라는 경보가 발생했습니다. 아직 공개 프로필에서 실행되거나 배포된 정황은 없지만, 허용되지 않은 파일이 저장될 수 있다면 서비스 변조와 악성 콘텐츠 배포로 이어질 수 있어 정식 출시 전 검증이 필요합니다.
이번 목표
허용된 이미지가 아닌 무해한 파일을 아바타로 승인받을 수 있음을 재현하고 저장 영수증을 확보하세요.
- 파일명, 요청 MIME, 서버 탐지 MIME, 실제 내용이 독립적인 신호임을 설명한다.
- 클라이언트가 보낸 Content-Type을 단독 신뢰하면 안 되는 이유를 확인한다.
- 검증 후 이름 재생성, 크기 제한, 비공개 저장, 실행 금지를 방어 순서로 연결한다.
학습 노트 · 업로드 보안은 확장자 하나를 검사하는 문제가 아니라 입력 검증과 저장·서비스 방식을 함께 설계하는 문제입니다.
multipart 요청의 Content-Type은 브라우저나 프록시가 작성하므로 사용자가 바꿀 수 있습니다. image/png라고 선언해도 실제 바이트가 PNG라는 보장은 없습니다.
서버는 필요한 파일 형식을 allowlist로 제한하고, 확장자와 magic bytes를 함께 검사하며, 원래 파일명을 버리고 무작위 저장명을 사용해야 합니다. 파일 크기와 이미지 디코딩 성공 여부도 검증해야 합니다.
가장 중요한 마지막 경계는 업로드 디렉터리를 public web root 밖에 두고 실행 권한을 주지 않는 것입니다. 파일 검증이 실패하더라도 저장과 제공 단계에서 실행을 막는 다층 방어가 필요합니다.
| 신호 | 누가 정하는가 | 단독 신뢰 가능 |
|---|---|---|
| 원본 filename | 클라이언트 | 아니오 |
| multipart Content-Type | 클라이언트 | 아니오 |
| 서버가 탐지한 magic bytes | 서버 | 다른 검사와 함께 사용 |
| 저장 위치와 실행 설정 | 서버 운영 정책 | 핵심 방어 경계 |
POST /pixelpet/avatar HTTP/1.1
Host: profile.pixelpet.training
Content-Type: multipart/form-data; boundary=BOUNDARY
--BOUNDARY
Content-Disposition: form-data; name="avatar"; filename="pet.png"
Content-Type: image/png
<file bytes>
--BOUNDARY--더 깊이 읽기
실습 전후에 공식 문서와 보안 아카데미 자료로 개념을 교차 확인하세요.
막혔을 때만 열기
다음 단서가 필요할 때만 한 단계씩 확인하세요.
힌트 1 · 두 종류의 타입
업로드 결과에서 filename 확장자와 multipart Content-Type이 각각 어떻게 기록되는지 비교하세요.
힌트 2 · 요청을 수정하기
브라우저에서 전송한 multipart 요청을 편집해 파일 part의 Content-Type만 바꿀 수 있습니다.
힌트 3 · 서버 판단 비교
의뢰용 무해 표식 파일의 이름과 본문은 그대로 두고, 프록시에서 업로드 파트가 선언하는 형식만 허용된 이미지 형식으로 바꿔 승인 결과를 비교하세요.
선행 의뢰가 잠겨 있습니다
이전 단계를 완료하면 자동으로 의뢰 메일과 실습 환경이 열립니다.