운영 가이드에 적힌 디렉터리 구조를 보다가 업로드 폴더가 웹으로 서비스되는 경로 아래에 있는 것이 눈에 띄었다. 그 위치면 주소만 알면 파일을 그대로 받을 수 있다.
Table of contents
Open Table of contents
디렉터리 구조에서 본 것
다만 디렉터리가 그 아래 있다는 것만으로 열려 있다고 단정할 수는 없었다. 웹서버 설정에서 그 경로만 막아 두는 것이 가능하기 때문이다.
그래서 설정 파일을 열어서 그 경로에 대한 규칙이 있는지를 확인했다. 위치가 아니라 설정이 실제로 무엇이 열려 있는지를 정한다.
위치와 웹서버 설정
확인해 보니 별도 규칙이 없어서 그 아래 있는 것이 전부 그대로 내려가고 있었다. 업로드된 파일 중에는 아무나 받으면 안 되는 것도 섞여 있었다.
이 상태에서는 파일 이름을 알아내는 것만으로 접근이 된다. 이름이 규칙적이면 추측도 가능하므로 이름을 어렵게 짓는 것으로는 부족했다.
공개 자원과 보호 자원을 가른다
그래서 파일을 두 종류로 갈랐는데 누구나 봐도 되는 것과 권한이 있어야 하는 것이었다. 앞의 것은 그대로 두고 뒤의 것은 웹으로 안 열리는 자리로 내렸다.
옮긴 파일은 요청을 받아서 권한을 확인한 뒤에 내려 주게 했다. 이렇게 하면 주소를 알아도 권한이 없으면 못 받으므로 경로를 추측하는 것 자체가 의미가 없어진다.
저장 파일명의 무작위화
저장할 때 파일 이름을 원본 그대로 쓰고 있던 것도 함께 손봤다. 원본 이름에는 사용자가 넣은 문자가 그대로 들어가서 인코딩 문제도 생기고 이름 자체가 정보를 흘리기도 한다.
그래서 저장 이름은 무작위 값으로 만들고 원본 이름은 DB에 따로 뒀다. 내려 줄 때 그 이름을 헤더에 실어 주면 받는 쪽에서는 원래 이름으로 저장된다.
한 서버의 여러 사이트
작업하면서 한 서버에 사이트가 셋 올라가 있는 것도 확인했다. 지금은 문제가 없지만 하나가 커지면 떼어 내야 할 수 있다.
그래서 무엇을 먼저 떼어 낼지를 미리 정해 두었는데 접근 통제가 다른 것부터 떼는 것이 기준이었다. 트래픽이 아니라 누가 접근할 수 있어야 하는지가 다른 것이 먼저 갈라져야 했다.
정리
- 업로드 경로가 열려 있는지는 위치가 아니라 웹서버 설정으로 확인한다
- 파일을 공개 자원과 보호 자원으로 가른다
- 보호 자원은 웹 루트 밖에 두고 요청을 받아 내려 준다
- 주소를 알아도 권한이 없으면 못 받게 한다
- 그러면 경로 추측이 무의미해진다
- 저장 파일명을 원본이 아닌 무작위 값으로 한다
- 원본 이름은 DB에 두고 내려줄 때 헤더로 준다
- 한 서버에 여러 사이트를 둘 때 무엇을 먼저 뗄지 정해 둔다