본문 바로가기
Web/Webhacking.kr

Webhacking.kr Challenge alien golf 문제 풀이

by jh117jh 2024. 3. 18.
728x90

 

이번 문제는 쿼리문이 2개로 이루어져 있다.

이런 문제 형태를 본 적이 있는데 블로그에 올려놨던

https://jh-hack.tistory.com/42

 

Lord of SQL Injection 25단계 (green dragon)

이번에 처치할 몬스터는 green dragon! 코드를 보면 이번엔 되게 특이한 문제다. 첫 번째 쿼리에서 id와 pw를 받고 id가 있으면 두 번째 쿼리가 작동되는 형식이다. 일단 싱글쿼터('), 더블쿼터(")가 필

jh-hack.tistory.com

 

Lord of sqlinjection 25단계도 비슷한 형태의 문제다.

하지만 문제의 조건은 다르므로 참고만 하면 될 것 같다.

우선 문제를 보면 1번 쿼리는 no파라미터를 숫자형태로 2번 쿼리는 문자열 형태로 쿼리문이 이루어져 있다.

또한 admin, if는 필터링되어 있다.

 

조건문은 

  1. 쿼리 1번의 출력값이 id='admin'이 아니면 sandbox1을 출력하고 종료
  2. 쿼리 1번의 출력값이 id='admin'이면 sandbox2를 출력하고 종료
  3. 쿼리 2번의 출력값이 id='admin'이면 sandbox를 출력하고 종료
  4. 쿼리 2번의 출력값이 id='admin'이면 no의 길이가 140byte보다 작으면 문제 해결

총 4개로 이루어져 있는데 처음에 뭔지 잘 이해가 안 되었다. 

1번과 2번 조건은 왜 존재하는지 + 3번과 4번 조건은 같은 조건에 다른 결과가 나오므로 

이게 무슨 문제인가 한참을 고민했다.

 

일단 id=admin이 쿼리의 출력값이 여야 하므로 

?no=1 or id=0x61646d696e을 입력해 본 결과

 

sandbox1이 출력되었고 이는 출력값의 id가 admin이 아니라는 걸 의미한다. 

여기서 힌트는 위에 lord of sql문제에서 얻을 수 있는데 해당 문제의 prob_alien테이블에 admin이라는 id가 저장되어 있지 않아 참인 쿼리문을 작성해도 출력되지 않는다는 걸 예상할 수 있다.

 

그래서 union을 이용하여 컬럼을 합쳐 id값을 만들 주면

?no=1 union select%200x61646d696e

 

 

sandbox2가 출력되면서 1번 쿼리문의 출력값 id가 admin인 것을 확인할 수 있다.

그러면 혹시 2번 쿼리문도 id가 admin인 출력값을 만들면 문제가 풀리지 않을까?라는 생각으로 쿼리문을 작성해 봤다.

 

' union select 0x61646d696e#' union select 0x61646d696e을 넣어

 

 

query : select id from prob_alien where no=' union select 0x61646d696e#' union select 0x61646d696e

 

query2 : select id from prob_alien where no='' union select 0x61646d696e#' union select 0x61646d696e'

(파란색 : 문자열, 초록색 : 주석, 빨간색 : 실행되는 union)

 

이러한 형태로 2번째 쿼리문도 id값이 admin이 출력되게 하였는데

 

실제로는 sandbox2가 출력되면서 1번 쿼리문만 admin인 것을 알 수 있다.

2번 조건문 (쿼리 1번의 출력값이 id='admin'이면 sandbox2를 출력하고 종료) 때문에 아래 조건이 실행이 되지 않고 종료되어 그럴 텐데

 

여기까지가 내가 혼자 풀어본 결과이다.

 

계속해서 바꿔보고 시도해 봤지만

1번과 2번 조건 때문에 admin이든 아니든 무조건 종료가 되기 때문에 도저히 저걸 무시하고 넘어가는 방법을 모르겠어서 구글에 검색을 해봤다.

 

처음 보는 방법이라 신기했다.

바로 쿼리값을 요청할 때마다 쿼리문을 변경하는 방법인데 처음 보고 나서 이 생각을 왜 못했지?라는 생각과 함께 진짜 창의력 싸움이구나라고 느꼈다.

 

조건문을 다시 보면 

  1. 쿼리 1번의 출력값이 id='admin'이 아니면 sandbox1을 출력하고 종료 -> admin O
  2. 쿼리 1번의 출력값이 id='admin'이면 sandbox2를 출력하고 종료        -> admin X
  3. 쿼리 2번의 출력값이 id='admin'이면 sandbox를 출력하고 종료          -> admin X
  4. 쿼리 2번의 출력값이 id='admin'이면 no의 길이가 140byte보다 작으면 문제 해결.  -> admin O

admin값만 변경하면 되므로 

0x61646d696e 

이 부분을 CONCAT(char(97+round(rand())),0x646d696e)으로 써주면 

 

rand함수는 0~1 사이 랜덤값을 생성해 주고 round함수는 반올림 함수로 round(rand())는 0 또는 1을 반환한다.

그러므로 char(97) 또는 char(98)이 반환되는데 이는 각각 문자 a와 b에 해당한다.

0x646d696e는 dmin이고 concat함수로 char함수와 합쳐주면 admin 또는 bdmin을 반환한다.

 

그럼 이제 쿼리값을 요청할 때마다 1/2 확률로 admin과 bdmin으로 요청값이 달라지는데

4가지 조건문을 다 맞추려면 1/8 확률이므로 몇 번 새로고침 하면 쉽게 나올 수 있다.

 

 

728x90