✏️ Check
가장 첫 페이지는에서는 auth(인증)버튼과 소스코드 링크가 첨부되어 있다.
이 상태 그대로 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>
소스코드는 위와 같다.
🔎 Analyze
📑 소스코드 분석
$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!");
}
$go 변수의 값이 sql 구문에 그대로 들어가면서 SQL Injection 취약점이 발생할 수 있게 된다.
하지만 $go의 값에 '2', '-', '\+', 'from', '=', '\\s', '\*', '\//i' 이 포함되어 있다면 접근할 수 없도록 필터가 설정되어 있다.
쿼리가 정상적으로 실행된다면 $result에 쿼리의 결과값이 저장되지만, 제대로 실행되지 않았다면 "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);
}
위에서 $result의 값을 읽어오면, 쿼리가 실행된 결과가 result에 저장되고 data[0] 즉, 사용자가 입력한 $go의 값이 2를 나타낼 경우 문제가 해결되도록 되어 있다.
필터링이 걸려있기 때문에 '3-1', '1+1' 등의 수식을 이용해서는 2를 표현할 수 없다.
그래서 사용해야 하는 것이 'union' 구문이다.
[SQL] union 구문
여러 sql 구문을 연결하여 실행할 수 있도록 한다.
따라서, 원래의 SQL 구문을 닫아주고(")"), union 문을 통해 2가 수행될 수 있도록 한다. 마찬가지로 2를 직접적으로 표현하거나 수식을 이용할 수는 없으므로, 아스키 코드를 이용하도록 한다.
🔓 Exploit
이 때 같은 쿼리를 실행하더라도 rand의 값이 1이 아닌 경우에는 괄호의 쌍이 맞지 않기 때문에 해결되지 않을 수 있다.
여러 번 새로고침하다보면 rand 값이 1이 되는 경우에 문제는 해결된다.
'Web > Web Hacking (Wargame)' 카테고리의 다른 글
[webhacking.kr] old-14 (1) | 2023.01.29 |
---|---|
[webhacking.kr] old-10 (0) | 2023.01.24 |
[webhacking.kr] old-05 (0) | 2022.12.22 |
[webhacking.kr] old-06 (0) | 2022.12.21 |
[webhacking.kr] old-02 (0) | 2022.12.17 |