본문 바로가기

🔐 Security/System

[시스템보안] 스택 버퍼 오버플로우

위 글은 2022년도 목포대학교 학점교류 '시스템보안' 수업에서 수행한 과제를 작성한 내용입니다.
교재 : 시스템 해킹과 보안: 정보 보안 개론과 실습 3판, 양대일 (2018)

 

1. gdb 분석으로 취약 프로그램의 스택 버퍼 오버플로 개념 이해하기

(1) bugfile.c 컴파일하기

vi 에디터를 사용하여 bugfile.c를 작성한 후, gdb로 디버깅하기 위해 -g 옵션을 사용하여 gcc로 컴파일한다.

(2) gdbbugfile.c 소스 코드 확인하기

gdb로 소스 코드를 확인한다.

list 명령을 사용하여 특정 행(3~7)의 범위를 조회한다.

(3) 브레이크 포인트 설정하기

gdb로 디버깅을 수행할 때 프로그램 행 번호를 기준으로 진행하므로, 5행에 브레이크 포인트를 설정한다.

(4) bugfile.c의 어셈블리어 코드 확인하기

gdb로 디버깅하기 전에 main 함수와 strcpy 함수의 어셈블리어 코드를 확인한다.

(5) 설정 브레이크 포인트 지점까지 프로그램 실행 후 변수 확인하기

설정한 브레이크 포인트(char buffer[10];)까지 프로그램을 실행한 후, 인수 ‘AAAA’를 입력하여 확인한다.

브레이크 포인트에서 변숫값 argc, argv[0], argv[1], buffer를 확인한다.
확인해보면 argc는 인수 개수를 가리키고, 프로그램 뒤에 붙은 문자열이 두 번째 인수가 된다.
버퍼에는 의미 없는 값(쓰레깃값)이 들어있다.

(6) 레지스터값과 스택 확인하기

레지스터 전체값을 info reg 명령으로 esp부터 16 워드(w) 범위만큼 스택을 조회한다.

(7) 다음 단계로 넘어가기

next 명령으로 strcpy(buffer, argv[1]); 명령을 실행한 후, buffer 값과 esp 값부터 스택 내용을 확인해보면 버퍼의 앞부분이 ‘AAAA’로 변경됨을 확인할 수 있다.

c(ontinue) 명령으로 프로그램을 끝까지 실행한다.
“bugfiile AAAA”실행 결과를 확인한다.

(8) char buffer[10] 범위를 넘겨 실행하기

버퍼 오버플로를 확인하기 위해 printf(“%s\n”, &buffer); 행에 브레이크를 설정하고, A 13개를 인수로 입력하여 Segmentation fault를 확인한다.

인수 A16개 입력해보면 segmantation fault가 발생함을 확인할 수 있다.
이는 인수로 A 문자를 buffer 이상을 쓰게 되면 ebp 주소를 문자열이 덮어쓰게 되어 저장된 ebp값이 손상되고 프로그램은 오류가 발생한다.

 

2. 스택 버퍼 오버플로 수행하기

eggshell 툴을 사용하여 셸을 먼저 메모리에 저장한 후 저장된 메모리 주소를 확인한다.
그리고 이 주소로 SetUID 권한이 설정된 취약 코드의 ret 주소를 확인된 메모리 주소로 변조하는 과정을 거친 후 프로세스를 넘겨 관리자 권한을 획득한다.

(1) bugfile.ceggshell.c 컴파일하기

bugfile.c 파일을 관리자 계정으로 컴파일한 후 SetUID를 부여한다.
su 명령으로 일반 사용자 계정으로 전환한다.

(2) 취약 함수 찾기

gdb에서 확인한 것처럼 취약함수를 찾는 것이 기본이나, 컴파일한 프로그램이 사용한 함수는 strings 명령으로 확인할 수 있다.
여기에서는 취약 함수인 strcpy를 사용했음을 알 수 있다.

(3) “Segmentation fault”가 일어나는 지점 찾기

프로그램의 ret 주소가 변조되면 Segmentation fault가 발생하고, ret 주소의 위치를 역으로 확인할 수 있다.
A 문자를 16개 이상 사용했을 때, ‘00’ 문자가 ret 주소의 1바이트 이상을 침범하면 Segmentation fault가 일어난다. 따라서 17~20바이트 ret 주소라는 것을 알 수 있다.

(4) eggshell 실행하기

eggshell을 실행하여 셸 코드를 메모리에 상주시킨다. 실습을 진행한 컴퓨터에서 주소는 0xbffffb68에 적재되었다.

(5) 스택 오버플로 공격 수행하기

(perl)을 이용하여 A 문자열과 셸의 메모리 주소를 bugfile에 직접 실행한다.
공격 시 셸 주소를 1바이트씩 거꾸로 입력(리틀 엔디언 방식 스택)한다.
공격이 끝나면 권한이 루트로 바뀌었음을 알 수 있다. (uid = 0)