IT/시스템 보안

[Stack Buffer Overflow] 데이터 변조와 유출

kykyky 2024. 2. 29. 16:36

데이터 변조

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int check_auth(char *password) { // 입력값(= password)을 buffer(= temp)에 담아 인증을 구현하는 함수
    int auth = 0;
    char temp[16];
    
    strncpy(temp, password, strlen(password)); 
    // strncpy: 입력받은 password 중 어떤 길이 (여기서는 strlen(password))만큼을 temp에 복사함.
    // 이때, password의 길이가 temp의 크기보다 크면,
    // password의 일부는 스택에서 temp가 차지한 범위를 넘어감. 
    // 이때, 그 넘친 위치에 만약 중요한 데이터가 있었다면, 이 데이터를 오염시켜버림.
    // 이 코드의 경우: auth가 오염됨. -> 인증되지 않은 경우 auth는 기본값인 0이어야 하는데, 0이 아니게 되어 인증을 통과해버림.
    
    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");
}

 

원래는 이걸 ./sbof_auth aaaaaaaaaaaaaaaaa로 실행하면 Hello Admin!이 나와야 하는데 왠지 안됐고

Dreamhack 사이트에서만 예상대로 수행됐다.

 

 

아래처럼, 입력값이 아직 16바이트라 auth 영역을 침범하고 오염시키지 않으면, 정상적으로 Access가 거부된다.

 

 

그러나 여기서 한 글자라도 더 써서 auth 영역을 침범하게 되는 순간, auth 값을 오염시키고 인증을 얻게 된다.

 

 

 


 

데이터 유출

 

C언어에서 정상적인 문자열은 Null 바이트로 종결되며, 표준 문자열 출력 함수들은 Null 바이트를 문자열의 끝으로 인식한다.

그런데 만약 어떤 버퍼에 오버플로우를 발생시켜서 다른 버퍼와의 사이에 있는 Null 바이트를 모두 제거하면, 해당 버퍼를 출력시켜서 다른 버퍼의 데이터를 읽을 수 있다.

 

#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); // 4바이트의 Null임.
  printf("Your name: ");
  read(0, name, 12); 
  // name 배열은 8바이트인데 비해, read를 통해 필요 이상으로 총 12바이트나 읽어들이고 있음. -> 사용자의 입력값이 name을 넘어 barrier 전체로까지 넘칠 수 있는 크기임.
  printf("Your name is %s.", name);
  // 만약 입력값이 12바이트 이상이 되어 barrier의 Null 4바이트가 모두 침범당하면, 
  // name이라는 string을 끝맺는 Null이 사라지고, 바로 다음의 secret string과 연결되어
  // secret string까지도 함께 print되어버림.
}

 

 

위 코드를 실행하여, 

입력값이 11바이트일 때까지는 name(= 사용자의 입력값)만 출력이 되지만,

12바이트 이상이 되고부터는 name을 넘어 secret 값까지 출력되어버린다.