본문 바로가기

웹 해킹

웹 해킹 공부 일기장 11 - 1(파일 업로드)

저번 시간에 파일 업로드 취약점에 대해 알아보았습니다.

파일 업로드 취약점은 공격자가 임의의 파일을 업로드할 수 있는 공격입니다.

보통 웹쉘 파일을 업로드하여 서버에 원하는 명령을 내릴 수 있게합니다.

 

그리고 가장 중요한 것이 서버에서 실행을 할 수 있는 파일이어야 하며 공격자는 파일을 실행하기 위해서 해당 파일의 경로를 알고 있어야합니다.

 

저번 시간 마지막에 .jpg로 끝나는 파일은 절대 실행시킬 수 없다고 말했었습니다.

그렇기 때문에 webshell.php.jpg 파일을 업로드한다면 절대로 실행시킬 수 없습니다.

 

하지만 몇가지 특수한 상황에서 jpg 파일을 업로드 시 실행시킬 수 있는 방법이 있습니다.

아마, 인터넷에서 보신 jpg 파일 업로드로 웹쉘을 실행시키는 방법 중 하나일 것입니다.

 

1. webshell.jpg.php 파일 업로드

일단 당연히 webshell.jpg.php파일은 php파일이기 때문에 업로드만 성공한다면 실행이 가능합니다.

webshell.jpg가 파일이름이 되고 php가 확장자 명이 되는 것입니다.

 

2. null byte injection 

이 방법은 webshell.php%00.jpg의 파일명으로 업로드하는 것인데 이 경우 파일명에 null을 추가하는 것입니다. 검색 시 .jpg로 끝나 정상적인 이미지 파일이라고 판단하여 검증을 통과하며, 파일 저장시 널 이후는 잘려 webshell.php 로 저장되게 됩니다.

널 바이트 추가

 

업로드시 버프로 요청을 잡아 사진과 같이 webshell.php.jpg 에서 php뒤에 00으로 널바이트를 추가하여 전송합니다.

 

webshell.php 파일 업로드

 

사진과 같이 업로드된 파일이 .jpg가 사라지고 webshell.php로 업로드된 것을 확인할 수 있습니다.

 

3. .htaccess 파일 사용

.htaccess 파일 같은 경우 해당 디렉토리에 대해 서버 설정을 정할 수 있습니다. 이 파일을 사용하여 jpg 확장자를 php로 실행하게 만들어서 jpg로 끝나는 파일을 php로 실행시킬 수 있습니다.

 

.htaccess 파일에 AddType application/x-httpd-php .jpg 라고 적은 다음에 해당 파일을 업로드하면 이제 이 파일이 있는 디렉토리는 jpg확장자를 php로 실행시킬 수 있습니다. 그렇기 때문에 이 경우는 꼭 jpg가 아니라도 어떠한 임의의 확장자도 원하는 방식으로 실행시킬 수 있습니다.

.htaccess 파일 업로드

 

사진과 같이 .httaccess 파일을 업로드하면 .test 확장자는 php로 실행시킬 수 있습니다.

 

.test 확장자 웹 쉘 실행 결과

 

그러면 이렇게 꼭 jpg가 아니더라도 어떠한 확장자든 설정한대로 실행시킬 수 있습니다.

 

결론은 위의 특수한 경우가 아니라면 jpg 확장자 파일은 절대 실행시킬 수 없다는 것입니다.

 

그럼 이 파일 업로드 취약점에 대한 대응방안은 무엇일까요??

일단 파일을 실행가능한 서버에 저장하기 때문에 발생합니다. 그렇기 때문에 파일 자체를 데이터베이스에 저장하는 것이 가장 좋습니다.

CLOB / BLOB 타입을 지정하면 파일을 데이터베이스에 저장할 수 있습니다.

 

다른 파일 저장과 똑같이 해당 타입으로 지정해주고 업로드할 파일을 insert 해주면 저장할 수 있습니다.

아래와 같이 작성해주면 파일을 문자열로 읽어 저장할 수 있습니다.

$fileContent = file_get_contents($_FILES["file"]["tmp_name"]);

 

가져올 때도 마찬가지로 select 해주면 저장된 문자열 그대로 가져와 파일을 사용할 수 있습니다.

    public static function getFile($idx) {
        $db_conn = connectDb();
        $query = "select file,filename from boards where idx=$idx";
        $result = mysqli_query($db_conn, $query);
        mysqli_close($db_conn);
        return mysqli_fetch_assoc($result);
    }

 

저장된 모습

 

BLOB 타입에 14.8KB 용량으로 저장된 것을 확인할 수 있습니다.

 require_once('models/board-model.php');
    // 다운로드 파일 경로
    $dir_path = "/var/www/html/";       
    // 파일명
    $fileId = $_GET['file'];

    $file = Board::getFile($fileId);
    $file_name = $file['filename'];
    $fileContent = $file['file'];
     
    //file_exists($file_path)
    if (isset($file_name)) {
        header('Content-Description: File Transfer');
        header("Content-Type:application/octet-stream");
        header("Content-Disposition:attachment;filename={$file_name}");
        header("Content-Transfer-Encoding:binary");
        header("Content-Length:".strlen($fileContent));
        header("Cache-Control:cache,must-revalidate");
        header("Pragma: no-cache");
        header("Expires:0");
        ob_clean(); //출력 버퍼 제거
        flush(); //출력 버퍼를 비우고 즉시 출력. 이를 클라이언트에게 전송. 전송지연최소화.

        echo $fileContent;

 

마지막으로 위와 같이 코드를 작성하면 다운로드도 정상적으로 가능합니다.

 

이렇게 파일을 실행할 수 없는 다른 곳에 저장하는 것이 좋습니다. 

이와 비슷하게 데이터베이스에 파일을 저장하는 방법말고 NAS를 사용하여 해당 언어로 된 파일을 처리할 수 없는 서버를 사용하여 파일을 저장하는 방법도 있습니다.

 

마지막으로 파일 업로드 취약점과 다른 파일을 사용한 취약점이 있는데 File Include 기능을 이용한 취약점입니다.

 

이것은 웹 개발시 중복되는 코드들을 include 기능을 사용하여 원하는 곳에 코드를 복사??하는 기능입니다.

여러번 중복되는 코드를 여러번 작성할 필요없이 한 파일에 코드를 저장하면 똑같은 코드를 어느 곳이든 include하면 해당 코드를 사용할 수 있습니다.

 

이때 사용자에게 입력을 받아 파일을 include할 경우 우리가 원하는 파일(웹쉘 파일)을 포함시켜 웹 쉘을 실행시키는 것입니다.

# 파일 업로드 기능이 없을 경우 log를 사용하여 원하는 코드 실행 가능

이런 공격이 있다는 것만 알고 다음에는 파일 다운로드 취약점을 알아보겠습니다.