공격 백터는 id와 pw가 있으며, select id,pw from prob_green_dragon where id='{$_GET[id]}' and pw='{$_GET[pw]}'에 사용이 된다. 똑같은 쿼리문이 2개가 작동하는데 첫번째 쿼리문의 id 결과 값이 있어야만 두번째 쿼리문이 작동되는 시스템이다.
id와 pw에 대한 검증은 prob, _, ., ', "이 필터링 되는 거 빼곤 없다. 그래서 일단 문자형 데이터를 삽입할 땐 hex값으로 넣어야 할 것으로 판단된다.
나는 id를 admin으로 만들어주기 위해 /**/를 사용하여 id=‘/*’ and pw=‘*/admin’이라는 쿼리문을 생각했지만, /**/은 ’, “ 안에서 사용 시 문자열로 인식되어 주석처리가 되지 않는다.
다른 방법으로 \를 사용하여 where절의 id을 ‘\’ and pw=‘로 만들어서 SQLI를 시도해봤다. 결과는 DB 안에 id가 admin인 데이터는 없는 것으로 나왔다.
다른 데이터는 있을까? 하여 1=1를 이용하여 출력해봤지만 결과는 출력되지 않고 있다. green_dragon 테이블 안에는 데이터가 없는 것으로 생각이 든다.
나는 Union을 이용하여 값을 넣어보기로 하였다.
첫번째 쿼리문의 id 결과가 admin이 반환되어 두번째 쿼리문이 출력되는 모습을 볼 수 있었다. 굳이 id의 결과가 admin일 필요는 없지만 편의상 admin을 반환시켰다.
이제 두번째 쿼리문을 해결을 해야하는데 머리가 아프다….
어차피 두번째 쿼리문도 첫번째 쿼리문처럼 값을 넣어줘야함으로 첫번째 쿼리문의 id 결과 값이 \으로 출력되겠끔 변경하여 값을 넘겨주었다. 이렇게 하니 훨씬 생각하기가 편해졌다.
두번째 쿼리문의 where절 pw에 들어가야하는 값은 UNION SELECT 0x61646d696e#이 들어가면 될 것 같았다. 하지만 첫번째 쿼리문에서 이를 인식하여 이상한 쿼리문이 만들어졌다.
첫번째 쿼리문에서 UNION SELECT 0x61646d696e#을 두번째 쿼리문에 넘기는 방법을 생각해봤지만 몇 시간을 고민 끝에 방법을 못 찾았다.
결국 다른 사람의 풀이를 참고하였는데, 아주 간단하였다.
방법은 Hex값으로 인코딩하여 넘겨주는 것이였다.
해당 방법대로 해보니, 문제를 클리어할 수 있었다.
왜 그런가 확인을 해보니, Hex값으로 넘겨주면 첫번째 쿼리문은 UNION SELECT 0x61646d696e# 문자열로 인식되고, 두번째 쿼리문는 UNION문으로 인식되는 것이였다.