본문 바로가기
작업/Webhacking.kr

webhacking.kr old-18 이해하기

728x90

 

 

 

 

old-18 페이지는 "SQL INJECTION" 이름을 가지고 있습니다.
아래에 "view-source" 링크가 있습니다. 새 탭을 열고서 링크를 들어갔습니다.



소스코드 분석

 

 

색 표시가 되어있는 php 구문이 이번 문제의 핵심입니다.
db가 언급되는 것으로 보아 데이터베이스를 다루는 것이며, 사용자 정보가 저장된 것으로 생각됩니다.


페이지의 제목이 SQL INJECTION인 만큼 정보를 알아낼 수 있는 SQL 삽입을 통해서
데이터베이스에 비정상적 동작을 하도록 유도하는 것이 문제 해결의 실마리입니다.


이를 위해서는 데이터베이스에 접근하는 구문을 이해하여 어떻게 동작하는지 알아야 합니다.

 

<?php
if($_GET['no']){
  $db = dbconnect();
  if(preg_match("/ |\/|\(|\)|\||&|select|from|0x/i",$_GET['no'])) exit("no hack");
  $result = mysqli_fetch_array(mysqli_query($db,"select id from chall18 where id='guest' and no=$_GET[no]")); // admin's no = 2

  if($result['id']=="guest") echo "hi guest";
  if($result['id']=="admin"){
    solve(18);
    echo "hi admin!";
  }
}
?>

 

preg_match() 함수는 해당하는 문자열과 일치하는 값이 있으면 1, 없다면 0을 반환합니다.


if문의 조건으로 삽입하여 일치하는 문자열이 있으면 exit()문을 실행하고, 

없다면 다음 문장을 진행하는 형태입니다.


preg_match() 함수의 첫 인자는 정규 표현식을 통해 검색하고자 하는 문자들을 받아들입니다.
정규식 표현 방법은 슬래시(/)를 사용하는 것과 RegExp() 함수를 사용하는 것이 있습니다.
위의 문장에서는 슬래시를 통해 표현되어있습니다.

 


정규 표현식에 대한 자세한 설명은 해당 링크에 있습니다.

 

 

https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/%EC%A0%95%EA%B7%9C%EC%8B%9D

 

정규 표현식

정규 표현식은 문자열에 나타는 특정 문자 조합과 대응시키기 위해 사용되는 패턴입니다. 자바스크립트에서, 정규 표현식 또한 객체입니다.  이 패턴들은 RegExp의 exec 메소드와 test 메소드  ,��

developer.mozilla.org

 

슬래시를 기준으로 틀 안에 있는 문자 리스트는 공백 문자( ), 슬래시(/), 괄호 열기( '(' ), 괄호 닫기( ')' ),
파이프( | ), 앰퍼샌드(&), select, from, 16진수 표현(0x) 입니다.


해당하는 문자는 $_GET['no']에서 찾아냅니다.  $는 변수를 의미합니다.
$_GET['no'] 변수는 사용자가 입력한 값을 저장하며,
해당 값이 데이터베이스에 있는 no의 값과 일치하면 결과를 출력합니다.


"select id from chall18 where id='guest' and no=$_GET[no]" 문장을 확인해 보겠습니다.

select ~ from ~ where ...


SQL을 학습하신 분들은 쿼리(query) 문장이라는 것을 알 수 있으실 것입니다.
문장에서는 guest로의 접근만 가능하도록 id='guest'로 고정했습니다.


and는 앞과 뒤의 조건이 모두 참(True)여야 참(True)을 출력합니다.
따라서 데이터베이스에서 id와 no는 한 쌍의 데이터를 의미합니다.


로그인 아이디와 비밀번호가 일치해야 접속이 되는 것처럼
guest라는 id와 $_GET[no] no값이 일치해야 허용이 된다는 의미입니다.



문제에서 제시된 php 코드에서는 주석으로 admin의 no는 2라고 명시하였습니다.
이제 어떻게 풀어낼 수 있는지를 알아내면 되겠습니다.

 


SQL INJECTION 활용하기

select id from chall18 where id='guest' and no=$_GET[no]

 

 

