Information Security/Hacking

파일 업로드 취약점 (File Upload Vulnerability)

Project_S 2021. 2. 15. 16:54
반응형

파일 업로드 동작 방식

* 파일 업로드 취약점 : 파일 업로드 기능이 존재하는 웹 상, 업로드 파일에 대한 제어(필터링, 개수 및 크기 제한 등) 미흡으로 외부에서 파일이 업로드 될 수 있는 취약점

- 악성 웹쉘(다양한 언어로 만들며, 임의의 명령을 실행할 수 있는 Server Side Script 파일) 업로드

- 다량의 대용량 파일을 연속 전송하여 시스템 부하 및 장애 유발 등

 

 

 

* 공격 예시 및 대응책

1) 파일 타입 필터링 미흡으로 인한 파일 업로드

//웹쉘 파일 코드 예시
~~~
Content-Disposition: form-data; name="upfile[]"; filename="webshell.php"
Content-Type: application/octet-stream

<?php
eval(base64-decode('DQplcnJvcl9yZXBvcnRpb... 이하 생략)

- PHP eval("문자열") 함수 (문자열을 php코드로 해석, 실행시키는 함수) 사용으로, 인코딩된 php코드를 base64로 디코딩하여 실행하는 웹쉘 구문 (실제로 굉장히 잦은 공격구문)

Base64 : 일반 텍스트 형식 외, Binary Data(파일) 첨부를 위한 변환 방식으로, 손실 없이 모든 Binary 데이터와  ASCII 데이터(문자)간 인/디코딩이 가능한 방식
- 변환 방식 : 64개의 ASCII 문자(A-Z, a-z, 0-9, +,/)와 패딩문자(=)로 표현
- 6bit 문자 4개씩 3Byte 단위 표현, 부족한 Bit는 0으로 채우고, 부족한 문자는 패딩문자(=)로 채움.

- 파일 업로드 시, Content-Type에 대한 정보 확인이 가능하며, 해당 파일 타입(MIME Type)을 허용 가능한(이미지 파일 등) 수준으로 관리 되도록 검증 필요

MIME (Multipurpose Internet Mail Extensions) : 이메일과 파일을 텍스트 형식으로 변환하기 위한 표준
- 현재 웹에서 파일 형태를 전달하기 위한 목적으로 사용하며, 파일 전송 시, Content-Type 헤더 필드에 MIME 타입 명시
- text/html, image/gif 와 같이, 타입/서브타입 형식으로 구성됨

// 업로드 파일 타입(MIME 타입) 검증 코드

// MIME 타입을 화이트 리스트 방식으로 체크하는 함수 생성
function check_type($file_type){
	$white_list=array('image/gif', 'image/jpeg', 'image/png');
    // 대소문자로 인한 파일 타입 우회 방지를 위한 소문자 변환
    $lower_file_type = strtolower($file_type);
    for($i=0; $<count($white_list); $i++);
    	$isSafe=eregi($white_list[$i],$lower_file_type);
        if($isSafe){
        				break;
        }
 }
 return $isSafe; // 화이트 리스트 파일 타입일 시, true 반환
}
?>
~~~ // 중간 생략
// HTTP 요청 메세지의 Content-Type 헤더 필드값 (MIME 타입)을 이용, 파일 타입 체크
if(trim($file_name) != ""){
	$isSafe=check_type($upfile_type[$i]);
    if(!$isSafe){ // 허용하지 않는 파일 타입은 차단
    	echo "<script>popup.alert('업로드 불허용 타입.');history.go(-1);</script>";
        exit;
    }
}

 

 

 

2) 파일 확장자 검증 미흡으로 인한 파일 업로드 : 파일 타입은 공격자가 임의 변조 가능, 추가적으로 확장자에 대한 검증 필요

- 파일 타입(MIME 타입)과 확장자 검증을 모두 수행하는 코드

// 업로드 파일 타입(MIME 타입) 검증 코드

// MIME 타입을 화이트 리스트 방식으로 체크하는 함수 생성
function check_type($file_type){
	$white_list=array('image/gif', 'image/jpeg', 'image/png');
    // 대소문자로 인한 파일 타입 우회 방지를 위한 소문자 변환
    $lower_file_type = strtolower($file_type);
    for($i=0; $<count($white_list); $i++);
    	$isTypeSafe=eregi($white_list[$i],$lower_file_type);
        if($isTypeSafe){
        				break;
        }
 }
 return $isTypeSafe; // 화이트 리스트 파일 타입일 시, true 반환
}



// 파일 확장자를 화이트 리스트 방식으로 체크하는 함수
function check_ext($fileEXT){
	$whiteList=array('gif', 'jpg', 'png');
    $lowerFileExt = strolower($fileExt);
    for($i=0; $i<count($whiteList); $i++){
    	$isExtSafe=eregi($whiteList[$i],$lowerFileExt);
        if($isExtSafe){
        				break;
        }
 }
 return $isExtSafe; // 화이트 리스트 파일 타입일 시, true 반환
}


