스택 버퍼 오버플로우는 스택에 할당되어 있는 버퍼의 크기보다 큰 값을 넣게 되었을때 발생하는 버그를 뜻한다.
스택 오버플로우는 스택이 너무 많이 확장되어 발생되는 버그로 둘 다 용어는 비슷하지만 다른 의미를 가지고 있다.
버퍼는 데이터가 출발지에서 목적지로 이동되기 전에 보관되는 임시 저장소이다.
출발지에서 데이터를 전송하는 속도와 목적지에서 데이터를 수신하는 속도가 다르다면,
보낼 때의 데이터와 받을 때의 데이터가 다를 수밖에 없다.
이 사이에 버퍼가 존재함으로써 속도는 평준화 되지만 데이터의 유실없이 완전성을 보장하며 데이터를 송수신 할 수 있게 한다.
버퍼 오버플로우는 이 버퍼가 넘치는 것을 의미 하는 것인데, int형의 변수는 4바이트의 크기를 갖는데 버퍼는 일반적으로 메모리상에 연속해서 할당되어 있어서 변수에 4바이트가 넘어가는 값을 대입 했을 때 입력한 값이 다른 퍼버의 값들이 입력한 값으로 조작될 위험이 있다.
이 문제로 인해 발생될 수 있는 상황의 예제를 확인해보자.
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) //인자값으로 password문자열을 받음.
{
int auth = 0;
char temp[16]; //연속된 버퍼
strncpy(temp, password, strlen(password)); // temp에 복사하는 길이는 사용자 입력이기 때문에 temp의 길이를 넘길 수 있음
if (!strcmp(temp, "SECRET_PASSWORD")) //입력한 값과 비교하여 auth 설정
auth = 1;
return auth; //return 0 or 1
}
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");
}
리눅스에서는 너무 긴 길이의 입력을 하면 여러 버퍼를 덮어쓸 위험이 있기 때문에 오류를 뿜는다
맨 처음 선언하는 변수를 통해 버퍼가 할당되고 temp 버퍼 뒤에 auth 버퍼가 위치하게 된다. 그렇게 temp의 길이는 16이지만 사용자 입력을 통해 더 긴 길이의 버퍼를 사용하게되고 auth 버퍼에 사용자가 입력한 데이터가 삽입되게 되어, 0이 아닌 다른 값 즉, true가 되어 admin으로 출력된다.
(왜 temp버퍼가 auth 버퍼 뒤에 위치하게 되는지?)
2. 데이터 유출
// 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); //name보다 더 큰 범위를 입력받음
printf("Your name is %s.", name);
}
C언어에서는 문자열의 마지막을 널바이트로 끝내게 되어 있으며 시스템에서도 문자열의 끝을 널바이트로 인식하여 구분한다. 하지만 특정 버퍼에 오버플로우를 발생시켜 다른 버퍼 사이에 있던 널바이트를 없애면 시스템은 문자열을 하나라고 인식 하게 될것이고 숨겨져 있던 데이터를 볼 수 있게 된다.
3. 실행 흐름 조작
2022.06.20 - [Pwnable/정리] - 함수 호출 규약
전에 작성했던 글을 참조 하여 보자.
함수가 호출될 때, 함수가 호출이 끝나고 원래 흐름으로 돌아갈 주소를 스택에 push하는데 이것을 오버플로우를 통해 push된 돌아갈 주소를 사용자가 특정 address를 입력하여 악의적인 행위를 하는 코드가 시작하는 메모리로 흐름을 바꿀 수 있다.
'Pwnable > 이론' 카테고리의 다른 글
Return Address Overwrite (0) | 2022.06.27 |
---|---|
Shell Code (0) | 2022.06.20 |
Calling convention (0) | 2022.06.20 |
최근댓글