본문으로 바로가기

File Upload (DVWA 사용)

category 웹 공격 기법들/File Upload 2021. 3. 2. 19:06

파일 업로드 취약점

- 파일 업로드 기능이 존재하는 웹 어플리케이션에서 확장자 필터링이 제대로 이루어지지 않았을 경우 공격자가 악성 스크립트 파일(웹쉘)을 업로드하여 해당 웹쉘을 통해 원격에서 시스템을 제어할 수 있는 취약점을 말한다.

 

-공격자는 취약점을 이용하여 시스템 명령 수행 등 시스템을 제어할 수 있으며 웹 페이지 변조 등의 공격도 수행할 수 있다.

 

※ 웹쉘

- 악의적인 목적으로 웹서버 내 임의의 명령을 실행할 수 있는 서버 스크립트 파일을 말하며 다양한 언어(ASP, PHP, JSP 등)로 만들어진다.



 

 

실습

다음같이 파일을 올릴 수있는곳에 웹쉘을 업로드 한다.

 

[cmd.php]

<pre>
<?php system($_GET['cmd']) ?>
</pre>

 

 

따라서 업로드가 잘 이뤄지면 다음과 같은 경로에 업로드가 이뤄지게 되며 

 

다음처럼 웹쉘경로에 파라미터를 넣어주어 원하는 명령을 수행 시켜줄 수 있다.

 

 

하지만 이는 아무런 보안작업이 이뤄지지 않은 기능만 구현되있어 가능한 상황이다. 다음은 기능만 구현되어있는 코드이다.

<?php
    if (isset($_POST['Upload'])) {

            $target_path = DVWA_WEB_PAGE_TO_ROOT."hackable/uploads/";
            $target_path = $target_path . basename( $_FILES['uploaded']['name']);

            if(!move_uploaded_file($_FILES['uploaded']['tmp_name'], $target_path)) {
                
                echo '<pre>';
                echo 'Your image was not uploaded.';
                echo '</pre>';
                
              } else {
            
                echo '<pre>';
                echo $target_path . ' succesfully uploaded!';
                echo '</pre>';
                
            }

        }
?>

 

 

따라서 대부분 파일의 타입과 용량을 검사해서 이미지만 업로드 할 수있게 코딩을 해둔다

 if (($uploaded_type == "image/jpeg") && ($uploaded_size < 100000))

 

하지만 이도 우회하는 방법이 있다.

먼저 파일의 이름을 

cmd.php -> cmd.php.jpg 로 변경한다음

 

피들러,burp suite등 패킷을 조작할수있는 툴을 사용해서 파일의 타입을 확인해준뒤 이름을 cmd.php로 다시 바꿔준다.

그렇게 되면 결과적으로 실행되는 php 파일이 업로드 된다.

 

 

 

대처방법

다음과 같이 코드를 수정해서 파일이 대소문자 구분없이 파일의 확장자가 jpg, jpeg, png인 경우에만 파일 업로드를 허용한다.

  if (($uploaded_ext == "jpg" || $uploaded_ext == "JPG" || $uploaded_ext == "jpeg" || $uploaded_ext == "JPEG") && ($uploaded_size < 100000))

 

전체코드

더보기
<?php
if (isset($_POST['Upload'])) {

            $target_path = DVWA_WEB_PAGE_TO_ROOT."hackable/uploads/";
            $target_path = $target_path . basename($_FILES['uploaded']['name']);
            $uploaded_name = $_FILES['uploaded']['name'];
            $uploaded_ext = substr($uploaded_name, strrpos($uploaded_name, '.') + 1);
            $uploaded_size = $_FILES['uploaded']['size'];

            if (($uploaded_ext == "jpg" || $uploaded_ext == "JPG" || $uploaded_ext == "jpeg" || $uploaded_ext == "JPEG") && ($uploaded_size < 100000)){


                if(!move_uploaded_file($_FILES['uploaded']['tmp_name'], $target_path)) {
                    
                    echo '<pre>';
                    echo 'Your image was not uploaded.';
                    echo '</pre>';
                
                  } else {
                
                    echo '<pre>';
                    echo $target_path . ' succesfully uploaded!';
                    echo '</pre>';
                    
                    }
            }
            
            else{
                
                echo '<pre>';
                echo 'Your image was not uploaded.';
                echo '</pre>';

            }
        }

?>

 

 

 

또한 함수를 통해 웹쉘 업로드 방지를 할 수 있는데

 

if( $uploaded_type == 'image/jpeg' ) {
	$img = imagecreatefromjpeg( $uploaded_tmp );
	imagejpeg( $img, $temp_file, 100);
}
else {
	$img = imagecreatefrompng( $uploaded_tmp );
	imagepng( $img, $temp_file, 9);
} 

업로드한 원본 이미지로부터 MIME 형식에 따라 PHP의 imagecreatefromjpeg() 함수나 imagecreatefrompng() 함수를 이용하여 새로운 이미지를 만들고 있다.

 

이 두 함수는 이미지만을 처리하기 때문에 이미지 데이타가 아닌 부분은 모두 버린다.

 

이 함수를 사용하려면 gd 라이브러리를 install 해야한다.
# apt-get install php5-gd

 

 

출처

https://beomsu33.tistory.com/180

webhack.dynu.net/?idx=20161221.001&print=friendly