본문 바로가기

정보보안기사 실기

정보보안기사 _ 6일차 _ 시스템 기본 학습 _ 시스템해킹(버퍼오버플로우)

포맷 스트링 공격 잘 안 와 닿아서 실습하면서 하려고 했는데...

내가 설치해놓은 CentOS가 로컬이었네. 이거 네트워크 연결하고 하려니까 갑자기 급 귀찮 ㅠㅠ

내일부터(내일 공부 못하니까 토요일부터?) 맥북으로 다시 도전하고 오늘은 내용 정리만!

 

시스템 해킹(버퍼 오버플로우, 레이스 컨디션, 포맷스트링 공격)

버퍼 오버플로우 공격

버퍼 오버플로우 공격은 연속된 메모리 공간을 사용하는 프로그램에서 할당된 메모리의 범위를 넘어선 위치에 자료를 읽거나 쓰려고 할 때 발생. 버퍼 오버플로우가 발생하면 프로그램의 오작동을 유발하거나 악의적인 코드를 실행하여 공격자 프로그램을 통제할 수 있는 권한을 획득하게 됨

* 메모리 공간을 넘어간다는 것은 정말 잘 이해가 되는데, 그래서 프로그램 오작동도 이해가 되는 듯 한데

* 악의적인 코드를 실행하여 공격자 프로그램 통제하는 권한 얻는다는게 이해가 안됨

* 특정 주소를 덮어씌운다는 행위가 어떻게 악의적인 코드 실행까지 연결되는가?

* 악의코드를 실행한다는 것은 그 주소를 안다는 것인데 그걸 어떻게 사전에 파악해서 그만큼 딱 넘치게 조작하나?

 

버퍼 오버플로우 공격의 종류

1. 스택 버퍼 오버플로우

  스택은 함수처리를 위해 지역변수 및 매개변수가 위치하는 메모리

  스택에 할당된 버퍼들이 문자열 계산 등에 의해 정의된 버퍼의 한계치를 넘는 경우 버퍼오버플로우 발생

  이는 복귀주소(Return Address)를 변경하고 공격자가 원하는 임의 코드를 실행

 

2. 힙 버퍼 오버플로우

  힙은 사용자가 동적으로 할당하는 메모리 영역(malloc()등의 메모리 할당 함수 이용)

  힙에 할당된 버퍼들에 문자열 등이 저장되어 질 때,

  최초 정의된 힙의 메모리 사이즈를 초과하여 문자열 등이 저장되는 경우

  버퍼 오버플로우가 발생하여 데이터 함수주소 등을 변경하여 공격자가 원하는 코드 실행 가능

 

 

이터와 함수 주소 등을 변경하여 공격자가 원하는 임의의 코드 실행

 

버퍼 오버플로우 이해를 위한 C 언어 함수

 1) strcpy(char *dst, const char *src) : src 문자열을 dst 버퍼에 저장

    src 문자열의 길일르 체크하지 않으므로 dst 버퍼를 초과하는 오버플로우 발생 가능

 2) strncpy(char *dst, const char *src, size_t len) : src 문자열의 len 만큼을 dst 버퍼에 저장

 3) size_t strlen(const char *str) : 문자열 str의 null 문자를 제외한 바이트수를 반환한다

 4) sizeof(피연산자) : 피연산자의 크기 반환

 

스택 오버플로우 발생 시 스택구조

1) 모든 함수는 호출이 되면 자신만의 스택 공간이 할당(어디에 메모리에?) = 이게 스택 프레임!

2) 스택 프레임 공간 내 스택 프레임 포인터(SFP)를 기준점으로 스택 포인터에 상대주소(offset)를 저장해 메모리 접근   

 

3) 현재 실행중인 함수의 스택 프레임 포인터(SFP)는 EBP 레지스터에 저장

4) 스택 포인터(SP)는 ESP 레지스터에 저장

5) 다음 실행할 명령어의 주소는 EIP 레지스터에 저장

 

6) 함수가 호출되면 이전 함수의 다음 실행할 명령어의 주소정보와 스택 프레임 포인터(SFP)를 먼저 스택에 저장

  * 이는 현재 호출된 함수가 종료하고 실행이 이전 호출한 함수로 돌아갔을 때

     EIP, EBP 레지스터의 값을 이전 함수로 되돌리기 위한 일종의 백업

  * 그래야 이전 함수에 이어 프로그램을 진행할 수 있어서 그런가부네

 

 

 

결론 : 함수 호출시 스택 공간이 할당(스택 프레임)되고

이전 함수의 다음 실행할 명령어의 주소(RET, Return Address)도 레지스터에 저장되는데

버퍼오버플로우를 이용해 스택공간과 복귀 주소(RET)를 악성코드가 위치한 주소값으로 덮어쓰면

함수 종료와 동시에 악성코드가 실행하게 되는 것이 스택 버퍼 오버플로우이다.

* 악성코드가 위치한 주소값 같은 것은 gdb를 실행하여 알아낼 수 있다.

* perl 스크립트 등으로 프로그램 실행시 주소값을 덮어씌울 수 있다.

 

스택 버퍼 오버플로우 대응방안

1. 안전한 함수를 사용하여 버퍼 오버플로우 방지 :  strcpy 말고 strncpy로 함수를 교체한다.

   strncpy함수는 인자로 strncpy(char *dst, const char *src, size_t len) src 문자열의 len만큼을 dst에 저장하기 때문이다

 

2. 입력값 사전 검증을 통한 버퍼 오버플로우 방지 

  입력 문자열이 버퍼의 크기와 같거나 크면 프로그램을 종료하도록 하는 것

  * 버퍼의 크기와 동일한 입력 문자열도 문자열의 끝을 의미하는 null(0x00)가 포함될 수 없으므로 이것도 안됨

 

3. 스택 버퍼 오버플로우 대응기술

  1) 스택가드(Stack Guard) : 메모리상에서 프로그램의 복귀주소(RET)와 변수 사이에 특정 값을 저장해두었다가

     그 값이 변경되었을 경우를 오버플로우로 가정하여 프로그램 실행을 중단하는 기술

  2) 스택 쉴드(Stack Shield) : 함수 시작 시 복귀주소를 Global RET라는 특수 스택에 저장해두었다가 함수 종료시

    저장된 값과 스택의 RET 값을 비교해 다를 경우 오버플로우로 가정하여 프로그램 실행을 중단시키는 기술

  3) ASLR(Address Space Layout Randomization) : 메모리 공격을 방어하기 위해 주소공간 배치를 난수화 하는 기법

    실행 시 마다 메모리 주소를 변경시켜 악성코드에 의한 특정주소 호출을 방지함