드디어 밀린 문제 풀이를 올립니다. 요즘 새로운 문제 푸는 게 손에 잡히지 않아서 복습도 할 겸 밀린 문제 풀이를 올려야겠네요! 이번 문제는 기초 SQL Injection 문제입니다. 문제를 열어보면 아래와 같은 화면을 보실 수 있습니다.
SQL Injection 문제가 대부분 admin으로 로그인하는게 목표이므로 이 친구도 admin으로 로그인하면 풀릴 거라 쉽게 예상할 수 있습니다. 일단 view-source를 클릭해서 소스코드를 확인해보겠습니다.
<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 18</title>
<style type="text/css">
body { background:black; color:white; font-size:10pt; }
input { background:silver; }
a { color:lightgreen; }
</style>
</head>
<body>
<br><br>
<center><h1>SQL INJECTION</h1>
<form method=get action=index.php>
<table border=0 align=center cellpadding=10 cellspacing=0>
<tr><td><input type=text name=no></td><td><input type=submit></td></tr>
</table>
</form>
<a style=background:gray;color:black;width:100;font-size:9pt;><b>RESULT</b><br>
<?php
if($_GET['no']){
$db = dbconnect();
if(preg_match("/ |\/|\(|\)|\||&|select|from|0x/i",$_GET['no'])) exit("no hack");
$result = mysqli_fetch_array(mysqli_query($db,"select id from chall18 where id='guest' and no=$_GET[no]")); // admin's no = 2
if($result['id']=="guest") echo "hi guest";
if($result['id']=="admin"){
solve(18);
echo "hi admin!";
}
}
?>
</a>
<br><br><a href=?view_source=1>view-source</a>
</center>
</body>
</html>
GET 방식으로 no 값을 받고 no값에서 select, from, & 등 몇가지 문자에 대해서 필터링을 해주고 해당 문자가 아닐 경우
select id from chall18 where id='guest' and no=입력값
위와 같은 쿼리문을 서버에 보내서 result에 담고 result['id']가 admin일 경우에 문제가 풀리는 코드입니다. 친절하게 admin은 no=2라고 주석에 적혀있네요!
일단 where 조건으로 id가 guest로 고정되어 있으니 이 부분부터 거짓으로 만들어 조건 값을 초기화 시켜줘야겠습니다. no=2가 admin이라는 걸 알았으니 일단 아래처럼 첫 입력값으로 2를 넣어서 조건 값을 초기화시켜줍니다.
select id from chall18 where id='guest' and no=2
파란 부분(id='guest')과 초록 부분(no=2)에 해당하는 값은 존재하지 않아 거짓이 되면서 결과값으로 아무런 값도 반환되지 않습니다. 그럼 이 상태에서 어떻게 admin id를 결과 값으로 반환시킬 수 있을까요? 간단합니다. 입력값 뒤에 새로운 조건을 넣어주면 됩니다.
select id from chall18 where id='guest' and no=2 or no=2
취소선 부분은 앞에서 거짓 처리되는 것을 확인했으니 where 부분을 새로 해석해보면 FALSE or no=2 가 됩니다. 이를 다시 해석하자면 아래와 같은 쿼리문이 서버로 날아가겠죠
select id from chall18 where no=2
그리고 아까 코드 주석에서 admin의 no값은 2라고 친절하게 설명해줬으니 결과값에 result에 admin이 들어갈 거고 문제가 풀려야 합니다만.. 코드를 살펴보면 '공백'에 대한 필터링이 존재합니다. 그렇다고 입력값을 다 붙여 쓴다면 or를 인식하지 못하죠. 결국 '공백'과 같은 효과를 주면서 '공백'이 아닌 문자를 넣어줘야 합니다. 예를 들면 LF(LineFeed) 같은 문자가 있죠. 이제 LF를 입력값에 넣고 넘겨주기만 하면 됩니다. 다만 일반적인 입력방식으로는 LF를 넘기는 건 불가능하니 ASCII 코드를 이용하기로 합니다. 그럼 아래와 같은 쿼리문이 서버에 날아가겠죠
select id from chall18 where id='guest' and no=2%0aor%0ano=2
그럼 아래와 같이 admin으로 로그인된 것을 확인할 수 있습니다. 끝!
'Web Hacking > Webhacking.kr' 카테고리의 다른 글
[Webhacking.kr] old-19 (0) | 2019.12.02 |
---|---|
[Webhacking.kr] old-10 (0) | 2019.10.29 |
[Webhacking.kr] old-06 (0) | 2019.10.29 |
[Webhacking.kr] old-54 (0) | 2019.10.22 |
[Webhacking.kr] old-26 (0) | 2019.10.22 |