📨File Inclusion Vulnerability (feat. Image Web Shell?)

DATE : 2024/2/18

File Inclusion Vulnerability

앞서 정리했던 File Upload Vulnerability (with 대응 방안)에서 이미지 파일 확장자의

web Shell은 절대 불가능하다 언급한 바 있다.

그럼에도 불구하고, "아닌데요!! 진짜 이미지 파일로 Web Shell 실행하는 거 봤다니까요?!" 라고

말하고 싶은 자를 위해 설명 들어가시겠다!

jpg, png와 같이 이미지 파일 확장자인 파일이 사실

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

위와 같은 PHP code를 품고 있다고 가정해보자.

이 파일을 업로드했다고 한다면, 우리는 과연 이 파일을 실행할 수 있을까??

~~/fils/shell.jpg

파일 경로를 정확히 알고 있다고 한들, URL 바에 jpg 파일 요청을 보내더라도 PHP code는 실행되지 않는다.

이전 글에서도 말했지만, Web Shell을 실행하려면 서버 측에서 실행 가능한 언어로 파일을 작성해야 한다.

jpg 파일이 아무리 PHP code를 품고 있다고 하더라도 확장자가 PHP가 아닌 이상,

서버는 이 파일을 실행해야 하는 파일로 인식하지 않는다.

그렇다면 jpg, png와 같은 파일로 Web Shell을 구현한 사례는 도대체 뭘까..?!

이런 경우는 단순히 파일을 업로드하는 과정만 수행되지는 않았을 것이다.

위와 동일한 과정으로 서버에 PHP code를 올리는 과정을 동일하지만

문제인 "파일을 실행하는 단계"를 위해서는 추가적인 절차가 요구된다.

그것이 바로 File Inclusion이다. 굳이 표현하자면 파일 삽입(?) 취약점 정도로 말할 수 있을 듯 싶다.

File Inclusion이 무엇인지 알아보기 위해 Inclusion 개념에 대해 먼저 살펴보도록 하자.

<?php
    include("db_connection.php");
    
    $sql = "select * from board";
    $res = mysqli_query($connection, $sql);
    
    ...
?>

어떤 커뮤니티 사이트가 있다고 할 때, 게시물을 가져오는 SQL이 적힌 파일이 있다고 한다.

개발하는 사람 관점에서 편의성을 고려해보면 게시물을 가져오는 파일 뿐만 아니라

로그인, 회원 가입, 개인 정보 페이지 등 SQL을 수행해야 하는 수많은 페이지가 있을 것이다.

이때 우리는 두 가지 선택을 할 수 있는데

첫 번째는 모든 파일에 일일이 DB와 연결하는 코드를 작성하는 것이고

두 번째는 하나의 파일에 동일한 코드를 작성해둔 다음, 이 파일을 필요할 때 가져다가 쓰는 것이다.

이때 우리가 알아야 하는 건, "파일을 가져다 쓴다는 게 어떤 식으로 동작하느냐" 이다.

PHP를 예시로 들면 include, require, require_once와 같이 파일을 가져올 때사용하는 기능

아래와 같이 db_connection.php 코드가 있다고 가정할 때

<?php
    $connection = mysqli_connect("localhost","my_user","my_password","my_db");
    
    if($connection->connect_errno) {
        echo "Fail to connect to DB";
        exit();
    }
?>

이 파일을 include 하는 파일 측에서 코드를 그대로 긁어다가 include한 파일 안에 붙여 넣고

<?php
    include("db_connection.php");
    
    $sql = "select * from board";
    $res = mysqli_query($connection, $sql);
    
    ...
?>
<?php
    $connection = mysqli_connect("localhost","my_user","my_password","my_db");
    
    if($connection->connect_errno) {
        echo "Fail to connect to DB";
        exit();
    }
    
    $sql = "select * from board";
    $res = mysqli_query($connection, $sql);
    
    ...
?>

코드를 실행하는 방식으로 동작한다.

이렇게 되면 DB와 연결을 맺어야 하는 파일마다 동일한 코드를 작성할 필요 없이

중복되는 코드를 작성해두고 가져다가 사용하는 방식으로 효율성을 높일 수 있다.


자! 이제 파일을 가져다 사용한다는 개념을 알아봤으니

File Inclusion이 어떻게 발생하는 공격인지 이해할 수 있을 것이다!

예시에서는 PHP code로 설명했지만 include 되는 파일은 txt일 수도, png일 수도, jpg일 수도 있다.

그렇다는 건, 파일을 업로드하기 위해 jpg와 같은 이미지 파일 확장자로 서버를 속인 다음

다른 파일을 불러다가 사용하는 파일에 업로드한 jpg 파일을 넣어주게 되면 ..!

비록 확장자는 jpg일지라도 안에 들어있는 코드를 실행할 수 있게 되는 것이다.

왜!? 파일을 가져다 쓰는 입장에서 파일 내용을 그대로 긁어다가 붙여 넣고 실행하기 때문!

그 밖에도 텍스트 파일인 경우에는 파일 내용을 그대로 가져와 화면에 출력하도록 할 수도 있다.

말 그대로 서버에 이미 존재하는 파일을 노출 시킬 수 있는 공격이란 말씀..!

따라서 우리는 서버 측에서 실행할 수 없는 확장자로 파일을 업로드 하더라도

해당 파일을 가져다가 쓰는 파일이 업로드한 파일 내용을 그대로 가져다가 실행시켜 줄 것이기 때문에

확장자와 상관없이 Web Shell을 실행할 수 있게 되는 것이다.

다만, 여기서 조건이 있다면 서버에 업로드한 파일을 가져다가 사용하는 파일이 있어야 한다는 점이다.

"서버에 업로드한 파일"이라 함은 같은 서버 내에 존재하는 파일을 가져다 쓴다는 의미

이를 Local File Inclusion (LFI)이라 말한다.

즉 jpg와 같이 이미지 파일의 확장자로 Web Shell을 실행한다는 건

이미지 파일을 업로드한 후, 요청해서 바로 명령을 내릴 수 있는 형태가 아닌

다른 파일에서 불러 들임으로써 실행하는 File Inclusion 취약점인 것이다.

File Inclusion과 File Upload 취약점은 서로 다른 취약점이며

엄밀히 말하면 File Inclusion 공격을 하는 과정에서 File Upload를 수행한다고 말할 수 있다.

File Inclusion 취약점은 말 그대로 우리가 원하는 파일 내용을

파일을 불러다가 사용하는 파일 안으로 삽입할 수 있는 취약점이기 때문에

소스 코드를 얻을 수는 없지만 (서버가 실행하기 때문에)

코드가 실행된 결과를 얻을 수 있는 강력한..! 취약점이라 할 수 있다. 👍

Last updated