본문 바로가기

닷컴's_IT/보안

파일 업로드 취약점 [-脆弱點, File Upload Vulnerability]

게시판 등에서

스크립트

파일의

업로드

에 대한 규제가 없을 경우 이를 악용한 해커에 의해 악성 스크립트 파일이 수행될 수 있는 보안 취악점.

첨부 파일

업로드를 허용하는 홈 페이지 게시판에서 .php, .jsp 등의

확장자

이름의 스크립트 파일의 업로드를 허용할 경우에 해커가 악성 실행 프로그램을 업로드한 후에 홈 페이지 접속 방식으로 원격에서 서버컴퓨터의 시스템 운영

명령어

를 실행시킬 수 있다. 예를 들어 모든 게시판에 대해 php, php3, asp, jsp, cgi, inc, pl 등의 확장자를 지닌 파일의 업로드를 시도하여 업로드가 되면 취약점이 있는 것이다

출처: 네이버 용어사전


================================================================================

소스 예제

□ ASP

 o 취약한 파일 업로드 예


Set Up = Server.CreateObject("SiteGalaxyUpload.Form")

uploadPath = server.mappath(".") & "\upload\"' 업로드 디렉토리

Fname = Up("file1")
if Fname <> "" then'파일 첨부가 되었으면
fileName=Mid(Fname,InstrRev(Fname,"\")+1)'파일이름부분 추출
savePath = uploadPath & fileName

Set fso = CreateObject("Scripting.FileSystemObject")
Up("file1").SaveAs(savePath)
response.write(savePath & " 저장 완료")
else
response.write("Error")
end if

Set Up = nothing


============================================================================

 o 안전한 파일 업로드 예


Set Up = Server.CreateObject("SiteGalaxyUpload.Form")
Path1 = server.mappath(".") & "\upload\"

Fname = Up("file1")

if Fname <> "" then'파일 첨부가 되었으면

if Up("file1").Size > 10240 then' 용량 제한
Response.Write "용량 초과"
Response.End
end if

if Up("file1").MimeType <> "image" then' 이미지만 업로드 허용
Response.Write "이미지 파일이 아닙니다."
Response.End
end if

Filename=Mid(Fname,InstrRev(Fname,"\")+1)'파일이름부분 추출

' 중복시에 파일이름부분을 변경하기 위해 분리를 한다
Farry=split(Filename,".")'.을 기준으로 분리
preFname=Farry(0)'파일이름 앞부분
extFname=Farry(1)'파일의 확장자

' 저장할 전체 path를 만든다, 파일이름을 구한다
Path2 = Path1 & Filename
saveFname=preFname & "." & extFname


Set fso = CreateObject("Scripting.FileSystemObject")
countNo = 0' 파일 중복될경우 셋팅 값
fExist=0' 같은 이름의 파일 존재 체크

Do until fExist = 1
If(fso.FileExists(Path2)) Then
countNo = countNo + 1
Path2 = Path1 & preFname & countNo & "." & extFname
saveFname=preFname & countNo & "." & extFname
else
fExist=1
End If
Loop

Up("file1").SaveAs(Path2)
response.write(saveFname & " 저장완료")
else
response.write("Error")
end if

Set Up = nothing

============================================================================

□ PHP

 o 취약한 파일 업로드 예

$uploaddir = '/var/www/uploads/';

$uploadfile = $uploaddir. $_FILES['userfile']['name'];

if(copy($_FILES['userfile']['tmp_name'], $uploadfile))
print "성공적으로 업로드 되었습니다.";
print_r($_FILES);
else
print "파일 업로드 실패";
print_r($_FILES);

============================================================================

 o 안전한 파일 업로드 예

$uploaddir = '/var/www/uploads/';

//파일 사이즈가 0byte 보다 작거나 최대 업로드 사이즈보다 크면 업로드를 금지 시킨다.
if($_FILES['userfile']['name'])
if($_FILES['userfile']['size'] <= 0)  // 최대 업로드 사이즈 체크 삽입
print "파일 업로드 에러";
exit;

//파일 이름의 특수문자가 있을 경우 업로드를 금지 시킨다.
if (eregi("[^a-z0-9\._\-]",$_FILES['userfile']['name']))
print "파일 이름의 특수문자 체크";
exit;

//파일 확장자중 업로드를 허용할 확장자를 정의한다.
$full_filename = explode(".", $_FILES['userfile']['name']);
$extension = $full_filename[sizeof($full_filename)-1];

/* PHP의 경우 확장자 체크를 할 때 strcmp(확장자,"php3"); 로 체크를 하게 되면
pHp3 이나 phP3는 구별을 하지 못하게 되므로 strcasecmp처럼 대소문자 구별을 하지
않고 비교하는 함수를 사용한다. 또한 .를 기준으로 하여 확장자가 하나로 간주하고
프로그램을 할 경우 file.zip.php3 이라고 올린다면 zip파일로 인식하고 그냥 첨부가
되므로 아래와 같이 제일 끝에 존재하는 확장자를 기준으로 점검하도록 한다. */

$extension= strtolower($extension);
if (!( ereg($extension","hwp") || ereg($extension","pdf") || ereg($extension","jpg")) )
print "업로드 금지 파일 입니다";
exit;


$uploadfile = $uploaddir. $_FILES['userfile']['name'];
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile))
print "파일이 존재하고, 성공적으로 업로드 되었습니다.";
print_r($_FILES);
else
print "파일 업로드 공격의 가능성이 있습니다! 디버깅 정보입니다:\n";
print_r($_FILES);

============================================================================

□ JSP

 o 취약한 파일 업로드 예

@ page contentType="text/html;charset=euc-kr" 
<%@ page import="com.oreilly.servlet.MultipartRequest,com.oreilly.servlet.multipart.DefaultFileRenamePolicy, java.util.*"
<%
String savePath="/var/www/uploads";// 업로드 디렉토리
int sizeLimit = 5 * 1024 * 1024 ;// 업로드 파일 사이즈 제한

try
MultipartRequest multi=new MultipartRequest(request, savePath, sizeLimit, new DefaultFileRenamePolicy());
Enumeration formNames=multi.getFileNames();// 폼의 이름 반환
String formName=(String)formNames.nextElement();
String fileName=multi.getFilesystemName(formName);// 파일의 이름 얻기

if(fileName == null)
out.print("Error");
 else
fileName=new String(fileName.getBytes("8859_1"),"euc-kr");
out.print("User Name : " + multi.getParameter("userName") + "<BR>");
out.print("Form Name : " + formName + "<BR>");
out.print("File Name  : " + fileName);


 catch(Exception e)
out.print("Error");
 
%>

=================================================================================================================

 o 안전한 파일 업로드 예

<%@ page contentType="text/html;charset=euc-kr" %>
<%@ page import="com.oreilly.servlet.MultipartRequest,com.oreilly.servlet.multipart.DefaultFileRenamePolicy, java.util.*"%>
<%
String savePath="/var/www/uploads";// 업로드 디렉토리
int sizeLimit = 5 * 1024 * 1024 ; // 업로드 파일 사이즈 제한

try
MultipartRequest multi=new MultipartRequest(request, savePath, sizeLimit, "euc-kr", new DefaultFileRenamePolicy());
Enumeration formNames=multi.getFileNames();  // 폼의 이름 반환
String formName=(String)formNames.nextElement();
String fileName=multi.getFilesystemName(formName); // 파일의 이름 얻기

String file_ext = fileName.substring(fileName.lastIndexOf('.') + 1);
if(!( file_ext.equalsIgnoreCase("hwp") || file_ext.equalsIgnoreCase("pdf") || file_ext.equalsIgnoreCase("jpg")) )
out.print("업로드 금지 파일");


if(fileName == null)
out.print("파일 업로드 실패");
 else
fileName=new String(fileName.getBytes("8859_1"),"euc-kr"); // 한글인코딩
out.print("File Name  : " + fileName);

 catch(Exception e)

Posted by 재한 행복한재한