위의 SQL 문장에서 최종적으로 뽑아오는 데이터는 id 값임을 알 수 있습니다.
코드에 적용되어있는 SQL 문장의 취약점을 활용하여 문제를 해결하겠습니다.


접근할 부분은 id='guest' and no=$_GET[no] 입니다.
id='guest'로 명시되어있기 때문에 이 값을 수정할 수는 없습니다.
하지만 사용자가 입력하는 부분인 $_GET[no]는 조작할 수 있습니다.


guest에 해당하는 no의 값은 1입니다. (실제로 페이지에서 시도했습니다.)
id='guest' and no=1이 참이라는 의미이며
사용자가 입력한 1에 일치하는 id 값으로 guest를 가져옵니다.


no가 1이 아닌 다른 수가 들어가면 and 연산에 의해 참이 나올 수 없게 되어
id 값으로 어떤 것도 가져올 수 없습니다.


그렇다면 id='guest' and no=$_GET[no]에서 앞의 id를 무시하고 뒤의 사용자 입력 값만을 
인식시킬 수 있게 된다면 어떻게 될까요?


or 연산과 admin에 해당하는 2를 활용해 보겠습니다.

 

 id='guest' and no=0 or no=2

 

괄호가 없기 때문에 앞에서부터 순서대로 진행됩니다. 

 


id='guest' and no=0 에서는 no값이 다르기 때문에 거짓(false)입니다.

 

 

그럼 이제 or no=2 연산만 남았습니다.

false or no=2는 다른 볼 것 없이 no 값이 2인 데이터가 있는지를 물어봅니다.

 

 

no=2에 해당하는 id가 없다면 둘 다 false이기 때문에 최종적으로 false,
no=2에 해당하는 id가 있다면 일치하는 데이터를 id 값으로 가져오는 것입니다.
no=2에 해당하는 id는 admin이기 때문에 admin 값을 id로 가져오게 됩니다.


?? 관리자 데이터에 접근하게 된 것입니다..!


풀이 적용

 

참고해야 할 부분으로 처음 정규식에서 제시된 문자들입니다.
제시된 문자들 중 하나라도 사용자 입력 값에 들어있다면 exit()에 의해 해결할 수 없습니다.


사용자 입력으로 들어가야 할 값은 0 or no=2라는 것을 알았습니다.
하지만 제한된 문자로 공백 문자( )가 존재하기 때문에 그대로 적으면 해결 불가...


우회하기 위한 방법을 적용해야 합니다.
해당 방법에 대한 자료를 참고하여 활용하였습니다.

 

https://h232ch.tistory.com/3

 

5. Filtering 우회

=  LIKE, >, <  substr, substring  LEFT, RIGHT, LIKE  주석  #, -- (뒤에 문자하나 필요), ;%00 => 한 줄 주석  /**/ => 여러 줄 주석  #, --과 같은 한 줄 범위 주석 우회  \n (라인피드, %0A)  %20..

h232ch.tistory.com

 

 

공백 문자를 우회하는 방법으로 %0a가 있다고 하여 적용해 보았습니다.


그렇다면 사용자 입력으로 들어갈 값은 = 0%0aor%0ano=2

 

 

 

텍스트 박스에 값을 입력하고 제출을 누르면 특별한 변화는 발생하지 않습니다.
하지만 URL을 확인하시면 값이 들어가 있는 부분을 확인할 수 있습니다.

 

 

 

 

no= 다음 부분을 사용자 입력에 사용했던 값 그대로 다시 입력하고 엔터를 눌러서 시도합니다.

 

 

 

hi admin과 함께 성공했다는 출력을 확인할 수 있습니다!

 

 

 

 

 

728x90

'작업 > Webhacking.kr' 카테고리의 다른 글

webhacking.kr old-6 이해하기  (0) 2020.09.02
webhacking.kr old-24 이해하기  (0) 2020.09.01
webhacking.kr old-17 이해하기  (0) 2020.08.30
webhacking.kr old-16 이해하기  (0) 2020.08.30
webhacking.kr old-14 이해하기  (0) 2020.08.30