JJANG-JOON
article thumbnail
반응형

버퍼 오버플로우: 알고 넘어가야 할 보안 취약점

 

개념:

버퍼 오버플로우는 컴퓨터 프로그래밍 및 시스템 보안에서 중요한 개념 중 하나로, 프로그램이 할당된 버퍼를 넘어서 데이터를 쓰거나 복사할 때 발생하는 보안 취약점을 가리킨다. 버퍼는 일련의 데이터를 저장하기 위한 메모리 블록으로, 버퍼 오버플로우는 입력 데이터가 버퍼의 크기를 초과하여 인접한 메모리 영역을 덮어쓰게 되는 상황을 의미한다.

 

원리:

프로그램은 데이터를 처리할 때 메모리 버퍼를 사용하여 데이터를 임시로 저장하거나 조작한다. 하지만 프로그래머가 입력 데이터의 크기를 충분히 확인하지 않거나, 잘못된 방식으로 데이터를 복사하거나 이동시킬 때, 버퍼가 허용 가능한 크기를 초과할 수 있다. 이로 인해 메모리 영역을 넘어가게 되어 중요한 제어 데이터나 실행 코드를 덮어쓰게 되며, 공격자는 이를 악용하여 시스템 제어권을 획득할 수 있다.

 

부가개념:

  • 스택과 힙: 버퍼 오버플로우는 스택과 힙 메모리 영역에서 주로 발생한다. 스택은 함수 호출 및 로컬 변수를 관리하며, 힙은 동적으로 할당된 데이터를 저장한다.
  • NOP 슬레드: 악용을 위해 주입되는 악성 코드를 실행하기 위해 사용되는 일련의 무작위 명령(No-Operation, NOP)을 포함하는 슬레드이다.

 

버퍼 오버 플로우 공격 방식 중 하나인 NOP 슬레드는 다음 명령으로 넘어가는 것이 썰매같다 해서 Sled 라고 불리며 ASLR이 걸려 있어 주소값이 계속 변경되는 환경에서 return-to-shellcode 기법이나 heap Spray형태의 공격 코드들에서 반복구문과 NOP sled를 쓴다.

 

그 이유로는

  • 임의의 메모리를 참조하게 되면 해당 위치에 무조건 악의적인 행위를 실행 하는 코드가 있을 수만은 없다.
  • NOP sled를 이용하여 참조한 위치에 악의적인 행위 코드가 없으면 자연스럽게 실행 흐름을 타고 흘러감
  • NOP명령어들을 타고 흘러가다 악의적인 행위 코드를 포함하고 있는 위치로 갈 수 있음.
  • Shell Code의 주소를 정확히 알아내기 힘들 경우 큰 메모리를 확보하여 Shell Code의 주소의 오차 범위를 크게 만들 때 사용.

 

스택버퍼 오버플로우 코드예시:

 

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

void vulnerableFunction(char *input) {
    char buffer[64];
    strcpy(buffer, input);  // 취약한 복사 함수 사용
}

int main(int argc, char **argv) {
    if (argc != 2) {
        printf("Usage: %s <input>\n", argv[0]);
        return 1;
    }
    vulnerableFunction(argv[1]);
    return 0;
}

설명: vulnerableFunction 내부에서 strcpy 함수를 사용하여 입력된 문자열을 버퍼에 복사하는데, 이때 입력 데이터의 크기를 확인하지 않기 때문에 입력 데이터의 크기가 버퍼의 크기를 초과하면 버퍼 오버플로우가 발생한다.

 

힙 버퍼 오버플로우 코드 예시:

 

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

int main() {
    char *buffer = (char *)malloc(16);
    if (buffer == NULL) {
        perror("Memory allocation error");
        return 1;
    }
    strcpy(buffer, "Hello, buffer overflow!");
    printf("%s\n", buffer);
    free(buffer);
    return 0;
}

 

 

NOP Sled 코드 예시:

NOP sled는 악성 코드 실행을 보다 정확하게 이끌기 위해 사용되는 일련의 무작위 명령(No-Operation, NOP)이다.

 

아래 코드는 x86 아키텍처에서 NOP sled를 구현한 예시:

section .text
global _start

_start:
    jmp short payload  ; NOP sled 이후 악성 코드로 점프

nopsled:
    nop                ; 여러 개의 NOP 명령
    nop
    nop
    ; 이하 생략

payload:
    ; 악성 코드 실행

 

설명: nopsled 섹션에는 여러 개의 NOP 명령이 나열되어 있다. 이후 payload 레이블에서 악성 코드를 실행하는데, 악성 코드의 주소는 NOP sled의 시작 지점으로부터 상대적인 위치로 설정되어 정확한 위치에서 악성 코드 실행이 시작될 수 있게 된다.

 

 

 

대응방법:

  • 입력 검증: 입력 데이터의 크기를 확인하여 버퍼 오버플로우 공격을 방지한다.
  • 보안 함수 사용: 안전한 문자열 복사 함수(예: strncpy) 사용을 통해 버퍼 오버플로우 가능성을 최소화한다.
  • ASLR 활성화: ASLR을 활성화하여 메모리 주소의 예측을 어렵게 하여 공격자의 작업을 어렵게 만든다.
  • 버퍼 크기 제한: 버퍼의 크기를 정확하게 할당하고 사용하는 것이 중요합니다. 데이터의 크기를 버퍼의 크기와 비교하여 오버플로우를 방지한다.
  • 스택 가드 사용: 스택 가드(예: 스택 쉴드, 스택 캐노리)를 활용하여 스택의 오버플로우를 탐지하고 방지한다.
  • 권한 및 접근 제어: 사용자 권한 및 접근을 제한하여 악의적인 코드가 시스템 또는 애플리케이션에 침입하지 못하도록 한다.
  • 버퍼 오버플로우 방어용 라이브러리 사용: 버퍼 오버플로우를 방어하기 위한 특별한 라이브러리(예: libsafe, StackGuard, Buffer Overflow Protection)를 사용한다.
  • 컴파일러 보안 옵션 활용: 컴파일러에서 제공하는 보안 옵션을 활용하여 버퍼 오버플로우와 같은 취약점을 예방한다.
  • DEP(데이터 실행 방지) 활성화: DEP를 활성화하여 실행 가능한 메모리 영역을 제한하여 악성 코드 실행을 방지한다.

 

용어정리:

  • 버퍼 오버플로우: 할당된 버퍼를 초과하여 데이터를 쓰거나 복사함으로써 메모리를 덮어쓰는 보안 취약점.
  • 스택: 함수 호출과 로컬 변수 관리에 사용되는 메모리 영역.
  • 힙: 동적으로 할당된 데이터를 저장하는 메모리 영역.
  • NOP 슬레드: 악성 코드 실행을 위한 일련의 무작위 명령.
  • ASLR: 주소 공간 배치 무작위화로 메모리 주소 예측을 어렵게 만듦.
  • DEP: 데이터 실행 방지로 실행 가능한 메모리 영역을 제한하여 악성 코드 실행을 어렵게 만듦.
반응형
profile

JJANG-JOON

@JJANG-JOON

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

profile on loading

Loading...