직접 업로드에서는 파일이 앱을 지나가지 않습니다. 그래서 검증할 자리가 사라집니다. 검증을 어디에 둘지가 이 개념의 문제입니다.
확장자는 내용이 아니다
파일 이름의 확장자는 클라이언트가 정한 문자열입니다. 보고서.pdf 라는 이름의 실행 파일을
막지 못합니다. 실제 종류는 파일 시그니처로 봅니다. 대부분의 형식은 앞부분 몇 바이트에
고유한 값이 있습니다.
| 검사 대상 | 신뢰도 |
|---|---|
| 확장자 | 없다. 이름만 바꾸면 통과한다 |
| 클라이언트가 보낸 콘텐츠 타입 | 없다. 요청을 직접 만들면 통과한다 |
| 파일 시그니처 | 있다. 실제 바이트를 본다 |
시그니처도 완벽하지 않습니다. 앞부분만 정상으로 위장할 수 있습니다. 그래서 이미지처럼 다시 인코딩할 수 있는 형식은 변환해서 다시 저장하는 편이 안전합니다. 변환에 성공하면 그것이 곧 검증입니다.
검사는 비동기로, 그 사이는 격리로
직접 업로드는 앱이 사후에만 볼 수 있으므로 검사가 비동기가 됩니다. 그러면 검사 전 구간이 생깁니다.
격리 영역과 공개 영역을 나누는 것이 핵심입니다. 같은 자리에 두고 상태 컬럼으로만 구분하면, 어딘가에서 상태 확인을 빠뜨렸을 때 검사 전 파일이 노출됩니다. 경계는 코드가 아니라 저장 위치로 만드는 편이 안전합니다.
크기 제한은 서명에 박는다
앞 개념에서 본 것과 같습니다. 화면에서만 막으면 요청을 직접 만들어 우회됩니다. 서명 조건에 넣으면 스토리지가 거절합니다.
여기에 하나 더 필요합니다. 서명은 한 번의 요청을 제한하므로, 멀티파트로 파트를 계속 올리는 것은 개별 서명으로는 못 막습니다. 전체 크기 상한은 업로드 세션 단위로 따로 세야 합니다.
무엇을 검사하지 않을지도 정한다
모든 파일을 깊게 검사하면 비용과 지연이 커집니다. 요구사항에 실시간 미리보기가 없으므로, 검사를 몇 초에서 몇 분 걸리게 두고 그동안 목록에 안 보이게 하는 선택이 가능합니다. 무엇을 포기할 수 있는지가 요구사항에서 나옵니다.