워게임

Lord of SQL Injection - 4번 문제풀이

풉키홍키 2023. 1. 2. 23:50

[4번 문제 - orc]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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__); 
?>
cs

해당 문제는 아직 나에겐 어려웠던 문제였다.. (다른 블로그를 보고 정답을 알아냈다.)

이 문제는 Blind SQL Injection 문제였다.

 

입력되는 pw 값($_GET['pw'])과 저장된 pw의 값($result['pw'])이 일치해야 문제를 풀 수 있는 문제여서 Blind SQL Injection 문제겠구나 싶었는데, 그 이후의 방법이 잘못되어서 고생도 하고 삽질도 엄청나게 했다.

 

[기존 구문]

select id from prob_orc where id='admin' and pw='{$_GET[pw]}'

 

[확인 구문]

pw 파라미터 : ' or 1=1#

 

pw 파라미터의 값을 ' or 1=1# 로 할 경우 Hello admin 이란 글자가 출력되고, 조건문이 거짓이면 글자가 출력되지 않는다.

그래서 참/거짓의 구별이 확실해 Blind SQL Injection 문제라고 감을 잡을 수 있다.

이제 문제를 풀기 위해서 알아야하는 함수가 있는데 바로 length 함수다 (난 이렇게 푸는 방법을 생각해내지 못했다..)

length 함수를 이용해서 pw의 길이를 알아낼 수 있다.

 

[패스워드 길이 확인 구문]

pw 파라미터 : ' or id='admin' and length(pw)=1#

 

id가 admin인 계정의 비밀번호의 길이를 알아내야 하기 위해 id='admin' 이라는 조건을 추가하고 and 구문으로 pw의 길이를 변경해가면서 몇 글자인지 알아 낼 수 있다.

 

답은 8글자이다.

 

[패스워드 확인 구문]

pw 파라미터 : ' or id='admin' and ascii(substr(pw,1,1))<97#

 

위와 같이 id가 admin인 계정의 pw 글자를 한 글자씩 알아내서 정답을 알아낼 수 있다.

pw의 첫 번째 문자부터 첫 글자가 아스키 코드 값으로 97보다 작은지 확인하는 구문이다.

= 로 확인하면 너무 오래걸리니 부등호(>, <)로 확인하면 그나마 시간을 줄일 수 있다.

가장 좋은 방법은 파이썬 코드같은 걸 이용해서 자동으로 Blind SQL Injection을 해주는 도구를 사용하는게 제일 편하다.

첫 번째 글자를 알아냈으면 두 번째 글자부터는 substr(pw,2,1) 로 변경해 가면서 8글자의 pw를 알아 낼 수 있다.

 

[문제 풀이 구문]

https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?pw=095a9852