김승현
[webhacking.kr] old-07 7번 문제 write up 본문
7번 문제에 접속해보면 admin page라고 뜨고 auth라고 적힌 버튼이 하나 있고 밑에는 소스를 보는 링크가 있다.
여기 주소를 보면 val이라는 파라미터가 처음부터 주어져 있는 걸 볼 수 있는데 저걸 활용해서 푸는 문제인 것 같다.
auth 버튼을 누르면 access_denied! 뜬다. 소스코드를 확인해 보자.
<?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>
중요한 부분만 대충 보고 넘어가겠습니다.
$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!");
$go에 파라미터인 val을 get 형식으로 저장합니다.
만약 $go가 없거나 0이면 index.php?val=1으로 이동시킵니다.
echo=는 그냥 페이지 출력 내용입니다.
$go에 2, -, +, from, _, =, \s, *,\, 공백을 띄어쓰기 없이 검사하고 포함되어 있다면 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!");
}
db를 연결하고 $rand에 1부터 5까지 랜덤한 값을 저장합니다. rand에 1~5의 값이 들어가 있으면
select lv from chall7 where lv=($go)의 쿼리를 $result로 보내고 nice try!를 출력하는데
rand가 1이면 $go에 한 개의 괄호가 감싸지고 5면 다섯 개의 괄호가 감싸집니다.
ex) rand = 1 → ($go) rand = 2 → (($go)) . . rand = 5 → ((((($go))))) |
$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);
}
전달된 val을 기준으로 나뉘는 것 같습니다.
val = 0 query error 출력
val = 1 access denied! 출력
val = 2 hello admin 출력과 solve
val에 2의 값을 보내야 되는데 2, -, +, from, _, =, \s, *,\, 공백 이런 것들 없이 넣어야 됩니다.
그렇다면 5%3을 이용해보겠습니다. %는 나머지를 나타내는데 5/3을 하면 2가 남기에 2가 전달되는 방식입니다.
( 같은 원리로 5%3 말고 8%3을 해도 2가 전달됩니다. )
이렇게 val에 5%3으로 우회해서 전달했더니 query error가 떴습니다. query error는 go가 0일 때 뜨는 문장이었습니다.
왜인지는 모르겠지만 다른 방식으로 입력해야 될 것 같은데 db를 사용하기도 했고 union을 이용해보겠습니다.
일단 들어가기 전 union에 대해서 간단히 설명을 드리자면 union이란 sql에서 여러 쿼리문을 합쳐주는 것입니다.
select lv from chall7 where lv=($go)
원래 쿼리문은 이렇게 생겼습니다. 근데 여기에 111)union(select(5%3) 이 내용을 입력하면
select lv from chall7 where lv=(111)union(select(5%3))
이런 식으로 쿼리문이 완성이 됩니다. 문제에선 val은 0, 1, 2에 대해서만 정의가 되어 있어서 0,1, 2 이외 없을만한 숫자를 앞에 입력해주고 2에 해당하는 테이블과 union을 시키면 앞에는 데이터가 없기 때문에 val = 2에 해당하는 내용만 저장이
되기 때문에 문제를 해결할 수 있습니다. 위의 값을 val 파라미터에 입력해보겠습니다.
입력했는데 nice try!가 떠서 당황할 수도 있는데 사실 당연한 결과입니다! 앞서 코드에서 rand는 1~5의 값을 가지고 거기에
따라 $go를 감싸던 괄호의 개수가 달라졌는데 우리가 작성한 쿼리문은 rand = 1에서만 유효하기 때문에 nice try가 뜹니다.
여러 번 새로고침을 하다보면
이렇게 문제를 해결할 수 있습니다.
'Web > webhacking.kr' 카테고리의 다른 글
[webhacking.kr] old-09 9번 문제 write up (0) | 2023.03.31 |
---|---|
[webhacking.kr] old-08 8번 문제 write up (0) | 2023.03.29 |
[webhacking.kr] old-06 6번 문제 write up (0) | 2023.03.11 |
[webhacking.kr] old-05 5번 문제 write up (0) | 2023.03.09 |
[webhacking.kr] old-04 4번 문제 write up (0) | 2023.03.09 |