김승현

[Lord Of SQLInjection] orge 7번 문제 write up 본문

Web/Lord Of Sql

[Lord Of SQLInjection] orge 7번 문제 write up

kshind 2023. 3. 14. 14:54

접속 화면은 이렇게 생겼다. 코드를 자세히 살펴보자.

 include "./config.php"; 
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~"); 
  if(preg_match('/or|and/i', $_GET[pw])) exit("HeHe");

첫 번째 줄은 ./config.php를 포함한다는 내용이다.

두 번째 줄은 login을 했는지 확인하는 내용이다.

db에 연결하고

preg_match내용은 필터링을 하는 내용이다. 

필터링 내용

no hack
    1. prob
    2. _
    3. .
    4. (
    5. )
HeHe
    1. and
    2. or
/i 내용은 대소문자를 구분하지 않는다는 내용이다.
 $query = "select id from prob_orge where id='guest' 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 {$result[id]}</h2>";

첫 번째 줄은 $query = select id from prob_orge where id='guest' and pw='{$_GET[pw]}'을 저장한다.

두 번째 줄은 $query에 저장된 내용을 강조해서 출력해주는 내용이다.세 번째 줄은 $result에 my_sql에서 db와 query를 연결해서 저장하는 내용이다.네 번째 줄에선 만약 result의 id가 존재하면 Hello {result[id]}의 내용을 출력한다.

 $_GET[pw] = addslashes($_GET[pw]); 
  $query = "select pw from prob_orge where id='admin' and pw='{$_GET[pw]}'"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("orge"); 
  highlight_file(__FILE__);

pw 파라미터를 get 방식으로 가져와서 addslashed 함수에 집어넣어 저장한다.

(addslashes함수란 데이터베이스 쿼리에서 처리가 되는 문자 앞에 \(백슬래시)를 붙인 문자열을 붙이는 함수이다.)

$query에 select pw from prob_orge where id='admin' and pw='{$_GET[pw]}'를 저장한다.

$result에 다시 한 번 my_sql의 db와 query를 연결해서 저장한다.

만약 pw가 존재하고 pw가 사이트에서 입력한 pw와 일치하면 orge 문제가 풀리는 방시깅다.

젤 아래 highlight_file의 경우 PHP 구문 파일을 강조하여 출력하는 그런 함수이다.

addslashes 함수의 경우 그냥 \t와 같이 escape 문자를 이용해서 우회하고 blind sqli로 문제를 해결하면 될 것 같다.

이렇게 pw의 길이를 8자리로 하면 hello admin이라면서 admin으로 로그인 되는 걸로 봐선 admin의 password의 길이가

8자리인 것을 볼 수 있다. ascii와 substr을 이용해서 password를 알아보자.

이렇게 ascii(substr(pw,1,1))<70과 같이 전송하면 pw 첫 번째 자리가 ascii문자로 70보다 작냐고 물어볼 수 있습니다.

55에서는 이렇게 뜨지 않지만

56에선 hello admin이 뜨는 걸로 봐선 첫 번째 자리는 55, 즉 7을 의미하는 것을 알 수 있습니다. 

다음 자리는 ascii(substr(pw,2,1))과 같이 바꿔가면서 여덟자리를 모두 알아내면 7b751aec라는 값을 얻을 수 있습니다.