[*] SQL Injection
SQL Injection은 웹 어플리케이션에서 일어나는 취약점 중에 가장 강력한 취약점 중 하나입니다.
PHP, JSP 등의 웹 프로그램에서 DB서버로 전달되는 쿼리를 특수문자(싱글쿼터, 백슬래쉬 등)를 이용하여
공격하는 것입니다.
<?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 "query : {$query}
"; $result = @mysql_fetch_array(mysql_query($query)); if($result['id']) solve("gremlin"); highlight_file(__FILE__); ?>
php소스를 보니 가장먼저 10번째 줄의 소스가 눈에 보인다.
if($result['id']) solve("gremlin");
php 소스에 대해 많이 알지 못하지만, 대충 추론해보면, "id의 결과가 있으면 gremlin이 풀린다."이런 의미 같다.
그러면 id만 맞으면 풀리는 건가? 생각할 찰나에 7번째 줄도 눈에 띈다.
$query = "select id from prob_gremlin where id='{$_GET[id]}' and pw='{$_GET[pw]}'";
쿼리문을 보면 id와 pw가 and로 되어있다. 결국 "내가 입력한 id가 참이고, 내가 입력한 pw가 참이어야 한다."
따라서 id만 입력한다고 되는것이 아니라 그에 따른 패스워드도 맞아야 된다.
이제 id와 pw에 아무 값이나 넣어보자.
id와 pw에 모두 hello값을 넣었다. 맞을리가 없으니 아무런 반응이 없다.
빨간 밑줄 부분에 where절을 보면, id='hello'이 참이고, pw='hello'이 참이여야 된다.
그러면 pw를 모르는 상태에서 pw를 참을 만들어야 된다는 말이다.
이때 sql의 가장 기본적인 구문을 써보자.
pw = 'hello'or'1'='1'
이렇게 입력해주면 pw는 'hello' 이거나, '1'='1'이라는 얘기가 된다.
pw가 'hello'가 아니라는것은 알고 있다. 하지만 or를 통해 뒷부분 '1'='1' 부분이 무조건 참이기 때문에 결과는 참이다.
따라서 pw를 몰라도 로그인이 가능해진다. 해당 값을 pw에 입력해보자.
GREMLIN Cear! 라는 문구가 출력되었다.
지금 사용한 sql 쿼리문은 sql 인젠션의 가장 기본적인 내용이다.
실제 모의해킹을 할때 sql injection이 적용되는가 테스트할 때 1'or'1'='1 이라고 입력을 해서 확인하기도 한다.
[또 다른 풀이]
<?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 "query : {$query}
"; $result = @mysql_fetch_array(mysql_query($query)); if($result['id']) solve("gremlin"); highlight_file(__FILE__); ?>
소스코드를 좀 더 자세히 살펴보면, config.php를 include하는 것을 볼 수 있다.
예상하기로는 config.php안에 login_chk()함수와 dbconnect()함수가 포함 되어 있을것 같다.
또한 preg_match()함수도 포함되어 있을 것이다. greg_match()함수는 문자열을 입력하면 검사해서 1 또는 0을 반환한다.
첫번째 풀이에서 말했듯이 "id의 결과가 있으면 gremlin이 풀린다."
따라서 id값만 넣고 pw 값을 넣지 않아도 결과를 가져올 수 있도록 우회하는 방법으로 풀어보겠다.
먼저 기초적인 url인코딩을 알고 시작하자. 싱글쿼터(')는 %27, 공백은 %20, #은 %23이다.
또, 오라클기반 주석처리는 '#', Mysql기반 주석처리는 '--'이다.
웹해킹을 공부하다 보면 자신도 모르게 알게된다.
id값은 admin을 넣고 pw값은 주석처리해보겠다. (보통 admin, administrator, master, webmaster 등.. 계정으로 공격한다.)
id값에 admin%27--%20 값만 넣었다.
id를 몰라도 첫번째 풀이에서 pw값을 무조건 참으로 만든것 처럼 id값을 무조건 참으로 만들어도 된다.
id값 : %27or%20%271%27=%271%27--%20 ('or '1'='1'-- )
※ 해당 문제는 id값이 admin이던 뭐든 값만 있으면 풀리는 문제이기 때문에 가능.