2021/01/12 - [프로젝트/DVWA 실습] - DVWA 실습 #6 - File Upload
문제 해결 방법
Medium 단계에서는 이제 $_FILES 변수를 활용하고 있다. 이 변수는 업로드된 파일의 이름(name), 타입(type), 크기(size), 임시 이름(tmp_name), 에러 코드(error)에 대한 정보를 담고 있는데 이 단계의 코드에서는 $_FILES['uploaded']['type'] 변수로 업로드된 파일의 mime-type을 검사하고 있다. 이 타입이 image/jpeg, image/png일 경우에만 파일을 업로드하고 있기 때문에 이전처럼 스크립트 파일을 업로드하려고 하면 오직 이미지 파일만 받는다는 에러 메시지가 출력된다.
그렇다면 이렇게 $_FILES 변수의 type만 검사해도 안전할까? 그렇지 않다. PHP 매뉴얼에 따르면 이 mime-type은 브라우저에서 제공되며 php 엔진에서는 이를 검증하지 않기 때문에 프록시 툴로 위조된 경우 이를 구분할 수 없다. Burp Suite로 파일 업로드 요청을 가로채보면 다음처럼 나타난다.
...
Accept-Encoding: gzip, deflate
Accept-Language: ko,en;q=0.9,en-US;q=0.8
Cookie: security=medium; PHPSESSID=2c6fb365f427b95e430888a8df31f7ac
Connection: close
------WebKitFormBoundaryWjGX10jHS8WBTnOu
Content-Disposition: form-data; name="MAX_FILE_SIZE"
100000
------WebKitFormBoundaryWjGX10jHS8WBTnOu
Content-Disposition: form-data; name="uploaded"; filename="malicious.php"
Content-Type: application/octet-stream
<html>
<body>
...
이 중 파일 업로드 폼을 처리하는 part('uploaded')를 살펴보면 filename이 'malicious.php'이며 전송되는 컨텐츠 타입은 'application/octet-stream'인 것을 볼 수 있다. 이 부분이 mime-type으로 MDN 문서를 참조하면 따로 정의되지 않은 모든 파일의 타입인 것을 알 수 있다. 이를 'image/jpeg'나 'image/png'로 바꿔주면 서버에서 이미지 파일로 인식하여 업로드되는 것을 볼 수 있다.
이를 방지하기 위해서는 확장자나 mime-type 같은 사용자 측에서 수정될 수 있는 값을 신뢰하지 않아야 한다. 그리고 업로드된 파일에 대해 다른 라이브러리나 함수를 이용하여 해당 파일 타입에 맞는 작업(이미지 리사이징, 오디오 추출 등)을 수행하여 정상적인 파일인지 검증하는 로직이 필요할 것이다. 이를 적용하기 어려운 경우 파일을 암호화하거나 최소한 확장자, 이름을 추측할 수 없는 값으로 변경한 후 실행 권한을 제거해야 할 것이다.
'프로젝트 > DVWA 실습' 카테고리의 다른 글
DVWA 실습 #7 - Insecure CAPTCHA (0) | 2021.01.14 |
---|---|
DVWA 실습 #6-3 - File Upload(high) (1) | 2021.01.14 |
DVWA 실습 #6-1 - File Upload(low) (0) | 2021.01.14 |
DVWA 실습 #6 - File Upload (0) | 2021.01.12 |
DVWA 실습 #5-3 - File Inclusion(high) (0) | 2021.01.12 |