보안 공부하는 꼬깔이

Webhacking.kr 18번 문제 풀이

 

 

 

 

18번 문제에 접속하게 되면 대놓고 SQL INJECTION 문제라고 알려준다.

 

index.phps 를 확인해보자

 

index.phps 파일에는 위에 해당하는 소스코드가 존재한다. 코드를 해석해보자

 

 

if($_GET[no]) #GET 방식으로 no값에 전달된 값이 있다면 if문 수행
{

if(
eregi(" |/|\(|\)|\t|\||&|union|select|from|0x",$_GET[no])) exit("no hack"
); // eregi 함수를 사용하여 코드에 나와있는 특수문자 및 구문을 |(파이프)를 기준으로 필터링하고 해당 필터링되는 문자중 하나라도 no 변수의 값에 있다면 no hack 이라는 구문이 출력되고 코드 종료  

$q=@mysql_fetch_array(mysql_query("select id from challenge18_table where id='guest' and no=$_GET[no]"
)); //코드의 쿼리를 수행해 $q 변수에 배열 형식으로 저장함.

if(
$q[0]=="guest") echo ("hi guest"
); //쿼리가 실행되어 q 배열에 저장된 값이 guest 라면 hi guest 출력
if(
$q[0]=="admin"
) // q배열에 저장된 값이 admin 이라면 문제 공략 성공
{
@
solve
();
echo (
"hi admin!"
);
}

}

 

 

코드 해석은 끝났고, 이제 어느 부분에서 어떻게 sql injection 공격을 해야하는지 실제 mysql을 통해 테스트 해보자 

 

 

우선 form에 1을 넣게 되면 hi guest가 출력된다는 점을 참조하자

 

 

guest의 no값이 1이라는 점을 반영해 문제와 비슷하게 테이블을 구축했다.

 

 

해당 문제의 쿼리는 이런식으로 동작된다. 이렇게 되면 id 값이 guest로 고정되며 and 연산으로 인해 guest에 해당하는 no 값을 입력해야만 참이되고 값이 출력된다.

 

 

하지만 이런식으로 no 컬럼에 존재하지 않는 거짓값(-1 같은)을 입력해 id와 no의 and 연산을 거짓으로 만들어주고 or 연산을 시도하여 참이 되는 값을 넣게되면 쿼리문이 동작되고 or 연산자의 조건으로 값이 출력될것이다.

 

 

실제로 테이블에 sql injection ID를 추가해주고 id와 pw의 and연산을 거짓으로 만들고 or 연산자에 참이 되는 쿼리를 추가하니 해당 쿼리에 대한 결과값이 도출되었다.

 

이제 본격적으로 문제를 풀어보자

 

우선 해당 문제에서 guest의 no 값은 1이다. 하지만 우리는 admin에 대한 no값이 무엇인지 모르기 때문에 no값으로 admin을 출력하기는 어렵다. 그렇기 떄문에 limit 연산자를 사용해 admin을 출력시켜보자.

 

TIP.limit 연산자?

- limit 의 사전적 뜻은 제한하다 라는 뜻이다. 그렇다면 limit 연산자는 mysql에서 어떤역할을 하는가? 바로 쿼리의 출력 결과의 개수를 임의로 정해서 출력할 수 있다. 예를들어 (select * from challenge18_table where id limit 0,5) 해당 쿼리를 출력하게 되면 challenge18_table의 id 값이 0번째 부터 5번째까지만 출력한다.(0부터 첫번쨰 컬럼) 2,6 을 적어주게 되면 3번쨰 컬럼부터 7번쨰 컬럼까지 출력하라 라는 뜻이 된다.

 

 

limit 0,1 의 결과값을 보면 테이블의 첫번째 값인 guest가 출력되었고 limit 1,1 의 결과값으로는 admin이 출력되었다. 실제 문제에서 테스트 해보자

 

 

sql injection 구문을 전송하니 no hack 이라는 구문이 출력되었다. eregi 함수로 인해 필터링되버린 것이다.

 

if(eregi(" |/|\(|\)|\t|\||&|union|select|from|0x",$_GET[no])) exit("no hack");

 

필터링구문을 다시 한번 확인해보니 \t(tab) 과 공백(띄워쓰기) 가 필터링되는 것을 확인할수 있다.  공백문자를 사용하지 못하면 쿼리 에러가 떨어질것이고 결과값이 출력되지 않을것이다. 그러므로 우리는 공백과 같은 역할을 하는 개행 문자들을 url encode 형식으로 전달해 필터링을 우회할것이다.

 

1. Tab : %09

  - no=1%09or%09id='admin'

 

2. Line Feed (\n): %0a

  - no=1%0aor%0aid='admin'

 

3. Carrage Return(\r) : %0d

  - no=1%0dor%0did='admin'

 

4. 주석 : /**/

  - no=1/**/or/**/id='admin'

 

5. 괄호 : ()

  - no=(1)or(id='admin')

 

6. 더하기 : +

  - no=1+or+id='admin'

 

위와 같이 공백과 같은 역할을 하는 여러가지 구문이 존재한다.

 

그중 %09(tab) 또한 필터링 당했으므로 우리는 %0a(Line Feed) 를 사용해 문제를 공략해보자

 

 

-1%0aor%0ano%0alimit1,1 이렇게 get 방식으로 전달해보자!

 

성공적으로 sql injection을 통해 admin 값을 출력했다!

 

 

100 Point 획득 :D

 

 

'Web Hacking > Web Hacking.kr' 카테고리의 다른 글

Webhacking.kr 21번 문제 풀이  (2) 2017.07.10
Webhacking.kr 20번 문제 풀이  (0) 2017.07.07
Webhacking.kr 17번 문제 풀이  (0) 2017.07.06
Webhacking.kr 16번 문제 풀이  (0) 2017.07.06
Webhacking.kr 15번 문제 풀이  (0) 2017.07.06