특별한 이유가 있는 건 아니지만, 이번엔 Buffer Overflow 에 대해 써보고 싶었어요. 제가 처음으로 시도해본 공격이자, 동시에 처음으로 방어하는 방법을 배운 기법이기 때문이죠.
요즘은 메모리를 안전하게 관리해주는 언어들이 많아서 이런 문제를 직접 마주할 일은 줄었지만, 이 개념을 이해하고 있으면 다른 분야에서도 도움이 돼요.
생각해보면 임베디드나 IoT 시스템에서는 아직도 C++ 같은 언어를 많이 쓸까요? 저는 특정 분야에만 주로 있었던 터라 다른 업계에서는 요즘 어떤 게 표준인지 잘 모르겠네요. (Namu Wiki)
1. Buffer Overflow 란?
버퍼 오버플로우는 프로그램이 메모리 버퍼에 할당된 크기보다 더 많은 데이터를 쓸 때 발생합니다.
주로 C나 C++처럼 메모리 관리를 직접 해야 하는 언어에서 자주 발생해요.
공격자는 이 취약점을 악용해 프로그램 흐름을 바꾸거나, 악성 코드를 실행할 수 있어 보안상 매우 심각한 이슈입니다.
2. 주요 공격 유형
1) 스택 기반 오버플로우
- 지역 변수 버퍼를 넘쳐서 리턴 주소를 덮어씀
- 쉘코드를 삽입하고 실행 흐름을 탈취
2) 힙 기반 오버플로우
- 동적으로 할당된 메모리를 공격
- 함수 포인터나 객체 구조 변경 가능
3) 포맷 스트링 공격
- %s, %x 같은 포맷 문자열을 악용
- 메모리를 임의로 읽거나 쓸 수 있음
3. 예시 코드 (C)
#include <stdio.h>
#include <string.h>
void vulnerable_function() {
char buffer[10];
printf("Enter input: ");
gets(buffer); // 위험! 길이 제한 없음
printf("You entered: %s\n", buffer);
}
int main() {
vulnerable_function();
return 0;
}
설명:buffer
는 10바이트만 저장할 수 있지만, gets()
는 입력 길이를 확인하지 않아요.
따라서 10자 이상 입력하면 인접한 메모리를 덮어쓸 수 있고, 심하면 리턴 주소까지 바뀔 수 있습니다.
실제 공격에서는 쉘코드를 삽입하거나 프로그램 흐름을 완전히 탈취할 수 있어요.
4. 방어 방법
gets()
같은 위험한 함수 대신fgets()
사용- 스택 카나리(Stack Canary)로 오버플로우 탐지
- ASLR(주소 공간 배치 무작위화) 활성화
- NX 비트 설정으로 실행 불가능한 메모리 보호
마무리 생각
버퍼 오버플로우는 겉보기엔 단순한 프로그래밍 실수처럼 보이지만, 시스템 전체를 장악할 수 있는 심각한 취약점이에요.
요즘은 메모리 관리를 자동으로 해주는 언어를 많이 쓰니까 크게 신경 쓰지 않을 수도 있겠지만,
만약 임베디드나 저수준 프로그래밍을 하게 된다면 꼭 알아둬야 할 개념이에요.