[Dreamhack-system] Stack Buffer Overflow(2)

박정원·2023년 4월 12일

보안공부

목록 보기
19/43

Memory Corruption : Stack Buffer Overflow

버퍼 오버플로우

스택 버퍼 오버플로우는 스택의 버퍼에서 발생하는 오버플로우를 뜻함

버퍼

  • 버퍼(Buffer)는 컴퓨터 과학에서는 '데이터가 목적지로 이동되기 전에 보관되는 임시 저장소'의 의미로 쓰임
  • 데이터의 처리속도가 다른 두 장치가 있을 때, 이 둘 사이에 오가는 데이터를 임시로 저장해 두는 것은 일종의 완충 작용을 함
  • 스택에 있는 지역 변수는 스택 버퍼, 힙에 할당된 메모리 영역은 힙 버퍼 라고도 불림

버퍼 오버플로우

  • 버퍼 오버플로우는 문자 그대로 버퍼가 넘치는 것을 의미함
  • 일반적으로 버퍼는 메모리상에 연속해서 할당되어 있으므로, 어떤 버퍼에서 오버플로우가 발생하면 뒤에 있는 버퍼들의 값이 조작될 위험이 있음

중요 데이터 변조

  • 버퍼 오버플로우가 발생하는 버퍼 뒤에 중요한 데이터가 있다면, 해당 데이터가 변조됨으로써 문제가 발생할 수 있음
#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");
}

위의 코드에서 main 함수는 argv[1]을 check_auth 함수의 인자로 전달한 후 반환 값을 가져옴. 이 때, 반환 값이 0이 아니라면 "Hello Admin!"을, 0이라면 "Access Denied"라는 문자열을 출력함

그런데 check_auth에서 strncpy 함수를 통해 temp 버퍼를 복사할 때, temp의 크기인 16바이트가 아닌 인자로 전달된 password의 크기만큼 복사시킴 -> argv[1]에 16바이트가 넘는 문자열을 전달하면, 이들이 모두 복사되어서 스택 버퍼 오버플로우가 발생함

데이터 유출

  • C언어에서 정상적인 문자열은 널바이트로 종결되며, 표준 문자열 출력 함수들은 널바이트를 문자열의 끝으로 인식함-> 만약 어떤 버퍼에 오버플로우를 발생시켜서 다른 버퍼와의 사이에 있는 널바이트를 모두 제거하면, 해당 버퍼를 출력시켜서 다른 버퍼의 데이터를 읽을 수 있음
#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);
}

위의 코드에서 8바이트 크기의 name 버퍼에 12바이트의 입력을 받음 -> 읽고자 하는 데이터인 secret 버퍼와의 사이에 barrier라는 4바이트의 널 배열이 존재하는데, 오버플로우를 이용하여 널 바이트를 모두 다른 값으로 변경하면 secret을 읽을 수 있음(널바이트가 없어져서 끝을 맺지 못함!)

실행 흐름 조작

  • Background : Calling Convention의 내용을 되짚어 보면, 함수를 호출할 때 반환 주소를 스택에 쌓고, 함수에서 반환될 때 이를 꺼내어 원래의 실행 흐름으로 돌아간다고 했음 -> 스택 버퍼 오버플로우로 반환 주소를 조작하면 프로세스의 실행 흐름을 바꿀 수 있음
profile
보안, 프런트엔드 공부 중!

0개의 댓글