6. 파일 업로드

O 파일 업로드 기능을 이용하여 시스템 명령어를 실행할 수 있는 서버 사이드 스크립트 및 웹 프로그램 등 악의적인 파일을 업로드 할 수 있는 취약점


O 근거 자료

☞ 주요정보통신기반시설 기술적 취약점 분석 평가 상세 가이드(p.707)


O 판단 기준

양호업로드 되는 파일에 대한 확장자 검증이 이루어지는 경우
취약업로드 되는 파일에 대한 확장자 검증이 이루어지지 않는 경우


O 점검 방법

- 스크립트 파일 (ASP, JSP, PHP, ASPX 등)업로드 시도

: 사용자 게시판에 파일 첨부 기능을 통해 Server Side Script파일 업로드가 가능한지 확인

: 업로드 된 Server Side Script파일이 브라우저 주소 창에서 실행이 가능한지 확인

: 업로드 파일 확장자 우회 기법 사용

: 확장자 대소문자 변경 (ex: jsp → JsP,JSp)

: 확장자 변경 (ex: jsp → jspx, jsv, jsw 등 / asp → cer, asa등 / php → php3, cgi등)

: 종단 문자열 추가 (Linux : .jsp → .jsp.jpg / Windows : .asp → .asp;.jpg) 은 URL 디코딩 후 삽입


O 조치 방법

- 서비스를 위해 허용되는 파일의 확장자 외의 파일은 업로드가 불가능하도록 구현

: avi, exe 등의 동영상, 실행 파일 등 악성코드가 포함될 수 있는 콘텐츠를 업로드 하지 못하도록 필터링 적용

- 파일 업로드 기능이 있는 모든 곳에 서버 사이드 스크립트 파일의 업로드 및 실행 금지

- 업로드 디렉터리를 웹 디렉터리 외부로 설정 

: 웹 디렉터리 내에 있어야 하는 경우 해당 업로드 디렉터리에서 서버 사이드 스크립트 실행 속성 제거

- 사용자로부터 경로 값 입력 받아 처리하는 경우 경로가 변조되지 않게 검증 로직 구현

: "../", "..\"등과 같은 문자열이 포함되어 있을 경우 에러처리

: 지정된 업로드 디렉터리 문자만 포함될 수 있도록 검증 

- 파일 명을 난수화하여 유추 불가능하도록 구현

- 응답 값에 업로드 경로 노출 제한

- 주기적으로 업로드 되어 있는 파일들을 대상으로 바이러스 검사 실시


O 시큐어 코딩(Secure Coding) 예시

# 업로드 디렉터리 실행권한 제거 방법 (IIS) ▶

1. 시작 > 제어판 > 관리도구 > 인터넷 서비스 관리자 > 등록정보 > 홈 디렉터리 > 해당 업로드 폴더 선택

2. 실행 권한을 "없음"으로 설정


# 업로드 디렉터리 실행권한 제거 방법 (Apache) ▶

- httpd.conf 내용 수정

<Directory "/usr/local/apache">
 AllowOverride FileInfo


# 업로드 디렉터리에 '.htaccess' 파일 생성 후 서버 스크립트 실행 제한 ▶
<FileMatch "(\.(asp|aspx|cer|jsp|jspx|php|htm|html))$"> Order allow, deny
    Deny from all
</FileMatch>


# JAVA ▶
.....
String fileName = file.getOriginalFilename().toLowerCase();
String fileExt = fileName.substring(fileName.lastIndexOf('.') + 1);

// 화이트리스트 방식으로 업로드 파일의 확장자를 체크한다
if( !fileExt.equals("jpg") && !fileExt.equals("png") ) {
    out.println("");
    return;
}

// 업로드 디렉터리 위치는 웹 디렉터리의 밖에 위치 시킨다
String uploadPath = "/upload/img/";

// 타임데이터 값을 파일 명으로 사용한다
String timeDate = new String(date.format(today).toString();

// 확장자 검증이 완료된 fileExt 확장자 변수 바인딩
String uploadFilePath = uploadPath + timeDate + "." + fileExt;

/* 파일 업로드 로직 수행 */
.....


# ASP ▶
.....
fileExt = Mid(fileName, InstrRev(fileName, ".")+1)

// 화이트리스트 방식으로 업로드 파일의 확장자를 체크한다
IF fileExt <> "jpg" and fileExt <> "png" and fileExt <> "gif" Then
    Response.Write("")
    Response.End
End IF

// 업로드 디렉터리 위치는 웹 디렉터리의 밖에 위치 시킨다
uploadPath = "E:\upload\pds\";

// 타임데이터 값을 파일 명으로 사용한다
timeDate = DateDiff("s", CDate("1970-01-01 00:00:00"), now()) - (9*60*60)

// 확장자 검증이 완료된 fileExt 확장자 변수 바인딩
uploadFilePath = uploadPath & timeDate & "." & fileExt;

/* 파일 업로드 로직 수행 */
.....


# PHP ▶
.....
$fileExt = strtolower(substr($fileName, strrpos($fileName, ".")+1));

// 화이트리스트 방식으로 업로드 파일의 확장자를 체크한다
if ($fileExt != "jpg" && $fileExt != "png" && $fileExt != "gif") {
    echo "";
    exit;
}

// 업로드 디렉터리 위치는 다큐먼트 루트(웹 디렉터리)의 밖에 위치 시킨다
$uploadPath = "/uploads/img/";

// 타임데이터 값을 파일 명으로 사용한다
$timeDate = time();

// 확장자 검증이 완료된 fileExt 확장자 변수 바인딩
$uploadFilePath = $uploadPath . $timeDate . "." . $fileExt;

/* 파일 업로드 로직 */
.....
카카오톡 채널 채팅하기 버튼