Web Hacking/LOS

Lord of SQL Injection - alien

Lucvs 2021. 10. 2. 09:00

query가 두 개 존재하는 문제이다. 잘 보면 위쪽 query 는 no 값에 아무런 quotation 이 사용되고 있지 않다. 반면에 아래의 query2는 single quotation 이 사용된 모습이다. 

 

먼저 두 개의 query를 동시에, 동일한 query로 만들어주어야 할 것이다. 싱글쿼터와 주석을 잘 활용하면 될 것 같다. 다음과 같이 작성해보자.

 

no=1 union select 1#' union select '1

결과는 아래와 같다.

query   : select id from prob_alien where no=1 union select 1#' union select '1
query2 : select id from prob_alien where no='1 union select 1#' union select '1'

 

모두 동일하게 'union select 1'을 갖게 된다. 이제 다음 코드라인들로 넘어가보자. 여기서부터가 중요한 문제이다.

 

코드를 순차적으로 보면 상당히 모순적인 것처럼 보인다. 첫 번째 fetch 에서는 id가 admin이 아니면 exit 된다. 이후 두 번째 fetch에서는 id가 admin이면 exit 된다. query2에서는 약간 다르지만 비슷한 양상이다. 결과적으로 각 부분에서 fetch가 될 때마다 필요한 id 값은 다음과 같다.

 

  1. admin
  2. not admin
  3. not admin
  4. admin

 

우리는 concat 함수를 이용하여 id 값이 admin이 될지, bdmin이 될지 결정할 것이다. char 함수의 인자에 'a'에 해당하는 아스키코드 값 '97'을 넣어준 뒤에 그 뒤에 합연산을 한다.

 

여기서 sleep 함수를 넣어주었는데, now 함수는 현재 시스템 시간을 반환하는 함수이기 때문에,

 

!sleep(1)&&(now()%2=1)

 

값이 0 또는 1이 나오기 위해서는 1초의 sleep이 필요하다. sleep 함수는 정상적으로 잠에 들 경우 '0'을 반환한다. 따라서 AND 연산의 대상으로는 적합하지 않기 때문에 이 앞에 NOT 연산을 해줌으로써 정상적으로 수행될 경우에 !sleep(1)은 '1'을 반환하게 된다. 

 

또한 쿼터 문자에 잡혀있는 query 문은 실행되지 않는 그저 문자열밖에 되지 않는 존재이다. 이 점과 query, query2 의 특징을 분석하여 시스템 시간이 짝수일 때, 홀수일 때의 경우를 각각 차근차근 계산해보면, query2가 받는 query문 부분에서 기존의 now()%2=1 이 아닌 now()%2=0 이 되어야 한다는 것을 알 수 있다.

 

 

결과적으로 payload는 다음과 같다.

no=1 union select concat(char(97%2b(!sleep(1)%26%26(now()%2=1))),"dmin")%23' union select concat(char(97%2b(!sleep(1)%26%26(now()%2=0))),"dmin")%23

꽤나 rough 하고 흥미로운 문제였다. -_-