공부하자 공부~/ASP

SQL Injection 처리 및 QueryString 값 제한..

Kelvin™ 2009. 5. 27. 10:19

목적 : 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

%>