1. 파일 업로드 취약점이란
파일 업로드 시 확장자를 검증하는 이유는
주로 게시판 등에서 파일 업로드 기능을 악용하여 시스템 권한을 획득할 수 있는 취약점을 의미한다.
악성 스크립트가 업로드된 후, 서버상에서 스크립트를 실행하여 쉘을 획득하는 등의 행위로 서버를 장악할 수 있다.
즉, 흔히 말하는 웹쉘의 업로드를 통해 시스템의 권한을 장악한다는 이야기이다.
그렇다면 어떤 파일들이 웹에서 구동되는가? 웹 서버에서 실행 가능한 확장자는 다음과 같다.
언어 | 확장자 |
asp, aspx | asp, aspx, htm, html, asa |
php | phtml, php, php3, php4, php5, inc, htm, html |
jsp, java |
jsp, jspx, jsw, jsv, jspf, htm, html |
perl |
pl, pm, cgi, lib, htm, html |
coldfusion |
cfm, cfml, cfc, dbm, htm, html |
이러한 악성 파일이 업로드 된다면, 접근권한, 정보유출, 악성코드 배포 등의 문제를 야기할 수 있다.
2. 공격방법
이러한 취약점을 찾아 공격하는 방법은 크게 4가지 정도이다.
2-1. 취약점 점검
가장 간단한 방법으로 다음과 같은 과정을 거친다.
- 파일 업로드시에 확장자 제한이 없는지 확인하고,
- 업로드된 파일에 접근 및 실행이 가능한지 확인하여 공격하는 것이다.
2-2. Proxy 툴을 이용해 확장자 검사 우회 파일 업로드
파일타입 변조등의 우회공격을 통해 확장자 검사를 피하는 것을 의미한다.
업로드 시 파일의 유형 정보를 알려주는 헤더 중, Content-type 속성을 프락시를 이용해 우회하여 공격할 수 있다.
2-3. Null을 이용한 파일 업로드
널(%00) 문자가 문자의 끝을 의미하기 때문에 특정 확장자를 숨기기 위한 목적으로 사용될 수 있다.
해당 부분의 취약점은 내부 API를 호출할 때 발생될 가능성이 있다.
널 바이트(%00)와. jpeg확장자를 함께 접목하여 업로드하면 %00 다음의 문자열은 무시하게 된다.
언어 | 우회패턴 | 처리패턴 |
php | test.php%00.jpeg | test.php |
asp | test.asp%00.jpeg | test.asp |
jsp | test.jsp%00.jpeg | test.jsp |
2-4. SQL Injection을 이용한 파일 업로드
2가지 정도의 방법이 존재하는데, 다음과 같다.
MySQL의 into outfile() 함수를 이용하여 웹서버에 파일을 생성할 수 있다.
MSSQL의 저장 프로시저(xp_cmdshell)를 이용하여 echo와 » (파이프) 명령어를 통해 특정 파일에 삽입할 수 있다.
3. 방어방법
모든 부분을 전부 작성할 수는 없지만, 대략적으로 다음과 같은 방법을 통하여 기초적인 방어를 할 수 있다.
- 확장자 검사
- 대소문자 구분하지 않고 확장자 비교
- 특수문자가 포함된 경우 업로드 금지
- 업로드된 파일명, 확장자를 난수 화하여 변경
- 업로드된 파일을 url 요청으로 직접 접근이 불가능한 위치에 저장
파일 업로드 유틸 부분
enum ExecutableExtensionType
{
ASPX, ASP, PHP, JSP, HTML, CGI, PERL, SH, EXE, BAT, BIN
}
//파일처리부분
Enumeration<String> fileNames = multipartrequest.getFileNames();
List<String> files = null;
while (fileNames.hasMoreElements())
{
String inputName = fileNames.nextElement(); // 파라미터명
// 파라미터명 없으면 생략
if(StringUtil.isEmpty(inputName))
{
continue;
}
String fileName = multipartrequest.getFilesystemName(inputName); // 파일명
// 파라미터에 파일이 없으면 생략
if(StringUtil.isEmpty(fileName))
{
continue;
}
// 업로드한 파일객체 얻기
File uploadFile = multipartrequest.getFile(inputName);
// 실행가능한 확장자인지 확인
String fileExt = FileUtil.getExt(uploadFile.getName());
ExecutableExtensionType[] exeExtTypes = ExecutableExtensionType.values();
for(ExecutableExtensionType exeExt : exeExtTypes)
{
// 실행가능한 확장자일경우 415(지원되지 않는 미디어 유형) 상태로 반환해준다.
if(exeExt.name().equalsIgnoreCase(fileExt))
{
uploadFile.delete();
reqMap.put(SUCC_YN, "N");
reqMap.put("STATUS", 415);
reqMap.put(ERR_MSG, fileName + " is Executable!");
}
}
파일 업로드 시 javascript ajax 에러 핸들링
error : function(jqXHRr, textStatus, errorThrown)
{
if(jqXHRr.status == 415)
{
alert('실행가능한 파일은 업로드되지 않습니다.');
}
else
{
alert("code:"+jqXHRr.status+"\nerror:"+errorThrown);
}
}
오늘도 보람찬 생존 ^.^
'자바 > 시큐어코딩' 카테고리의 다른 글
XSS(Cross Site Scripting) 방어 (2) | 2022.12.30 |
---|
댓글