티스토리 뷰

728x90
반응형

$_GET[id]
$_GET[pw]

PHP 소스코드 상으로는 아이디와 패스워드를 GET parameter 방식으로 받는다고 한다.

 

 if(preg_match('/prob|_|\.|\(\)/i', $_GET[id])) exit("No Hack ~_~");
 if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");

그리고 아이디와 패스워드 모두에 prob 라는 단어가 포함되어 있거나, _(언더바), .(온점), ((여는 괄호), )(닫는 괄호) 를 사용하는 것을 금지하고 있다.

 

$query = "select id from prob_gremlin where id='{$_GET[id]}' and pw='{$_GET[pw]}'";
echo "<hr>query : <strong>{$query}</strong><hr><br>"; // 화면에 입력한 쿼리 출력함
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if($result['id']) solve("gremlin");

query 변수에 GET parameter로 전달받은 아이디와 패스워드를 넣고, mysql에 query를 실행해봤을 때 결과로부터 id 가 참값(true)일 때 문제는 해결이 된다.

 

이 문제를 해결할 수 있는 방법은 두 가지가 있을 수 있겠다.

첫 번째, 실제로 데이터베이스 테이블(prob_gremlin)에 존재하는 아이디(id)를 찾아냈을 경우

두 번째, 결과값을 그냥 참(true)값으로 만드는 경우

 

당연히 첫 번째 방법은 query 구문을 봤을 때 실제로 존재하는 id와 pw를 입력해야만 가능한 것이니깐, 거의 불가능하다고 생각하고, 두 번째 방법이 가장 유력한 방법이겠다.

 

select * from table where id = '0' and pw = '0' or 1;

위 구문은 뒤의 or 1 덕분에 무조건 참이 되는 query 구문이다. id와 pw가 뭐가 들어갔던 간에 어쩌피 마지막의 or 1 때문에 참이 된다. 그렇기 때문에 select 구문에서는 모든 record를 찾을 때마다 where 구문의 조건에 부합되는 항목을 찾아서 출력해줄 것인데, where 구문의 조건이 무조건 참이기 때문에, 그냥 일반적으로 모두 조회하는 것과 다를바가 없게 된다.

 

그래서 간단히 아래와 같이 구문을 완성하면 문제를 해결할 수 있겠다.

select id from prob_gremlin where id='' and pw='' or 1#'

 

pw 에 ' or 1# 이라고 입력하게 되면, #은 주석처리를 의미하므로, 뒤의 '(작은따옴표)는 주석처리 되고, 앞의 ' or 1 로 인해 무조건 참(true)값이 되는 것이다. 물론 ' or 1# 이것을 굳이 pw 에 넣을 필요 없이 id에 넣어도 된다.

 

https://los.rubiya.kr/chall/gremlin_1.php?pw=' or 1%23

URL 파라미터는 위와 같이 입력해주면 된다. %23 은 URL 디코딩하면 # 이다. URL에서 #을 인코딩안하고 넣게 되면, 브라우저는 id를 가리키는 hash tag로 해석하기 때문에 반드시 인코딩 해줘야 한다. 작은 따옴표는 알아서 인코딩해준다.

 

 

그럼 위와 같이 문제를 풀 수 있게 된다. 위 방법 말고도 수많은 다양한 방법으로 문제를 해결할 수 있다. 다양한 방법으로 다양한 문제풀이를 해보는 것도 좋을 것 같다.

 

 

- 끝 -

728x90
반응형
댓글