[webhacking.kr] 문제풀이 No.18

박준서·2021년 10월 4일
0

webhacking-kr

목록 보기
6/7
post-thumbnail

[ webhacking.kr 사이트의 문제에 대한 풀이입니다. ]

시험 기간 동안 문제에 대한 풀이를 하나도 올리지 못하여 늦게나마 다시 올리기 시작한다. 이번 문제는 시험 전에 미리 풀어두었다가 풀이를 올리는 문제이다.

[ 풀이 ]


화면에 대놓고 sql injection을 시도하라고 써놓았으니 밑에 있는 소스를 통해 어떤걸 인젝션 해야하는지 확인해보자

들어가면 일반적인 php 소스코드가 보일 것이다.
위쪽의 html은 무시하고 바로 php 소스를 살펴보자.

<?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!";
  }
}
?>

우선 $_GET['no'] 부분은 no 값을 get 방식으로 가져온다.
그후 db에 연결하고, preg_match 함수를 통해 필터링을 실행한다.

preg_match 가 뭘까?
간단하게 설명하면 정규식을 통한 문자포함 확인 함수이다.
preg_match의 인자를 살펴보면
(정규식, 확인할 문자열, 매칭된 값을 저장할 변수) 인데,
이 때 확인할 문자열에 정규식의 패턴이 포함되어 있으면 이를 반환한다.

만약 preg_match 에서 걸린다면 "no hack"이라는 알림창을 만나게 될 것이다.

그 밑에는 db에서 sql 쿼리를 통해
id 는 guest이며, no=${우리가 입력한 숫자} 값이 일치하는 데이터의 id 를 가져오라고 명령을 내립니다.
이때 주석을 통해 admin의 no 값은 2라고 알려주고 있습니다.

그러나 밑에서 admin 인지를 확인하는 과정에서 id를 통해 확인하기 때문에 우리는 직관적으로 일반적으로 no 값에 2를 넣어 확인하면 안된다는 것을 알 수 있습니다.

그러므로 sql injection을 사용하여야 하는데, 이 때 우리는 앞의 and 문을 무시하기 위해서 or 을 사용하여
mysqli_query($db,"select id from chall18 where id='guest' and no=-1 or 2")와 같은 쿼리문을 만들어야 합니다.

no 값은 get으로 갖고 오기 때문에 주소창에 바로 적어서 보내면 되는데, 우리가 위에서 살펴본 필터링을 우회하기 위해 띄어쓰기는 모두 url encoding해서 보내야한다.

space의 url encoding 값은 %09이므로 띄어쓰기를 이로 모두 바꿔서 보내면 문제 주소 뒤에
?no=-1%09or%09no=2 과 같이 넣어 보낸다면 문제가 해결될 것이다.

마무리하며...

오랜만에 적은 글이라 너무 서두 없이 적은 것 같다. 조금 더 정리한 후에 글을 적을 필요가 있어보인다.

profile
학생 개발자의 블로그입니다.

0개의 댓글