본문 바로가기

Security

[systemhacking] 버퍼 오버플로우

반응형

버퍼란 지정된 크기의 메모리 공간.

버퍼 오버플로우 : 버퍼가 허용할 수 있는 양의 데이터보다 더 많은 값이 저장되어 버퍼가 넘치는 취약점

 

버퍼 오버플로우가 발생하는 위치에 따라

스택 버퍼 오버플로우, 힙 오버플로우와 같이 나눠서 부름.

 

스택 버퍼 오버플로우

// stack-1.c
#include <stdio.h>
#include <stdlib.h>
int main(void) {
    char buf[16];
    gets(buf);
    
    printf("%s", buf);
}

지역변수 buf는 스택 영역에 16바이트로 저장됨.

gets는 사용자가 개행 입력하기 전까지 입력했던 모든 내용을 첫 번째 인자로 전달된 버퍼에 저장.

버퍼를 오버플로우 시켜 ret 영역을 0x41414141로 만들면 성공

Ascii는 Hex Encode 되므로 41을 의미하는 A로 도배.


#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: ./stack-1 ADMIN_PASSWORD\n");
        exit(-1);
    }
    
    if (check_auth(argv[1]))
        printf("Hello Admin!\n");
    else
        printf("Access Denied!\n");
}

argv로 패스워드를 입력받아서 그 값을 temp에 복사

password 길이는 지정되어 있지 않고 temp에 복사하기 때문에 16바이트를 넘어서면 버퍼 오버플로우 발생.

temp 뒤에는 auth의 4바이트가 할당되어 있으므로 버퍼 오버플로우를 통해 auth 값 조작 가능.

Hello admin 출력


#include <stdio.h>
#include <unistd.h>
int main(void) {
    char win[4];
    int size;
    char buf[24];
    
    scanf("%d", &size);
    read(0, buf, size);
    if (!strncmp(win, "ABCD", 4)){
        printf("Theori{-----------redacted---------}");
    }
}

win 4byte, size 4byte, buf 24byte 가 깔림.

입력받은 size 만큼 buf를 채움 


#include <stdio.h>
int main(void) {
	char buf[32] = {0, };
	read(0, buf, 31);
	sprintf(buf, "Your Input is: %s\n", buf);
	puts(buf);
}

buf에 값을 입력받아서 "Your Input is: " 뒤에 붙여서 다시 buf에 씀.

buf를 32바이트 꽉 채우면 "Your Input is: " 15바이트만큼 뒤로 밀림.


스택버퍼 오버플로우는 길이에 대한 검증을 제대로 못했을 때 생김.

입력받은 데이터가 저장되기까지 흐름을 타고가 버퍼의 크기를 넘는 양을 저장할 수 있는지 가능성 검토해야 함.

 

 

힙 오버플로우

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    char *input = malloc(40);
    char *hello = malloc(40);
    
    memset(input, 0, 40);
    memset(hello, 0, 40);
    
    strcpy(hello, "HI!");
    read(0, input, 100);
    
    printf("Input: %s\n", input);
    printf("hello: %s\n", hello);
}

memset은 초기화 함수

만약 input에 데이터를 써서 hello 영역을 침범하면 hello에 복사한 HI 대신 다른 값이 출력됨.

반응형