[컴퓨터 보안] 버퍼 오버플로우(Buffer overflow)의 개념과 예방법

버퍼 오버플로우(Buffer overflow)의 개념과 예방


버퍼 오버플로우 개념

버퍼 오버플로우는 버퍼 오버런(buffer overrun), 버퍼 오버라이트(buffer overwrite)라고도 불린다. 
버퍼 오버플로우의 개념은 버퍼에 할당된 저장 영역에 할당된 영역보다 더 많은 자료를 입력하여 데이터를 변경 할 수 있는 조건이다. 
공격자는 조건을 이용하여 시스템 먹통으로 만들거나 코드를 삽입해서 시스템의 제어를 가진다.
버퍼 오버플로우는 스택 버퍼 오버플로우, 힙 버퍼 오버플로우 2 가지가 있다.


버퍼 오버플로우 예제


1. 아래 코드를 실행 해보자.

#include <stdio.h>
#include <string.h>

void vulnerableFunction(char* input) {
    char buffer[10];
    strcpy_s(buffer, 20, input);//4 copy하기
    printf("입력값: %s\n", buffer); //공백"\n" 포함 10자가 넘으면 오류 발생
}

int main() {
    char userInput[20];
    printf("문자열을 입력하세요: ");// 1. 문자 입력
    gets(userInput); //2. 문자열 입력 받기(공백"\n" 포함 )
    vulnerableFunction(userInput);//3. 함수 가기
    return 0;
}


2. 1234567891 을 입력하면 총 11글자다.(gets 함수는 문자열을 입력하는 함수인데 공백(\n)을 포함 한다.)



3. 버퍼 오버플로우가 발생했다면서 에러가 발생한다.




4. 오류가 발생하는 이유

1. main 함수의 UserInput[20] 배열은 20바이트를 할당 했고 
2. vulnerableFunction 함수의 buffer[10] 배열은 10 바이트를 할당 했다.
3. strcpy_s(buffer, 20, input); 함수에서 buffer에 *input의 11바이트(1234567891\n)을 복사해서 넣을려고 하니 버퍼 오버플로우가 발생해 오류가 났다.



5. gets 함수 바꿔서 개수 지정해주기

위처럼 gets 함수는 문자열을 입력 할 수 있다. gets 함수 대신 fgets 함수를 사용하여 최대  입력 수를 정할 수 있다. 만약 10을 적으면 10개만 입력이 가능하니 버퍼 오버플로우를 예방 할 수 있다.



스택 버퍼 오버플로우


buffer[8] 보다 많은 8글자 이상 입력하면 오버플로우가 발생한다.
gets 함수를 fgets로 바꿔 입력수를 제한해야 한다.

#include <stdio.h>

int main() {
    char buffer[8];
    printf("문자열을 입력하세요: ");
    gets(buffer);
    printf("입력값: %s\n", buffer);
}


힙 버퍼 오버플로우


동적 할당을 한 buffer 보다 많은 10글자 이상 입력하면 오버 플로우가 발생한다.
gets 함수를 fgets로 바꿔 입력수를 제한해야 한다. 또한 동적 할당 해제인 free를 꼭 해줘야 한다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void vulnerableFunction(char* input) {
    char* buffer = (char*)malloc(10);
    strcpy_s(buffer, 10, input);
    printf("입력값: %s\n", buffer);
    free(buffer);
}

int main() {
    char userInput[20];
    printf("문자열을 입력하세요: ");
    gets(userInput);
    vulnerableFunction(userInput);
    return 0;
}




버퍼 오버플로우 예방법


1. 프로그래밍 언어 선택 : 현대의 고급 프로그래밍 언어는 변수 타입, 허용되지 않는 연산 등에 대해 강력한 표기법을 제공한다. 이러면 프로그래머가 오버플로우를 따로 검증하는 코드를 안 작성해도 된다. 왜냐하면 이미 컴파일러가 그 표기법은 안된다고 검증을 하라고 알려주기 때문.

2. 안전한 라이브러리 사용 : 검증된 라이브러리 같은 경우는 개발자들이 마음 놓고 쓴다. 하지만 어떠한 버퍼 오버플로우가 있을 지 모르는 일이다. 또한 사용하지 말라는 함수는 사용 하면 안된다. 예를 들어 gets 함수대신 getsf 함수를 쓰는 것처럼 안전한 라이브러리 함수를 사용해야 한다.



댓글

이 블로그의 인기 게시물

[Arduino] 아두이노 초음파 센서(HC-SR04) 사용하기

[Arduino] 아두이노 조이스틱 사용하기

[자연 환경] 농약의 장단점 농약이 환경과 인간에게 미치는 영향