웹/LOS

LOS # darknight

묘나 2021. 3. 16. 20:51
728x90
반응형
SMALL

쿼리문!

query : select id from prob_darkknight where id='guest' and pw='' and no=

 

코드 분석 go 

 


<?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|=/i'$_GET[no])) exit("HeHe"); 

// 필터링을 여러 가지 해주고 있다.

$_GET[no] -> substr, ascii, ', =

$_GET[pw] -> '


  
$query "select id from prob_darkknight where id='guest' and pw='{$_GET[pw]}' and no={$_GET[no]}"

// pw와 함께 새롭게 등장한 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>"

// 참인 조건이 들어가면

Hello {$result[id]} 이 출력된다.

-> Blind SQL Injection 인가...? 생각해볼 수 있음

   
  
$_GET[pw] = addslashes($_GET[pw]); 

// $_GET[pw]에 저장된 입력받은 pw는 addslashes() 함수를 거친 후 다시 저장된다.


  
$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"); 

// 이미 정해진 pw과 입력한 pw가 같아야 문제가 해결됨!

이전의 문제들처럼 역시 Blind SQL Injection을 이용해서 pw를 구하는 문제인 것 같다!


  
highlight_file(__FILE__); 
?>

 

 

<addslashes() 함수>

 

: 문자열을 데이터베이스의 필드값으로 저장하기 전에 사용하는 함수

 

만약 그 문자열에 특수 문자 (ex : ', ", \ 등..) 가 포함되어 있다면,

이러한 문자 앞에 \ 를 붙여주는 작업을 수행한다.

 

특수 문자에 \ 가 붙어, 데이터베이스의 필드값을 저장되면 그 특수 문자가 순수한 하나의 문자로 인식되어 저장된다.

 

만약 이 addslashes() 함수를 사용하지 않고 특수 문자가 포함된 문자열을 저장하게 되면,

그 특수 문자가 하나의 일반적인 문자가 아닌, 특수 문자로 인식되어

오류를 일으키거나 잘못된 결과를 도출하게 될 수 있다.

 

즉, PHP -> DB 연동에 중요하게 쓰이는 함수

사용 형식

: addslashes($string)

 

-> 예제

$string = "안녕...'사랑'...'행복'";

&add_string = addslashes($string);

echo("$add_string <br>");

 

-> 실행 결과안녕...\'사랑'\...\'행복'\

 

* 참고로

addslashes() 와 반대되는 역할을 하는 함수 

: stripslashes()  

 

 

 

 

이제 대충 분석을 끝냈으니 pw를 구해보자.

먼저 pw의 길이부터 구해야한다.

 

pw에는 아무 값도 넣지 않아도 된다.

no에는 그냥 1을 넣어줬다.

' 을 필터링하고 있으므로 그냥 숫자를 넣어줬다.

 

id가 'admin'일 경우의 pw를 구하는 것이므로, id에 대한 조건도 입력해준다.

=을 필터링하고 있으므로 like를 써주고,

char() 함수를 사용해 id에 'admin'을 넣어준다.

 

char('admin'의 아스키값) -> char() 함수에 의해 'admind'으로 변환되어 인식된다.

char(97,100,109,105,110)

 

 

length()함수를 이용해 pw의 길이를 구해줬다.

역시 이번에도 길이는 8이었다..

 

<ord() 함수>

 

: 문자열의 첫 번째 문자에 해당하는 아스키코드를 반환하는 함수

문자 -> 아스키코드로 변환

 

사용 형식

: ord(문자열)

 

* 참고로

ord() 와 반대되는 역할을 하는 함수 

: char()  

-> 아스키코드를 문자로 변환한다.

 

 

이제 pw 8개를 각각 구해보자.

이 문제에서는 필터링하고 있는 요소들이 매우 많아서 이를 다 우회해줘야 한다.

 

지금까지 사용했던 방법&우회를 대충 정리해보면,

 

#orge에서는

ascii(), substr() 사용

2myona.tistory.com/82

 

Lord of SQL Injection # orge

query : select id from prob_orge where id='guest' and pw='' 쿼리문은 이렇게 나와있다. pw를 찾으면 되는 문제인듯! php코드이구... 코드를 일단 간단하게 분석해보쟈.

2myona.tistory.com

 

 

#golem에서는

ascii(), substr() 대신 -> right() + left() 사용

2myona.tistory.com/93

 

LOS # golem

쿼리문! query : select id from prob_golem where id='guest' and pw='' 코드를 분석해보자.

2myona.tistory.com

 

그런데 이 문제에서는 여기서 더 진화해 ascii까지 막아놨다.

ascii() -> ord()/hex() 

두가지 방법으로 우회를 할 수 있다.

 

나는 ord()를 사용할것이다.

 

그리고, 이번에는

substr() 대신 -> mid() 함수를 사용해주자.

mid() 함수는 substr() 함수 대신 사용해 줄 수 있는 동일한 기능을 가진 함수이다.

 

 

 

<substr(), mid(), substring() 함수>

 

사용 형식

: 함수(문자열, m, n)

 

-> 문자열에서 m으로부터 n 길이만큼의 문자를 출력

 

m이 0이나 1이면 문자열의 첫글자를 의미

n이 생략되면 문자열의 끝까지를 의미

m이 음수이면 뒤쪽 방향으로부터의 위치를 의미

 

 

 

이제 함수들을 이용해서 pw를 하나씩 앞에서부터 구해보자.

이런식으로 써주자.

?no=1||id%20like%20char(97,100,109,105,110) and ord(mid(pw,1,1))<50%23

 

 

++ '='을 필터링해주는 like을 이용해 한번 더 확인해 볼 수 있다.

나는 8개 중에 하나를 잘못 찾은 것인지 계속 문제 해결이 안되길래 밑의 방법으로 한번씩 다시 확인을 해주었다.

그러니 틀린 것을 찾아낼 수 있었다..!

위와 같은 식으로 찾은 pw를 이제 문자로 변환해서 입력해주면 된다.

 

48 -> 0

98 -> b

55 -> 7

48 -> 0

101 -> e

97 -> a

49 -> 1

102 -> f

 

0b70ea1f

 

 

 

해결!

 

 

 

 

728x90
LIST