SQL Injection 처리 및 QueryString 값 제한..
목적 : SQL Injection 이 들어오는 QueryString 값을 제한하여 초기대응함과 동시에
로그인시 필요한 Return URL 을 제외한 모든 QueryString 값의 길이를 구별하여 50자 이상의
쿼리 스트링은 모두 접근 거부 하고자 함.
조건
- 아래의 소스는 모든 페이지에 include 형태로 존재하고 있어야 함.
- Option Explicit 구문 사용시 변수명 중복에 주의 하여야 함.
- XML 화일이 저장되는 곳의 폴더 권한 설정 필요.
- 정상 요청도 막는 경우가 있으니 항상 XML 화일 확인하여 정상접근을 해제 해 주어야 함.
추가
- 아래의 소스는 인터넷 어딘가에서 퍼온 소스를 수정한것이나 원작자를 기억하지 못하고 있습니다.
- 참고된 소스의 원작자가 보고 계시다면 연락 부탁 드립니다.
====================== 이하 소스 ============================================
' ===========================
' injection 처리
' ===========================
' 변수 선언 ( 타 소스와 중복되지 않게 주의 요망 )
Dim injection_filter, item, inj_qs, injection_filter_arr
Dim injection_filter_cnt, j, get_check, post_check
injection_filter = "having|syscomments|xp_displayqueuemesgs|xp_printstatements|table|raiserror|xp_dsinfo|xp_peekqueue|--|shutdown|exec|xp_mergelineages|xp_proxiedmetadata|select|kill|xp_|xp_readpkfromqueue|xp_displayparamstmt|insert|declare|sp_|xp_readpkfromvarbin|xp_availablemedia|update|openrowset|xp_cmdshell|xp_repl_encrypt|xp_enumdsn|delete|opendatasource|xp_reg|xp_resetqueue|xp_filelist|drop|pwdencrypt|xp_servicecontrol|xp_sqlinventory|sp_password|alter|msdasql|xp_setsqlsecurity|xp_unpackcab|sp_adduser|create|sqloledb|xp_readerrorlog|xp_sprintf|sp_addextendedproc|inner|join|char(|xp_controlqueueservice|xp_displayparamstmt|sp_dropextendedproc|from|syslogins|xp_createprivatequeue|xp_enumresult|sp_add_job|where|sysxlogins|xp_decodequeuecommand|xp_showcolv|sp_start_job|union|sysdatabases|xp_deleteprivatequeue|xp_updatecolvbm|sp_delete_alert|group|by|sysobjects|xp_deletequeue|xp_execresultset|sp_msrepl_startup|%20and%20|isMember|administrators /add|xp_dirtree|--|2=2|3=3|a=a|b=b|c=c|…|;’|’;"
' 등록된 Injection 코드 발견시 XML 로그 생성할 function
Function objXML_Log(BAD_WORD,QUERY_STRING)
' 함수내 변수 선언
Dim objXML, blnFileExist
Dim objXMLv
Dim intID
Dim xml_file_name
' 에러처리
On Error Resume Next
Set objXML = server.CreateObject("Microsoft.XMLDOM")
objXML.async = False
'-----파일명칭 ( 로그가 쌓일 XML 화일의 경로를 지정 - 보통은 화일 업로드 폴더에 따로 넣어둠 )
xml_file_name = "/FileHome/injection.xml"
'-----파일이 존재하는지 체크
blnFileExist = objXML.load(server.MapPath(xml_file_name))
If blnFileExist = False Then
objXML.appendChild(objXML.createProcessingInstruction("xml","version=""1.0"""))
objXML.appendChild(objXML.createElement("IP_LOGS"))
intID = 1
Else
intID = objXML.documentElement.childNodes(objXML.documentElement.childNodes.length - 1).childNodes(0).text + 1
End If
'-----프로세스 시작
Set objXMLv = objXML.createElement("IP_LOG")
objXMLv.appendChild(objXML.createElement("ID"))
objXMLv.appendChild(objXML.createElement("USER_ID"))
objXMLv.appendChild(objXML.createElement("BAD_WORD"))
objXMLv.appendChild(objXML.createElement("QUERY_STRING"))
objXMLv.appendChild(objXML.createElement("HTTP_REFERER"))
objXMLv.appendChild(objXML.createElement("REMOTE_ADDR"))
objXMLv.appendChild(objXML.createElement("LOCAL_ADDR"))
objXMLv.appendChild(objXML.createElement("DATE"))
objXMLv.childNodes(0).text = intID
objXMLv.childNodes(1).text = session("USER_ID")
objXMLv.childNodes(2).text = BAD_WORD
objXMLv.childNodes(3).text = Request.ServerVariables("SCRIPT_NAME") &"?"& QUERY_STRING
objXMLv.childNodes(4).text = Request.ServerVariables("HTTP_REFERER")
objXMLv.childNodes(5).text = Request.ServerVariables("REMOTE_ADDR")
objXMLv.childNodes(6).text = Request.ServerVariables("LOCAL_ADDR")
objXMLv.childNodes(7).text = Now()
'-----파일 저장
objXML.documentElement.appendChild(objXMLv.cloneNode(True))
objXML.save(server.MapPath(xml_file_name))
'-----객체 해제
Set objXMLv = Nothing
Set objXML = Nothing
End Function
' 실제 Injection 공격이 있는지 확인 하는 Function
Function f_injection(query_string)
f_injection = false
injection_filter_arr = split(injection_filter,"|")
injection_filter_cnt = Ubound(injection_filter_arr)
for j = 0 to injection_filter_cnt
if InStr(1,query_string,injection_filter_arr(j),1) > 0 Then
f_injection = true
' Injection 공격 명령어 리스트에 있는 단어이면 오류 메시지 출력
Response.Write " (필터링된 문자 : <font color=blue>"& injection_filter_arr(j) &"</font>)<br>"
Call objXML_Log(injection_filter_arr(j),query_string)
Response.End
exit for
end if
next
End function
'post체크
For each item in REQUEST.FORM
For i=1 to REQUEST.FORM(item).Count
If REQUEST.FORM(item)(i) <> "" Then
If f_injection(REQUEST.FORM(item)(i)) = true then
post_check = true
exit for
End if
End if
Next
Next
' QueryString 길이 체크하여 블럭처리
For Each item in Request.QueryString
If item <> "redirect_URL" Then
If len(Request.QueryString(item)) >= 50 Then
Response.write "전달하는 값의 길이가 너무 길어 공격 시도로 판단되어 처리를 종료합니다."
response.end
End If
End If
Next
'QueryString 내용에 Injection 구문 체크
inj_qs = Request.ServerVariables("QUERY_STRING")
If inj_qs <> "" Then
get_check = f_injection(unescape(inj_qs))
End if
if post_check = true or get_check = true then
Response.End
End if
%>