Memory Corruption: Stack Buffer Overflow
# 서론
- 모리스 웜: 스택 버퍼 오버플로우 공격을 통해 전파됨
- CVE details에 따르면 스택 버퍼 오버플로우를 포함한 오버플로우 취약점은 이제까지 18,081개가 발견되어 전체에서 3번째로 많이 발견되었으며, 2019년에도 1,247개가 추가로 발견됨
# 스택 버퍼 오버플로우
1. 버퍼 오버플로우
1.1 버퍼
- 버퍼(Buffer): 데이터가 목적지로 이동되기 전에 보관되는 임시 저장소
- 데이터가 처리속도가 다른 두 장치가 있을 때, 이 둘 사이에 오가는 데이터를 임시로 저장해두는 것은 일종의 완충 작용을 함
- 예를 들어 키보드에서 데이터가 입력되는 속도보다 데이터를 처리하는 속도가 느린 프로그램이 있음
- 이런 키보드를 사용하는데 별도의 장치가 없다면, 키보드의 입력 중에 프로그램에서 수용되지 못한 데이터는 모두 유실될 것임
- abcdefgh를 입력했는데 프로그램에는 abcd만 전달될 수 있음을 의미
- 이런 문제를 해결하고자 수신 측과 송신 측 사이에 버퍼라는 임시 저장소를 두고, 이를 통해 간접적으로 데이터를 전달하게 함
- 송신 측은 버퍼로 데이터를 전송하고, 수신 측은 버퍼에서 데이터를 꺼내 사용함
- 버퍼가 가득 찰 때까지는 유실되는 데이터 없이 통신할 수 있음
- 버퍼의 역할 - 빠른 속도로 이동하는 데이터를 안정적으로 목적지에 도착할 수 있도록 완중 작용을 함
- 버퍼의 다른 의미 - 완충의 의미가 많이 희석되어 데이터가 저장될 수 있는 모든 단위를 의미하게 됨
- 스택에 있는 지역 변수: 스택 버퍼
- 힙에 할당된 메모리 영역: 힙 버퍼
💡 버퍼링
- 버퍼에서 유래된 단어로, 송신 측의 전송 속도가 느려서 수신 측의 버퍼가 채워질 때까지 대기하는 것을 의미
1.2 버퍼 오버플로우
- 버퍼 오버플로우(Buffer Overflow): 버퍼가 넘치는 것
- 버퍼는 제각기 크기를 가지고 있는데, int로 선언한 지역 변수는 4바이트의 크기를 갖고, 10개의 원소를 갖는 char 배열은 10바이트의 크기를 가짐
- 10바이트 크기의 버퍼에 20바이트 크기의 데이터가 들어가려 하면 오버플로우 발생
- 일반적으로 버퍼는 메모리상에 연속해서 할당되어 있으므로, 어떤 버퍼에서 오버플로우가 발생하면, 뒤에 있는 버퍼들의 값이 조작될 위험이 있음
- Figure2. 버퍼 오버플로우로 인한 메모리 오염
2. 중요 데이터 변조
- 버퍼 오버플로우가 발생하는 버퍼 뒤에 중요한 데이터가 있다면, 해당 데이터가 변조됨으로써 문제가 발생할 수 있음
- 예를 들어, 입력 데이터에서 악성 데이터를 감지하여 경고해주는 프로그램이 있음
- 악성의 조건이 변경되면 악성 데이터에도 알람이 울리지 않을 수 있음
- 또한 "https://twitter.com"과 통신하는 프로그램이 있다면 주소를 "https://example.evil"로 조작하여 악성 서버와 데이터를 주고받게 할 수도 있음
- Figure3. 스택 버퍼 오버플로우 예제
- main함수는 argv[1]을 check_auth 함수의 인자로 전달한 후, 반환 값을 받아옴
- 이때, 반환 값이 0이 아니라면 "Hello Admin"을, 0이라면 "Access Denied!"라는 문자열을 출력함
- check_auth 함수에서는 16 바이트 크기의 temp 버퍼에 입력받은 패스워드를 복사한 후, 이를 "SECRET_PASSWORD" 문자열과 비교함 →문자열이 같다면 auth를 1로 설정하고 반환함
- 그런데 check_auth에서 strncpy 함수를 통해 temp 버퍼를 복사할 때, temp의 크기인 16바이트가 아닌 인자로 전달된 password의 크기만큼 복사함
- 그러므로 argv[1]에 16바이트가 넘는 문자열을 전달하면, 이들이 모두 복사되어 스택 버퍼 오버플로우가 발생하게 됨
- auth는 temp 버퍼의 뒤에 존재하므로, temp 버퍼에 오버플로우를 발생시키면 auth의 값을 0이 아닌 임의의 값으로 바꿀 수 있음
- 이 경우, 실제 인증 여부와는 상관없이 main 함수의 if(check_auth(argv[1]))는 항상 참이 됨
// Name: sbof_auth.c
// Compile: gcc -o sbof_auth sbof_auth.c -fno-stack-protector
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int check_auth(char *password) {
int auth = 0;
char temp[16];
strncpy(temp, password, strlen(password));
if(!strcmp(temp, "SECRET_PASSWORD"))
auth = 1;
return auth;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: ./sbof_auth ADMIN_PASSWORD\n");
exit(-1);
}
if (check_auth(argv[1]))
printf("Hello Admin!\n");
else
printf("Access Denied!\n");
}
- overflow
3. 데이터 유출
- C언어에서 정상적인 문자열은 널바이트로 종결되며, 표준 문자열 출력 함수들은 널바이트를 문자열의 끝으로 인식함
- 만약 어떤 버퍼에 오버플로우를 발생시켜서 다른 버퍼와의 사이에 있는 널바이트를 모두 제거하면, 해당 버퍼를 출력시켜서 다른 버퍼의 데이터를 읽을 수 있음
- 획득한 데이터는 각종 보호기법을 우회하는 데 사용될 수 있으며, 해당 데이터 자체가 중요한 정보일 수도 있음
- Figure5. 스택 버퍼 오버플로우와 메모리릭
- 8바이트 크기의 name버퍼에 12바이트의 입력을 받음
- 읽고자 하는 데이터인 secret버퍼와의 사이에 barrier라는 4바이트의 널 배열이 존재하는데, 오버플로우를 이용하여 널 바이트를 모두 다른 값으로 변경하면 secret을 읽을 수 있음
// Name: sbof_leak.c
// Compile: gcc -o sbof_leak sbof_leak.c -fno-stack-protector
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main(void) {
char secret[16] = "secret message";
char barrier[4] = {};
char name[8] = {};
memset(barrier, 0, 4);
printf("Your name: ");
read(0, name, 12);
printf("Your name is %s.", name);
}
- overflow: 인터랙티브 모듈을 활용해 "secret message" 출력하기
4. 실행 흐름 조작
- Background: Calling Convention에서 배운 내용
- 함수를 호출할 때 반환 주소를 스택에 쌓고, 함수에서 반환될 때 이를 꺼내어 원래의 실행 흐름으로 돌아감
- 함수의 반환 주소를 조작하면 프로세스의 실행 흐름을 바꿀 수 있음
- Figure6. 스택 버퍼 오버플로우를 통한 반환 주소 덮어쓰기
// Name: sbof_ret_overwrite.c
// Compile: gcc -o sbof_ret_overwrite sbof_ret_overwrite.c -fno-stack-protector
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char buf[8];
printf("Overwrite return address with 0x4141414141414141: ");
gets(buf);
return 0;
}
- overflow: 인터렉티브 모듈을 활용하여 main 함수의 반환 주소를 0x4141414141414141로 변경하기
- "Success!"라는 문자열이 출력되면 성공
# 마치며
- 버퍼 오버플로우는 지정된 버퍼의 크기보다 많은 데이터가 입력되어 발생함
- 모든 메모리 영역에서 발생할 수 있으며, 이를 통해 데이터 변조, 데이터 유출, 실행 흐름 조작 등이 가능함
'Hacking Tech > System Hacking' 카테고리의 다른 글
[Dreamhack] Mitigation:NX & ASLR (0) | 2022.09.05 |
---|---|
[Dreamhack] Mitigation: Stack Canary (0) | 2022.09.04 |
[Dreamhack] Background: Calling Convention (0) | 2022.08.31 |
[Dreamhack] Exploit Tech: Shellcode (0) | 2022.04.03 |
[Dreamhack] Tool: pwntools (0) | 2022.03.28 |