홈페이지 취약점 분석 이야기 파일 지도 사진 깨알






>> 목록보이기
#조치방안 #방어법 #경로조작 #Path Traversal #파일다운로드 취약점 #경로조작 방어 #파일다운로드 방어 #절대경로 비교

파일다운로드/경로조작 취약점에 대한 방어법

첨부파일 관리는 게시판의 파일업로드 기능과 밀접한 관련을 맺고 있다. 최근에 가장 흔하게 적용하는 방법은 첨부파일을 시스템 내부적인 규칙에 따라 이름을 바꿔서 저장하고 원래 파일이름, 관련 게시물 정보 등은 DB에 별도로 저장하는 것이 주요 추세이다.

root@kali:~# curl -I https://data.unhcr.org/syrianrefugees/download.php?id=7898
HTTP/1.1 200 OK
Date: Wed, 09 Nov 2016 11:13:37 GMT
Server: Apache
X-Powered-By: PHP/5.3.10-1ubuntu3.11
Set-Cookie: PHPSESSID=q7d8bu57odr91g443o9tdn7186; path=/
Expires: 0
Cache-Control: must-revalidate, post-check=0, pre-check=0
Pragma: public
Content-Description: File Transfer
Content-Disposition: attachment; filename=YUVANeeds-assessment-report-Final.pdf
Content-Transfer-Encoding: binary
Content-Length: 1568855
Content-Type: application/octet-stream

root@kali:~#

위의 사례는 id 변수에 숫자 하나만을 전달하지만 서버는 - 아마도 - DB에 저장된 정보를 바탕으로 원래 파일이름을 복구하여 다운로드할 수 있도록 한다. id 변수에 대해서 SQL 구문삽입 공격만 방어하면 다른 파일을 읽을 수 있는 임의 파일다운로드 (Arbitary File Download) 취약점이나 경로조작 (Path Traversal) 취약점은 발생하지 않을 것이다.

그러나 아직도 많은 웹 어플리케이션에서 첨부파일을 서버에 저장한 파일이름으로 내려받는 경우가 많다. 이러한 경우의 파일다운로드 취약점을 해소할 수 있는 방안은 "다운로드할 파일의 절대경로를 확인"하는 것이다.

<?php // file_down.php
	if (isset($_GET['down'])) {
		// get the real path with realpath() function
		$file = realpath('files/'.$_GET['down']);
		if (strstr($file, '/www/data/files/') == FALSE) {
			header("Location: /");
    			exit;
		}
		if (file_exists($file)) {
    			header('Content-Description: File Transfer');
    			header('Content-Type: application/octet-stream');
    			header('Content-Disposition: attachment; filename="'.basename($file).'"');
    			header('Expires: 0');
    			header('Cache-Control: must-revalidate');
    			header('Pragma: public');
    			header('Content-Length: ' . filesize($file));
    			readfile($file);
    			exit;
		}
		else {
			header("Location: /");
			exit;
		}
	}
?>

예를 들어보자. 위의 코드는 비교적 안전한 파일 다운로드 PHP 소스인데, (1) 절대경로 구하기와 (2) 디렉토리 확인의 두 단계로 구성되어 있다. PHP의 realpath() 함수를 사용하여 다운로드할 파일의 절대경로를 구하면 연이은 마침표("..")와 같은 공격 문자열이 자동으로 걸러진다. 이후에 다운로드할 파일이 다운로드가 허용된 디렉토리 - 여기서는 /www/data/files/ - 내에 위치하지 않으면 다운로드를 진행하지 않도록 한다. 이렇게 간단한 검증만으로도 허용되지 않은 파일을 악의적인 공격자가 다운로드 받기는 거의 불가능하다.

다만, 위의 사례에서는 strstr() 함수를 사용하여 디렉토리 이름을 검증했으므로 /home/www/data/files/, /var/www/data/files/, /data/home/jsphome/www/data/files/ 등과 같은 디렉토리가 있다면 이러한 디렉토리 내에 있는 파일을 다운로드할 수 있는 미약한 취약점은 존재한다.

[처음 작성한 날: 2016.11.09]    [마지막으로 고친 날: 2016.11.30] 


< 이전 글 : 파일업로드(웹쉘) 방어하기 (2016.11.09)

> 다음 글 : XSS, SQL Injection 방어하기 (2016.11.09)


크리에이티브 커먼즈 라이선스 이 저작물은 크리에이티브 커먼즈 저작자표시 4.0 국제 라이선스에 따라 이용할 수 있습니다.
잘못된 내용, 오탈자 및 기타 문의사항은 j1n5uk{at}daum.net으로 연락주시기 바랍니다.
문서의 시작으로 컴퓨터 깨알지식 웹핵 누리집 대문