/* 파일 타입과 확장자 모두 체크 */

if(trim($file_name) != ""){
	$isTypeSafe=check_type($upfile_type[$i]);
    $isExtSafe=check_ext($file_ext);
    if(!$isTypeSafe || !$isExtSafe){ // 허용하지 않는 파일 타입 및 확장자 차단
    	echo "<script>popup.alert('업로드 불허용 타입.');history.go(-1);</script>";
        exit;
    }
}

 

 

 

* 취약점 판단 기준 : 업로드가 가능한 입력 Form악성 스크립트 파일의 업로드가 성공할 시, 취약한 것으로 판단

 

 

 

* 대응책

1) 업로드 파일 타입(MIME 타입) 및 확장자 검증화이트리스트 방식 적용, 업로드 차단

 

 

 

2) 파일 업로드 전용 디렉터리 별도 생성, 직접 URL 호출 및 파일 실행웹서버 설정으로 차단

- httpd.conf(아파치 설정 파일)의 Directory 섹션AllowOverride 지시자에 FileInfo 또는 All을 추가 후, 업로드 디렉터리에 엑세스 파일(.htaccess) 생성

// httpd.conf 파일 내 설정으로 업로드 디렉터리에 대한 문서 타입 제어
<Directory "/var/www/html"> // /var/www/html은 업로드 디렉터리 경로에 대한 예시(제어할 디렉터리 경로 삽입)
	AllowOverride All
</Directory>

AllowOverride 지시자 : 엑세스 파일(.htaccess)에 어떤 지시자 설정을 할지 결정하는 지시자
- All : 액세스 파일에 모든 지시자 적용

- FileInfo : AddType과 같은 문서 타입 관련 지시자 설정 허용

액세스 파일(.htaccess) : httpd.conf와 함께, 디렉터리별 설정 파일
- 특정 디렉터리에 생성 시, 해당 디렉터리 및 그 하위 디렉터리까지 설정한 지시자가 적용됨

- 이후, 파일 업로드용 디렉터리(ex-/var/www/html/~~~ 등)에 액세스 파일(.htaccess) 생성 후 FilesMatch 지시자 설정, *.ph, *.inc, *.lib 등 파일에 대한 직접 URL 호출 차단(Deny from all) 설정

- 추가적으로, 액세스 파일(.htaccess)에 AddType 지시자 설정으로 특정 확장자들에 대해 강제로 MIME 타입 재조정 설정

[root@test data]# pwd
/var/www/html/home/download/data
[root@test data]# ls -al .htaccess
-rw-r--r-- 1 root root 216 2021-02-15 12:30 .htaccess
[root@test data]#cat .htaccess
#allowd와 deny사이 공백이 있으면 안됨.
<FilesMatch "\.(ph|inc|lib)">
    order allow,deny
    Deny from all
</FilesMatch>
AddType text/html .html .htm .php .php3 .php4 .phtml .phps .in .cgi .pl .stml .jsp
# AddType text/html로 시작 시, 뒤에 설정된 확장자를 가진 파일들은 강제로 HTML 문서로 처리!


[root@test data]#

 

- 윈도우 IIS 웹서버 업로드 디렉터리 실행 권한 제거

- 이 외, 적합한 계정에만 적절한 권한 부여 (그룹 설정 등) 적용

 

 

 

3) 업로드 파일 크기 검증에 따른 업로드 제한 : 코드 설정, 웹서버 설정 파일 수정 등 이용

- 용량 제한 코드 설정

// 업로드 허용 파일 크기 5MB(5000000 Byte) 이하로 제한
~~~ 생략

if($upfile_size[$i] > 5000000) {
	echo("
    	<script>
        	popup.alert('업로드 파일 크기가 지정 용량(5MB)를 초과.');
            history.go(-1)
        </script>
    ");
    exit;
}
~~~

- httpd.conf 설정 파일 내, 업로드 파일 크기 제한

<Directory/>
	Options FollowSymLinks
    AllowOverride All
#	LimitRequestBody 5000000 <- /(모든 경로)에 대해 파일크기 5MB 제한 (현재 주석 처리)
</Directory>

<Directory "/var/www/html/~~~">
	LimitRequestBody 5000000
</Directory>

LimitRequestBody 지시자 : 클라이언트가 POST, PUT 메소드 이용, HTTP 요청 메세지 Body부에 데이터를 담아서 전달할 수 있는 최대 크기(Byte) 의미
- 0 지정 시, 무한대를 의미
- 설정 크기를 초과 할 시, 413(Request entity too large) 에러메시지 반환

 

 

 

반응형