요즘 발생하는 웹해킹은 웹서버의 보안이 강화(?)되고 있기때문에 직접 파일을 올려서 서버상의
페이지 변조등의 다양한(?) 작업을 하기보다 단순히 스크립트만을 삽입하는 형태가 대세인듯합니다. 특별히 대세가 아니라 파일업로드가
어려워지자 스크립트만 삽입하는게 시간대비 성공률이 월등히 높아서 일수도 있습니다. 파일 업로드를 막는
방법에서도 알수 있듯이 간단합니다. 추가적으로 파일 업로드를 하면서 웹쉘을 막는 더 좋은 방법도 있습니다.
스크립트만 삽입하는 방식은 웹쉘을 올릴필요도 없고 달랑 한줄짜리의
웹사이트 접속로그를 만들면서 원하는 작업을 할수 있기때문에 가장 선호하는 방법이 된것인지도 모릅니다. 가장 선호하는 만큼
가장 경계를 해야할 대상입니다.
다음은 웹서핑중 찾은 webknight 로그 입니다.
위 로그에서 한개의 쿼리 단어만 막으면 막히는 간단한 웹해킹 로그입니다.
정답은 case, char(
입니다.
webknight 가 정규식을 지원하지 않는 관계로 엄청 많은 룰을 입력해야 합니다. nice19님이 테스트하신 부분 이 있으니 참고하시기
바랍니다.
요즘 많은 분들이 MASS SQL Injection 으로 피해를 보고 있는것 같습니다. 필자도 물론 예외는 아니였습니다. 지금에야 '쿠키를 이용한 인젝션공격이였습니다' 라고 이야기를 하지만 얼마전까지만해도 스크립트가 추가된 구문을 볼때마다 필자가 관리하는 서버를 사용하는 분들에게 송구스러운 마음이 참 많았습니다.
예전부터 심심치 않게 SQL Injection 을 이용한 스크립트 삽입공격은 있었습니다. 쿼리스트링에 추가하여서 공격하는 수준이였기때문에 웹나이트(Webknight) 문법으로 전부 막아내는 쿼거(?)도 이루었던 적도 있습니다.
이렇게 자만하다 큰코다친겁니다. 제가 관리하는 몇개의 사이트가 스크립트가 추가되는 사례가 발견되더니 잊을만 하면 한번씩 스크립트가 추가되는 현상을 발견하게 되었고, 쇼핑몰같은 경우는 데이터베이스를 복구할수도 없는 그런 상황까지 겪게 되었습니다.
"목마른 사람이 우물을 판다"고 했던가요.. 일단 삽입이 되도록 하는 구문을 분석하여서 이를 바탕으로 스크립트만 삭제하는 구문을 작성하려고 하였습니다. char, nchar, varchar, nvarchar 는 너무 쉽게 변경이 가능했지만 문제는 text, ntext 같은 대용량의 유니코드 형식의 데이터에서 스크립트를 삭제하는 부분이였습니다.
몇몇 다른 분들의 경우 text 타입을 varchar(8000) 으로 변환하고 이를 수정하는 방법을 선택하셨습니다. 이 방법도 좋은 방법입니다. 쿼리만으로 작업을 진행할수도 있고, 일단 SQL 쿼리를 구하기가 쉬웠습니다. ( SQL 쿼리를 공개해주신 분들 감사합니다.)
그래도 문제는 발생하였습니다. 문자열을 신문을 집어 넣은건지 상당히 큰 text 타입의 데이터를 만나버리고 말았던 것이였습니다. 결국 VBScript 를 이용해서 다시 작업을 하도록 변경하였습니다. (사실 SQL 쿼리 수정보다 VBScript가 더 쉽게 생각되었습니다.;)
이래서 탄생한 Replace_string_in_mssql.vbs 입니다.
' ***************************************************************************************
' 디비 변조데이터 복구 스크립트
' 버 젼 : v1.0
' ***************************************************************************************
Option Explicit
'On Error Resume Next
' 삭제할 자바스크립트 구문
' 다중입력이 가능하며, 다중입력시 | 로 입력하시기 바랍니다.
Const strReplace = "<script src=http://ojkqn.cn></script>|<script src=http://wefd4.cn>|"
Const strDBServerIP = "127.0.0.1" ' 접속할 데이터베이스 서버 IP
Const strSQLuser = "sa" ' 접속할 데이터베이스 아이디
Const strSQLpass = "1230" ' 접속할 데이터베이스 패스워드
Const strSQLBD = "pubs" ' 접속할 데이터베이스 이름
Dim CRLF, TAB :TAB = CHR( 9 ):CRLF = CHR( 13 ) & CHR( 10 )
Dim AdCn,connectionstring,SQL,DBdata,arrDBData, arrDBData2
Dim SQL_Tables, SQL_Tables_Exists_Javascript, ColumnsArrDBdata, ColumnsTotal, TableArrDBdata, TableTotal, SQL_tmp
Dim i, j, db_table, db_column, db_xtype, db_type, db_owner, db_len
Dim TablecolumnCheck, SQL_Tables_Replace_Javascript
Dim KeyName, Key_code, Key_entry, arr_Replacetxt, Replacetxt
arr_Replacetxt = split(strReplace,"|")
SQL_Tables = "select o.name, c.name, c.xtype, type = (select t.name from systypes t where t.name <> 'sysname' and t.xtype=c.xtype ) , owner = user_name(uid) " & _
" ,Len = (select case when t.name in (N'nchar', N'nvarchar') then c.length/2 else c.length end from systypes t where t.name <> 'sysname' and t.xtype=c.xtype ) " & _
" from dbo.syscolumns c " & _
" Left Join (select name,id,uid from dbo.sysobjects where xtype='U' " & _
" and (case when (OBJECTPROPERTY(id, N'IsMSShipped')=1) then 1 else OBJECTPROPERTY(id, N'IsSystemTable') end)=0 ) o " & _
" on c.id=o.id where o.name is not null and c.xtype in (35, 99, 167, 175, 231, 239) " & _
" order by o.name, c.name "
' 35 -- text
' 99 -- ntext
' 167 -- varchar
' 175 -- char
' 231 -- nvarchar
' 239 -- nchar
connectionstring = "Provider=SQLOLEDB.1;Data Source= "&strDBServerIP&";Initial Catalog="&strSQLBD&";user id = '"&strSQLuser&"';password='"&strSQLpass&"' "
SQL = SQL_Tables
Set AdCn = CreateObject("ADODB.Connection")
AdCn.open = connectionstring
set DBdata = AdCn.Execute(SQL)
IF Not DBdata.Eof then
ColumnsArrDBdata = DBdata.GetRows()
ColumnsTotal = UBound(ColumnsArrDBdata, 2)+1
else
ColumnsTotal = 0
end if
DBdata.Close
Set DBdata = Nothing
wscript.echo "컬럼갯수 : "&ColumnsTotal
If ColumnsTotal>0 then
For i=1 to ColumnsTotal
db_table = ColumnsArrDBdata(0,i-1)
db_column = ColumnsArrDBdata(1,i-1)
db_xtype = ColumnsArrDBdata(2,i-1)
db_type = ColumnsArrDBdata(3,i-1)
db_owner = ColumnsArrDBdata(4,i-1)
db_len = ColumnsArrDBdata(5,i-1)
SQL = "select count(*) From ["&db_owner&"].["&db_table&"] where CHARINDEX('<script',"&db_column&") > 0 "
set DBdata = AdCn.Execute(SQL)
IF Not DBdata.Eof then
arrDBData = DBdata.GetRows()
TablecolumnCheck = arrDBData(0,0)
else
TablecolumnCheck = 0
end if
DBdata.Close
Set DBdata = Nothing
if TablecolumnCheck > 0 then
If db_xtype <> 35 and db_xtype <> 99 then
For each Replacetxt in arr_Replacetxt
wscript.echo "["&db_owner&"].["&db_table&"] 에서 "&db_column&" 컬럼에 대한 "&Replacetxt&" 삭제중..."
SQL = "Update ["&db_owner&"].["&db_table&"] Set "&db_column&" = replace("&db_column&",'"&Replacetxt&"','')"
AdCn.Execute(SQL)
Next
Else
SQL = "select name from syscolumns where id in (select id from sysobjects where name = '"&db_table&"') "
SQL = SQL&"and colid in (select sik.colid from sysindexkeys sik join sysobjects so on sik.id = so.id where sik.indid = 1 and so.name = '"&db_table&"')"
set DBdata = AdCn.Execute(SQL)
IF Not DBdata.Eof then
arrDBData2 = DBdata.GetRows()
KeyName = arrDBData2(0,0)
else
KeyName = ""
end if
DBdata.Close
Set DBdata = Nothing
If Len(KeyName) > 0 then
SQL = "select "&KeyName&","&db_column&" From ["&db_owner&"].["&db_table&"] "
set DBdata = AdCn.Execute(SQL)
IF Not DBdata.Eof then
TableArrDBdata = DBdata.GetRows()
TableTotal = UBound(TableArrDBdata, 2)+1
else
TableTotal = 0
end if
DBdata.Close
Set DBdata = Nothing
If TableTotal > 0 then
for j=1 to TableTotal
Key_code = TableArrDBdata(0,j-1)
Key_entry = TableArrDBdata(1,j-1)
Key_entry = Replace(Key_entry,"'","''")
For each Replacetxt in arr_Replacetxt
Key_entry = Replace(Key_entry,Replacetxt,"")
Next
wscript.echo "["&db_owner&"].["&db_table&"] 에서 "&db_column&" 컬럼에 대한 삭제중..."
SQL = "update ["&db_owner&"].["&db_table&"] Set "&db_column&" = '"&Key_entry&"' where "&KeyName&"="&Key_code
AdCn.Execute(SQL)
Next
End if
End if
End if
End if
next
Else
wscript.echo "컬럼이 없습니다."
end if
AdCn.Close
set AdCn=Nothing
내용은 무척 간단합니다. 컬럼중에 text, ntext, varchar, char, nvarchar, nchar 에 해당하는 것들에 대해서 "<script" 라는 구문이 포함되어 있으면 삭제작업을 하는 것으로 text, ntext 타입에 대해서만 특별히 ado를 이용해서 처리하였습니다.
댓글을 달아 주세요
최근에 CSRF 와 SQL injection 의 짬뽕 기법이 등장하기 시작했다고 합니다. -_-
2008.12.05 23:36 [ ADDR : EDIT/ DEL : REPLY ]날이 갈수록...어렵군요. CSRF는 웹방화벽으로도 방어가 힘들다는데...큭;
웹어플리케이션에서 막는다면 이런게 필요가 없겠죠..
2008.12.08 01:30 [ ADDR : EDIT/ DEL ]정규식을 지원하지 않는다면 엄청난 막일이겠군요.
2008.12.11 13:02 [ ADDR : EDIT/ DEL : REPLY ]네. 정말 좌절입니다.
2008.12.11 17:20 [ ADDR : EDIT/ DEL ]스킨이 맘에 들어서 바꾸기는 했는데..
다니는 블로그마다 같아서 햇갈리는군요..;;