본문
원문 : http://hungred.com/2009/08/17/useful-information/secure-file-upload-check-list-php/
1. Content Type 검증
$_FILES['uploadfile']['type']로 MIME type 검증
* PHP가 받아오는 MIME type은 웹브라우저가 넘겨주는 값을 그대로 쓴다. 대다수 웹브라우저들은 확장자로 MIME type을 결정하기 때문에 신뢰도가 떨어지는 건 어쩔 수 없다.
2. Image 파일 검증
$imageInfo = getimagesize($_FILES['uploadfile']['tmp_name']);
getimagesize로 MIME type 검증하기
* 이미지 업로드시 쓰는 방법이다. 이미지라면 제대로 값을 return 해주지만 그렇지 않으면 return을 못한다.
3. 확장자 검증
$filename = $strtolower($_FILES['uploadfile']['name']);
$fileInfo = pathinfo($filename);
echo $fileInfo['extension'];
* '.'단위로 explode해서 end로 확장자를 구하는 게 원문이지만, pathinfo 함수로도 확장자를 구할 수 있다. 여튼 이것도 확장자로만 검사하기 때문에 당연히 정확한 건 아니다. 가장 좋은 거야 당연히 파일 내용 자체를 검사하는 거지만, 성능 손해가 만만치 않기에 -0-...
4. 업로드 디렉토리
검증이라고는 생각이 안 되지만, 어느 정도의 방어 수단인 것 같다.
내 경우에는 이미지만 받는 게 보통이라서 업로드 디렉토리와 다운로드 디렉토리가 같다. (-_-;;)
물론 그렇지 않은 경우에는 업로드 디렉토리는 외부에서 접근 불가능하고 다운로드 프로그램으로만
다운로드 하도록 한다.
또한 업로드 파일이 너무 많아지면 훗날 한 디렉토리에 파일이 많아지므로 년 + 월로 매번 디렉토리를 생성해서
업로드를 한다.
예) 2009년 8월이면 /upload/200908
5. Include Function
원문에 있길래 적어놓기는 하는데... 사용자 입력 값만을 믿고 import하는 건 잘못된 거다.
왜 이런 예가 있는지 이해가 안 된다.
정 사용자 입력 값으로 import를 해야한다면,
switch ($_GET['import']) {
case 'foo':
include $_GET['import'].'.php';
break;
case 'abc':
include $_GET['import'].'.php';
break;
default:
include 'qwe.php';
break;
}
이런 식으로 정확한 값만 통과할 수 있도록 해야 된다고 생각한다.
원문의 예제는 단지 isset만으로 값이 넘어왔나 안 넘어왔나만 확인 하는데... 만약 빈 값으로 넘기면 어쩌려고?
GET, POST, COOKIE는 사용자 입력 값이다. 언제든 위변조가 가능하다. SESSION도 따지고 보면 사용자 입력
값에 의해 가공되므로 SESSION도 100% 믿으면 안 된다.
6. 임의 파일명
난 사용자가 올린 파일명을 그대로 안 쓴다.
한글 파일명은 UTF-8 다시 보내기 문제도 있고, 이래저래 사용자 입력 값보다 더 무서운 게 사용자가 올리는
파일이기 때문이다. 내 경우에는
랜덤값 여섯자리 + 타임스탬프
로 파일명을 정한다.
* 되도록이면 어느 정도 구현된 파일 업로드 함수를 쓰는 게 낫다고 생각한다. 물론 경우마다 다르겠지만 PHP 자체만으로 업로드를 하는 경우는 거기서 거기인 경우가 많다. 가장 좋은 건 사용자 입력 값은 최소로 하는 게 좋다는 거다. 일반적인 커뮤니티 게시판에서는 이미지만 업로드 되면 된다. 소수의 사용자를 위한 배려가 큰 악재로 바뀌는 것보다는 낫다고 생각한다.
관련링크
댓글목록
등록된 댓글이 없습니다.