파일업로드 취약점은 공격이 성공하면 바로 서버가 해킹이 되는 것이기 때문에 가장 리스크가 큰 취약점 입니다.
그래서 절대로 웹쉘이 업로드가 되지 않도록 해야 합니다.
근본적으로 대응하는 방법은 간단합니다.
파일이 업로드 되는 서버나 폴더에 서버사이드 스크립트 실행 권한을 제거해 버리면 됩니다.
그러면 웹쉘이 업로드 되더라도 asp, php, jsp 등이 실행이 되지 않기 때문에 문제가 없습니다.
파일 업로드 폴더에서 스크립트 실행 권한을 제거하려면 우선 웹 페이지 폴더와 업로드 파일 폴더를 분리해야 합니다.
(서버단위로 분리하는것이 가장 좋은 방법이겠지만 폴더 단위로도 권한을 제어할 수 있습니다.)
기존에 분리되어 있다면 스크립트 실행권한이 있는지만 확인하고, 있을경우 삭제해 버리면 끝입니다.
일단 조사를 해야 할것입니다.
어느 메뉴가 파일 업로드 기능을 가지고 있는지 모두 조사를 해야 합니다.
왜냐하면 모든 메뉴의 페이지에서 대응을 해야 하니까요..
모든 메뉴의 파일 업로드 로직을 일일이 확인하고 웹쉘같은 악의적인 파일이 업로드 될 수 있는지 체크해야 합니다.
window2008 서버에서 파일실행권한 제거 방법
1. iis에서 실행권한을 제거하고자 하는 폴더를 클릭합니다.
2. 처리기매핑을 클릭합니다.
3. 마우스 오른쪽키를 눌러 기능사용권한 편집을 클릭합니다.
4. 스크립트 항목 선택을 해제 후 확인버튼을 누릅니다. 페이지 레벨에서 대응하지 않고 IPS를 활용하면 한번에 해결할 수 있지 않을까 하는 생각을 해 볼수가 있지만 제 경험상 IPS만으로는 한계가 있습니다.
왜냐하면 패턴으로 등록해서 방어할 수도 있겠지만 이 취약점 만큼은 100% 완벽하게 막아야 하기 때문에 우회가 가능한 IPS만으로는 어렵죠..
(그렇다고 IPS를 사용할 필요가 없다는 것은 아닙니다. IPS가 있다면 최대한 활용을 하는것이 원칙이죠//)
일단 IPS예기가 나온김에 패턴이라도 보고 가겠습니다.
아무래도 웹쉘이다 보니 OS 명령어를 실행할 수 있는 스크립트 함수가 패턴이라 할 수 있겠네요..
asp / aspx :
cmd.exe
WScript.Shell
Scripting.FileSystemObject
ADOX.Catalog
Adodb.connection
VBScript.Encode
CODEPAGE
"949"
<%execute
Language="C#"
System.Reflection
VBScript.Encode
script runat
WScript.ShellApp
WSCRIPT.NETWORK
Shell.ApplicationApp
Adodb.Connection
Adodb.RecordSet
Adodb.Stream
Scripting.FileSystemObject
SoftArtisans.FileUp
Provider=SQLOLEDB.
등등
jsp :
jdbc.sqlserver
jdbc:microsoft
sun.jdbc.
.OracleDriver
jdbc:mysql:
Runtime.
.exec
out.println
import="java.io
등등
php :
popen(
exec(
fopen(
system(
passthru(
escapeshellcmd(
$_SERVER
등등
각각의 업로드 페이지 레빌에서 웹쉘을 체크하는 로직에 대해서 알아보겠습니다.
웹쉘을 체크하는 로직은 아래와 같은 방법이 있습니다.
1. 확장자 체크
2. mime type 체크
3. ; , %00, %zz 체크
1. 업로드 되는 파일의 확장자 체크는 가장 기본적이며 필수입니다.
모든 확장자를 제한하고 허용하는 일부 확장자만 업로드 되도록 제한하는 것이 기본입니다.
확장자를 체크힐때는 뒤에서 부터 체크를 해야 합니다.
shell.gif.asp shell.jpg.jsp 등으로 확장자체크 우회 테크닉은 기본중의 기본이니까요..
2. 두번째는 mime-type 체크입니다.
이미지 파일일 경우는 image/pjpeg, image/gif 이겠지만 웹쉘같은 텍스트 형식일 경우는 txt/html 형식일 것입니다.
물론 mime-type 은 간단한 조작에 의해서 우회가 되겠지만..
기본적으로 확장자 체크와 같이 하는것을 권장합니다.
3. 특수문자 체크
파일명에 특수문자가 있는지 체크합니다. -> %00 , %zz, ;
%00 이나 %zz 는 종단문자로서 파일서버가 리눅스 시스템일 경우 우회 기법으로 사용합니다.
예를들어 파일명을 shell.jsp%00.gif 로 업로드 하면 확장자 체크는 우회할 수 있습니다.
그리고 서버에 저장되어 호출될때 시스템이 %00, %zz 를 종료문자로 인식하여
shell.jsp 로 호출을 했을때 jsp로 실행되는 경우가 있습니다.
세미콜론(;) 같은 경우는 윈도우 IIS 의 취약점입니다.
shell.asp;.jpg 로 파일명을 업로드 하면 확장자 체크를 우회할 수 있는데 shell.asp 로 호출을 하니 호출이 됩니다.
세미콜론(;) 이나 물음표(?) 는 URL에서 URI와 파라메터를 구분하는 문자입니다.
예: http://www.xxx.co.kr/xxx.asp;xxxx=111
URL : http://www.xxx.co.kr/xxx.asp;xxxx=111 URI : http://www.xxx.co.kr/xxx.asp 인자값 : xxxx=111
그래서인 지는 몰라도 IIS 에서 호출할때 shell.asp;.jpg 파일을 shell.asp 로 호출하면 asp 로 정상 호출이 됩니다.
IIS의 바보같은 버그이죠.
이정도 체크를 해야 안심할 수 있습니다.
여기에다가 파일 이름은 난수화 시켜서 저장한다던지, 아예 확장자를 강제로 붙여버리는 로직을 구현한다면 더 안전할 것입니다.
g_file1=UploadForm("g_file1")
if Len(g_file1)>0 then
att_file=UploadForm("g_file1").filepath
filesize1=UploadForm("g_file1").size
if filesize1<20000000 then
filename=mid(att_file, InstrRev(att_file,"\")+1) //파일명+확장자를 뽑는다.
strname=Mid(filename, 1, InstrRev(filename,".")-1) //파일명만 뽑는다.
strname = file_StrDelete(strname)
strExt=Mid(filename,InstrRev(filename,".")+1) //확장자만 뽑는다.
strExt=Lcase(strExt)
fnc_strExt_block(strExt)
bExist=True
strfilename = strname & "." & strExt
cntFile = 0
do while bExist
if (FSO.FileExists(DIR_O_CODE&"/"&strfilename)) then
cntfile = cntfile+1
strfilename= strname&"_"&cntfile&"."&strExt
else
bExist=false
end if
Loop
filename1 = strfilename
strfilename = DIR_O_CODE &"/"& strfilename
UploadForm("g_file1").SaveAs strfilename
else
Alert_back "화일 용량이 20M을 초과할수 없습니다."
end if
end if
위 소스에서 가장 중요하게 필터링 할 부분이 아래 부분입니다.
strname = file_StrDelete(strname)
파일명과 확장자를 구분한 다음 file_StrDelete() 함수를 이용해서 파일명으로 된 문자열을 필터링하게 됩니다.
파일명에 의심되는 문자나, 특수문자등을 제거해 줍니다.
아래는 file_StrDelete() 함수 입니다. 필터링 해야 할 문자가 더 있다면 소스에 추가만 하면 됩니다.
'------------------- 특정 문자 삭제 함수 -----------------------
Function file_StrDelete(strmessage)
StrDelete=Replace(strmessage,".","")
StrDelete=Replace(StrDelete,"&","")
StrDelete=Replace(StrDelete,"%","")
StrDelete=Replace(StrDelete," ","")
StrDelete=Replace(StrDelete,",","")
StrDelete=Replace(StrDelete,"?","")
StrDelete=Replace(StrDelete,"@","")
StrDelete=Replace(StrDelete,"$","")
StrDelete=Replace(StrDelete,"!","")
StrDelete=Replace(StrDelete,"^","")
StrDelete=Replace(StrDelete,"*","")
StrDelete=Replace(StrDelete,"(","")
StrDelete=Replace(StrDelete,")","")
StrDelete=Replace(StrDelete,"+","")
StrDelete=Replace(StrDelete,";","")
StrDelete=Replace(StrDelete,"#","")
StrDelete=Replace(StrDelete,"=","_")
StrDelete=Replace(StrDelete,"'","")
file_StrDelete=StrDelete
End Function
두번째로 중요한 소스트 fnc_strExt_block(strExt) 명령입니다.
fnc_strExt_block() 함수는 특정한 확장자만을 업로드 할수 있는 기능입니다.
asp의 경우 , asp, dll, cer, php, exe 등으로 막아 놓으면, 얼마든지 확장자를 우회해서 업로드 할 수 있습니다.
이런 경우 서버가 위험해 질 수 있으니,
개발자가 허가한 확장자만 올리게끔 막아 놓는게 가장 안전합니다.
'----------파일 업로드시 확장자 체크 ----------
Function fnc_strExt_block(strExt)
strExt = Lcase(strExt)
chk="X"
select case strExt
'이미지 파일
Case "gif","jpeg","bmp","tif","tiff","jpg","png","psd","au","ogg"
chk="O"
'압축 파일
Case "zip","alz","a01","a02","a03","egg"
chk="O"
'문서 파일
Case "doc","hwp","xls","xlsx","ppt","pptx","csv","txt","doc","pdf","docx"
chk="O"
'녹취 파일
Case "wav","avi","mp3","mpg","mpeg"
chk="O"
'플레쉬 파일
Case "swf"
chk="O"
end select
If chk="O" Then
Else
Response.write "파일명의 확장자를 확인해 주세요!
(이미지 파일 : gif , jpg , bmp , tif , tiff , png , psd , au , ogg)
(압축 파일 : zip ,alz, a01 , a02 , a03 )
(문서파일 : doc , hwp , xls , xlsx , ppt , pptx, csv , txt , doc , pdf )
(녹취 파일 : wav , avi , mp3)
(플레쉬 파일 : swf , fla ) 위에 언급한 파일만 업로드 할 수 있습니다."
Response.end
End If
End Function
파일 업로드, 즉 웹쉘이 업로드 될 수 있는 취약점은 99.9% 가 아닌 100% 막아야 하는 취약점일 것입니다.
무슨 수를 써서라도 막아야 하는데.. 웹보안이라는것이 해킹하는것보다 막는것이 훨씬 어려운지라..
아무리 막아도 막아도 근본적으로 안전하다고 자신하기에는 힘드네요..