The Basic Of Blind SQL Injection Sur3x5F - PRIDE NateOn : austinkwon@nate.com
목 차 0x00. Intro 0x01. You should know... 0x02. What is Blind SQL Injection 0x03. Get db information from information_schema 0x04. WebGoat-Blind SQL Injection 0x05. To be safe from this problem
0x00. INTRO 안녕하세요, Sur3x5F 의 PRIDE 입니다. Blind SQL Injection 에관한문서가적고, 개인적인복습및공부, 또한 IT 공부하 시는분들게도움이되고자작성한문서입니다. 이문서는 SQL 과기본 SQL 인젝션에대해안다는전제하에제작한문서입니다. Blind SQL Injection 의개념및이루어지는과정을이해하시는데조금이나마도움 이됬으면좋겠습니다. 이문서를배포및재이용하실때에는이저작물에적용된저작권을명확하게나타 내셔야합니다. Sur3x5F : http://www.sur3x5f.org PRIDE : http://www.pride.wo.tc
0x01. You should know... Blind SQL Injection 에필요한함수들을간략히소개하겠습니다. 이문서는 SQL 과 SQL INJECTION 을안다는전제하에쓰여진문서이기때문에 SQL 에 대해서는설명하지않겠습니다. substr 함수는문자열과자를문자열의범위를파라미터로받아서해당부분의 문자열을리턴해주는함수입니다. -substr 함수 : substr( string, 자르기시작할문자의인덱스, 자를문자의개수 ) ex) USERS 테이블엔 id 와 pw 컬럼이존재하며 id = pride 이고 pw = asdf 인 행이존재할때, USERS table id pride pw asdf substr((select pw FROM USERS WHERE id='pride'),1,1) 위의쿼리문을 db 에보내게되면 1) SELECT pw FROM USERS WHERE id='pride' 의쿼리를먼저실행하여 'asdf' 라는문자열을가져오게되고, 2) substr('asdf',1,1) substr 함수에의하여첫번째글자부터한글자를가져옵니다. 3) asdf 의첫글자인 a 가반환됩니다. ascii 함수는파라미터로받은값의아스키코드값을리턴해주는함수입니다. -ascii 함수 : ascii( 변환할문자 ) ex) ascii(c) 이쿼리를보내어실행시켰을때, c 의아스키코드값인돌려주게됩니다. 99 를
0x02. What is Blind SQL Injection Blind SQL Injection 은평범한 SQL Injection 과같이원하는데이터를가져올쿼리를삽입하는기술입니다. 하지만평범한 SQL Injection 과다른점은평범한 SQL Injection 은쿼리를삽입하여원하는데이터를한번에얻어낼수있는데에비해 Blind SQL Injection 은참과거짓, 쿼리가참일때와거짓일때의서버의반응만으로데이터를얻어내는기술입니다. 즉, 쿼리를삽입하였을때, 쿼리의참과거짓에대한반응을구분할수있을때에사용되는기술입니다. 마치장님 (The blind) 이지팡이를이용하여장애물이있는지없는지를판단하는것처럼. Blind SQL Injection 은위두함수를이용하여쿼리의결과를얻어, 한글자씩끊어온값을아스키코드로변환시키고임의의숫자와비교하여참과거짓을비교하는과정을거쳐가며계속질의를보내어일치하는아스키코드를찾아냅니다. 그러한과정을반복하여결과들을조합하여원하는정보를얻어냄으로써공격을이루어지게하는것입니다. 많은비교과정이필요하기때문에악의적인목적을가진크래커들은 Blind SQL Injection 공격을시도할때에자동화된툴을사용하여공격합니다. 취약점이발견된다면순식간에많은정보들이변조되거나크래커의손에넘어가게됩니다.
0x03. Get db information from information_schema Mysql 의 information_schema 에는데이터베이스의여러정보들이들어있습니다. db 의모든테이블과컬럼의정보도있습니다. mysql 에서 information_schema 의모든테이블 위사진에서붉게네모친부분이각각 db 의모든테이블들과컬럼들의정보를 가지고있는테이블입니다.
tables 테이블에서모든정보를가져와보면, SELECT * FROM information_schema.tables 자신이접근할수있는모든 db 의테이블정보를볼수있습니다. 많은정보들이있지만테이블정보를얻을때에가장많이쓰이는것은 table_name 과 table_type입니다. 컬럼명처럼 table_name 에는테이블의이름, table_type 에는테이블의종류가들어있습니다. 일반적으로 db 관리자가테이블을만들게되면 table_name 은테이블명, table_type 는 base table 로지정됩니다. 공격자들은이를이용하여관리자가만든테이블의이름을알아내기도합니다. 저도이를이용하여 Blind SQL Injection 으로유저의정보를담고있는테이블명을 알아내도록하겠습니다. 취약한로그인폼에서의상황을예로들어보겠습니다.
위로그인폼은값을필터링없이 login_ck.php 에폼에입력된값을전송하고, login_ck.php 에서는 mysql 에연결하여 SELECT * FROM users WHERE id=' 전송받은값 ' AND pw=' 전송받은값 ' 쿼리를보내일치하는레코드를가져옵니다. 우선 information_schema에서가져올테이블명에대해알아보도록하겠습니다. SELECT table_name FROM information_schema.tables WHERE table_type='base table' LIMIT 0,1 쿼리를보내 table_type 가 base table인테이블중가장위에있테이블명을한개가져왔습니다. ( 결과값 : users ) Blind SQL Injection은이런결과값을 substr 함수를이용해한글자씩잘라서가져옵니다.
substr 함수로위결과값을한글자끊어오면 SELECT substr((select table_name FROM information_schema.tables WHERE table_type='base table'),1,1) 쿼리를보내 users 라는테이블명에서앞에서한글 자인 'u' 를반환하였습니다. ( 결과값 : u ) 이렇게잘라온글자를 ascii 함수를이용해아스키코드로변환합니다. SELECT ascii(substr((select table_name FROM information_schema.tables WHERE table_type='base table'),1,1)) 쿼리로위에서가져온 u 의아스키코드값 인 117 을가져왔습니다.( 결과값 : 117) 위와같은쿼리를인젝션하여가져온결과값아스키코드를임의의숫자와비교해가며그아스키코드를알아내어문자로반환하고각글자들을조합하여원하는데이터를알아내는것을 Blind SQL Injection 이라고합니다. 이제로그인폼에서위에서했던과정들을수행해보겠습니다. 먼저 admin 으로올바른 id 와 password를전송하여로그인하였을때 ( 참 ), 데이터베이스에있는레코드와일치하지않는 id 와 password 를보냈을때 ( 거짓 ) 의반응을보도록하겠습니다. 바른 id 와 password 를입력해레코드를가져오게되면
Hello,ADMIN 이라는문구와함께로그인이됩니다. 반면 ID 와패스워드가틀렸을경우에는아이디또는비밀번호가잘못되었다는팝 업창이뜨게됩니다. 이제 blind sql injection 으로테이블명을알아내겠습니다. id 와비밀번호를다입력할필요없이 admin'# 만입력해주어도쿼리가 SELECT * FROM users where id='admin'#' and pw='bulabula' 이되어초록색부분이주석이되기때문에 id='admin' 이라는조건에만일치하는레코드를가져와서 admin 으로로그인할수있습니다. 이를이용하여 id='admin' 조건뒤에 and 연산자와함께 ascii(substr((select table_name FROM information_schema.tables WHERE table_type='base table' limit 0,1),1,1)) 를삽입하면임의의숫자와비교하여참이면로그인성공, 거짓이면로그인에실패하게됩니다. 공격을시도해보겠습니다. 메모장에있는쿼리를 id 폼에삽입하였는데, 위쿼리가 참이면로그인에성공하고거짓이면로그인에실패하게됩니다. 로그인버튼을눌러 전송해보면,
로그인에성공하였습니다 ( 참 ). 그러므로결과값의첫글자의아스키코드는 120 미만 입니다. 결과값의첫글자의아스키코드가 115 미만인지비교. 로그인에실패하였습니다 ( 거짓 ). 결과값의첫글자의아스키코드는 115 이상입니다. ( 현재 115<= 첫글자아스키코드 <120) 결과값의첫글자의아스키코드가 117 미만인지비교. 로그인에실패하였습니다 ( 거짓 ). 결과값의첫글자의아스키코드는 117 이상입니다. ( 현재 117<= 첫글자아스키코드 <120)
결과값의첫글자의아스키코드 118 미만인지비교. 로그인성공. 결과값의첫글자의아스키코드는 118 미만입니다. 117<= 첫글자아스키코드 <118 이므로첫글자의아스키코드는 117 입니다. SELECT table_name FROM information_schema.tables WHERE table_type='base table' LIMIT 0,1 결과값의첫글자는아스키코드 117 에해당하는문자인 'u' 입니다.
이런방법으로참인지거짓인지비교하여한글자씩알아내면, 'users' 라는테이블명을알수있게됩니다. 이렇게 db 정보가노출이되면데이터들을조작하거나얻는것은시간문제입니다. 그렇기때문에위험성을파악하고보안에힘써야합니다.
0x04. WebGoat-Blind SQL Injection 이번에는웹고트의 Blind SQL Injection 문제를풀어보면서어떤식으로공격이 이루어지는지를확실히알아보도록하겠습니다. 문제 : The form below allows a user to enter an account number and determine if it is valid or not. Use this form to develop a true / false test check other entries in the database. Reference Ascii Values: 'A' = 65 'Z' = 90 'a' = 97 'z' = 122 The goal is to find the value of the first_name in table user_data for userid 15613. Put the discovered name in the form to pass the lesson. Only the discovered name should be put into the form field, paying close attention to the spelling and capitalization. 문제를요약하여해석하자면 user_data 테이블에서 userid=15613 을갖는레코드의 first_name 의값을알아내는것이목적입니다.
우선존재하는 userid와존재하지않는 userid를입력함에따른반응을비교해보도록하겠습니다. account number을입력하는폼에문제에서주어진 userid 인 15613을넣어주고전송하면, Account number is vaild ( 번호가존재합니다.) 라는문구가나옵니다. 임의의값을넣고전송하면 Invalid account number ( 번호가없습니다.) 라는문구가나옵니다. 쿼리가참일때와거짓일때각각 Account number is vaild, Invalid account number 라는문구가나오게된다는것을알수있었습니다. 이제 Blind SQL Injection 을시도해보겠습니다. 지금얻어야하는데이터는 user_data 테이블에서 userid=15613을갖는레코드의 first_name입니다. 그러므로 SELECT first_name FROM user_data WHERE userid=15613 의결과값을한글자씩잘라와서아스키코드로변환하여임의의숫자와비교하여데이터를얻으면됩니다.
존재하는 userid 의값인 15613 과함께 and 연산자, ascii(substr((select SELECT first_name FROM user_data WHERE userid=15613))) 쿼리를삽입하여임의의 숫자와비교하도록하겠습니다. 우선첫글자가소문자인지대문자인지확인하기위해 Z 의아스키코드값보다 1 이 큰 91 과비교해보면 Account number is vaild 라는문구가출력되었으므로참입니다. 첫글자의아스키코드는 91 미만이므로대문자입니다. ( 첫글자아스키코드 < 91 ) Account number is vaild 라는문구가출려되었으므로참. ( 첫글자아스키코드 < 80 )
Invalid account number 문구가출력되었으므로거짓. ( 70 <= 첫글자아스키코드 < 80) Account number is vaild 라는문구가출려되었으므로참. ( 70 <= 첫글자아스키코드 < 75)
Invalid account number 문구가출력되었으므로거짓. ( 73 <= 첫글자아스키코드 < 75) Invalid account number 문구가출력되었으므로거짓. ( 74 <= 첫글자아스키코드 < 75) 첫글자의아스키코드값은 74 이상 75 미만입니다. 그러므로첫글자의아스키코드값은 74입니다. 아스키코드 74에해당하는문자는 'J' 입니다.
위와같은방법으로계속공격해주게되면, 두번째글자의아스키코드는 111 이므로두번째글자는 'o'
세번째글자의아스키코드는 101 이므로세번째글자는 'e' 네번째글자의아스키코드는 115 이므로네번째글자는 's'
다섯번째글자의아스키코드는 115 이므로다섯번째글자는 'p' 여섯번째글자의아스키코드는 104 이므로여섯번째글자는 'h' 이렇게알아낸글자들을조합하면, first_name 의값은 'Joesph' 이됩니다.
인증성공. WebGoat 의 blind sql injection 문제풀이였습니다.
0x05. To be safe from this problem 문서를읽으시면서 Blind SQL Injection 공격이위험성에대해서도생각하실수있으셨을겁니다. Blind SQL Injection 공격으로부터안전해지기위해서는쿼리를변조할수있는문구가삽입되는것부터막아야합니다. 전달받은값을 db 와연동하는페이지가있다면전달받은값에서충분한필터링을거치게해야합니다. 정도를필터링하시면 db의정보가유출되거나조작되는것을막으실수있습니다. union, select, from, where, limit, or, and,, &&, (, ), <, >, insert, update, delete, create, drop 등 SQL 구문을감지하는패턴을만들어배열화시킨 $_REQUEST 시켜패턴과매치하면 SQL INJECTION을감지하여서버담당자가원하는동작을수행하도록하면간단하고, 효율적으로 SQL INJECTION 을방어할수있습니다. 또, 중요한것은쿼리에러가났을때에러에대한정보를보여주어서는안됩니다. 대부분이에러정보를바탕으로쿼리인젝션을시도하기때문이죠. 서버관리자분들이안전한서버관리를하실수있으시면좋겠습니다. - PRIDE -