본문 바로가기
[웹해킹]/[Webhacking.kr]

[Webhacking.kr] 57번

by Hevton 2020. 11. 26.
반응형

600점짜리 문제

 

내가 좋아하는 SQL injection 문제

 

소스보기

<?php
  include "../../config.php";
  include "./flag.php";
  if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 57</title>
</head>
<body>
<?php
  $db = dbconnect();
  if($_GET['msg'] && isset($_GET['se'])){
    $_GET['msg'] = addslashes($_GET['msg']);
    $_GET['se'] = addslashes($_GET['se']);
    if(preg_match("/select|and|or|not|&|\||benchmark/i",$_GET['se'])) exit("Access Denied");
    mysqli_query($db,"insert into chall57(id,msg,pw,op) values('{$_SESSION['id']}','{$_GET['msg']}','{$flag}',{$_GET['se']})");
    echo "Done<br><br>";
    if(rand(0,100) == 1) mysqli_query($db,"delete from chall57");
  }
?>
<form method=get action=index.php>
<table border=0>
<tr><td>message</td><td><input name=msg size=50 maxlength=50></td></tr>
<tr><td>secret</td><td><input type=radio name=se value=1 checked>yes<br><br><input type=radio name=se value=0>no</td></tr>
<tr><td colspan=2 align=center><input type=submit></td></tr>
</table>
</form>
<br><br><a href=./?view_source=1>view-source</a>
</body>
</html>

 

preg_match 필터링부분에 benchmark가 있어서, Time - based Sql injection이라는 힌트가 주어진 것 같았다.

 

 

Time - Based SQL injection (시간 기반 SQL Injection)

 

쿼리의 결과값이 true이던 false 이던 그 결과를 화면에 출력하지 않아서 알아볼 수 없을 시에, 조건에 따라 시간을 멈춤으로써 경과한 시간을 가지고 쿼리의 참/거짓을 판단하는 방법이다.

 

대표적인 방법으로는

sleep(), benchmark(), 헤비쿼리 사용 등이 있다.

 

 

INSERT into 문에서 어떻게 하면 pw 컬럼에 들어가는 $flag 값을 확인해볼 수 있을지 생각해보다가, $_GET['se'] 부분에 if 조건식을 이용한 time - based sql injection을 시도하고자 해봤다.

se는 secret 유무에 따란 체크박스의 값으로 0 , 1만 전달될 수 있으나, 주소창을 건드리면 다양한 값을 전달할 수 있다.

 

아래 값을 입력해봤다.

se=if(3>0, sleep(1), 1)

참이면 1초 뒤에 쿼리가 응답되고 기본값이 se에 들어가겠으며, 거짓이면 se의 값으로 곧바로 1이 전달되어 쿼리가 바로 응답받을 것이다.

실행결과 1초 뒤에 Done 메세지창이 뜬다. 이 취약점이 성공했다는 것.

 

이를 응용하여 바로 패스워드값을 알아내보자

se=if(length(pw) = x, sleep(1), 1)

x의 값을 변화시키면서 1초뒤에 쿼리가 응답되는 경우를 찾으면 x = 24임을 알아낼 수 있다.

 

 

이제 프로그램을 이용해 비밀번호의 자리들을 확인해볼 것이다.

se=if(ascii(substr(pw, i, 1))=j, sleep(2), 1)

i는 자릿수 (1~24), j는 아스키코드값을 넣어보며 반복을 돌린다. 그리고 프로그램에서 검증하는 방식은 setReadTimeOut(2000) 등 타임아웃값을 주어서 쿼리의 결과가 참인지 거짓인지 판별한다. (위 함수는 JAVA 기준)

 

참고로 Brute Force 공격방식이므로 sleep을 너무 짧게 주고 타임아웃 값도 너무 짧게 주면, 인터넷 연결 문제 상 지연이 생기는 건지 아니면 쿼리 내에서 지연이 생기는 건지 판별할 수 없는 경우가 생기거나 인터넷이 다운될 수도 있으니 마음 느긋하게 갖고 적절히 여유있는 값을 주고 다른 할 일을 하다 보면 문제가 풀려있을 것이다.

FLAG{y2u.be/kmPgjr0EL64}

 

반응형

'[웹해킹] > [Webhacking.kr]' 카테고리의 다른 글

[Webhacking.kr] 59번 + 멀티 바이트 취약점 정리  (0) 2020.11.28
[Webhacking.kr] 58번  (0) 2020.11.27
[Webhacking.kr] 56번  (0) 2020.11.25
[Webhacking.kr] 55번 & 나중에 다시 보기  (0) 2020.11.24
[Webhacking.kr] 54번  (0) 2020.11.23