Buffer Overflow (Buffer Overrun)
버퍼 오버플로우 (버퍼 오버런)
- Buffer는 임시 저장 공간으로, 이종의 Component간의 병목 현상을 해소하기 위해 중간에 위치하는 저장 공간이다.
- Buffer Overflow는 Buffer에 수용 가능한 크기 이상의 Data가 입력되어,
기존의 데이터를 Overwrite하는 것을 의미하며
이는 프로그램의 오류를 야기한다.
- Buffer Overflow는 의도치 않게 발생되거나, 공격자에 의해 악의적으로 발생될 수 있으며,
공격자에 의해 악의적으로 일어난 Buffer Overflow를 Buffer Overflow Attack이라 지칭한다.
- Buffer Overflow Attack은 아래와 같이 두 가지 유형 중 하나로 수행된다.
- 버퍼내에 어떤 데이터를 사용자가 원하지 않는 데이터로 Overwrite한다.
- User Data 혹은 System Data가 덮어씌워질 수 있다.
- Authentication 정보는 일반적으로 Boolean Type Value로 저장되는데,
이 값이 Toggle되면 보안 문제가 발생할 수 있다.
- 버퍼내에 어떤 데이터를 Overwrite하여 사용자가 의도하지 않는 Code로 인도한다.
- Stack의 Function Return Address가 다른 데이터로 Overwrite되어
Program Flow가 의도치 않게 다르게 흘러갈 수 있다.
- 시스템 메모리 Section별로 Overflow Attack이 행해지는 방법은 서로 상이하며,
시스템 메모리의 구조와 저장되는 데이터의 종류는 아래와 같다.
Memory Section | Store Whats |
Text | - Program Code |
Data | - Static Variables - Global Variables |
Heap | - Dynamic Data |
Stack | - Dynamic Local Variables - Function Parameters - Return Address |
* Memory Organization (URL)
Stack-Based Exploitation (Stack Smashing)
- 일반적으로, Stack에 Overflow를 일으켜 프로그램을 조작하는 방식은 아래와 같이 구분된다.
- Overwriting a Local Variable
- Overwriting the Messy Return Address in a Stack Frame
- Overwriting the Malicious Return Address in a Stack Frame (Code Injection)
- Overwriting the Function Pointer
- Overwriting the Exception Handler
- 이들 유형은 공격자가 지정한 주소로 Program Control을 바꾸거나,
Program에 Error를 발생시키는 것을 목표로 한다.
- 일반적으로, 공격자는 본인의 Evil Code의 주소나, Stack내에서의 Return Address를 모르기때문에,
아래와 같은 방식으로 공격을 행한다.
- Stack의 상당 부분을 NOP Code로 채워
Evil Code로 향하는 Return Address에 맞딱드리게 하는 Landing Pad를 Stack에 삽입한다. - Evil Code로 향하는 수많은 Return Address를 Stack에 삽입한다.
Example. Stack Smashing on Authentication Program
(Case: Attacker does not have a Source Code)
- Serial Number로 인증을 수행하는 프로그램의 Executable File(exe)을 가진 공격자는
이를 Disassemble하여 Overwrite할 Address를 찾아내어
적법한 Serial Number 없이도 인증을 완료하는 부분으로 건너뛸 수 있다.
- Program의 Source Code 없이도, 공격자는 인증을 우회할 수 있다.
1. Serial Number로 인증을 수행하는 프로그램의 실행 파일을 공격자는 갖고 있다. (Source Code가 아닌, Executable File) |
|
2. 공격자는 Trial and Error를 통해 Buffer를 발생시키고 Buffer의 크기를 알아낸다. |
|
2. Executable File을 Disassemble하여 Overwrite Target Address(0x401034)를 알아낼 수 있다. - 0x401034에 대한 ASCII Code는 "@^P4" 이다. - 해당 프로그램은 x86 기반 프로세서에서 구동되는데, x86 프로세서는 Little-Endian 구조이므로, "4^P@"가 Target Address가 된다. |
|
3. 공격자는 Stack내의 Return Address를 Target Address로 Overwrite하여 인증을 우회한다. |
Stack Smashing Prevention
- Stack Overflow Attack은 수십년동안 지속된 공격으로,
Legacy Code가 개선되지 않고, 질낮은 소프트웨어가 개발되는한 지속될 수 밖에 없다.
- Stack에 대한 Overflow Attack 예방 방법은 아래와 같다.
- NX Flag Bit를 사용하는 Non-Executable Stack을 채용하는 방법
- NX Bit란 No Execute를 의미하는데, NX Bit가 설정된 Stack이나 Heap에서는 프로그램이 실행될 수 없다.
- Java, C#과 같은 Safe Language를 사용하는 방법
- Java나 C#에서는 Run-Time동안 모든 Memory Access를 Check하는 메커니즘이 존재하여
실행시간이 느리지만, 높은 보안성이 확보되는 장점이 있다.
- Safer C Functions를 사용하는 방법
- strcpy()의 Safer Version인 strncpy()를 사용하는 것과 같이, 보다 안전한 버전의 함수를 대신 사용하는 방법이다.
- Canary Mechanism을 채용하는 방법
- Canary Mechanism이란, Run-Time동안 Stack을 Check하는 메커니즘이다.
- Canary는 어떤 상숫값이며 Stack의 Return Address값과 Buffer 값 사이에 삽입되는데,
이 Canary값에 변경이 생기면 Stack Overflow가 발생되었음을 의미한다.
- Canary 값은 0x000aff0d이거나, Return Address값에 비례한 값으로 설정된다.
* Microsoft's Buffer Security Check (Security Cookie) Feature (URL)
- Microsoft에서 C++의 GS Compiler에 추가한 기능으로
Canary Mechanism을 Implementation한 기능이다.
- GS Compiler에서 Buffer Security Check 기능은 Default로 설정되어 있다.
- Canary값이 변질되었을 경우, User-Supplied Handler가 자동으로 호출된다.
- 그러나, 이 Handler Code는 공격자에 의해 Specify될 수 있어,
User-Supplied Handler 자체가 공격의 대상이 될 수 있는데,
Reference: Information Security: Principles and Practice 2nd Edition
(Mark Stamp 저, Pearson, 2011)
Reference: Computer Security: Principles and Practice 3rd Edition
(William Stallings, Lawrie Brown, Pearson, 2014)
Reference: 2022학년도 1학기 홍익대학교 네트워크 보안 강의, 이윤규 교수님