본문 바로가기
프로그램 (PHP,Python)

안전한 PHP 파일 업로드 구현 체크 리스트

by 날으는물고기 2009. 9. 23.

안전한 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 다시 보내기 문제도 있고, 이래저래 사용자 입력 값보다 더 무서운 게 사용자가 올리는

파일이기 때문이다. 내 경우에는

랜덤값 여섯자리 + 타임스탬프

로 파일명을 정한다.


출처 : http://www.cyworld.com/maengis

728x90

댓글