SH1R0_HACKER

004. Format String Bug 본문

System/System Exploitation

004. Format String Bug

SH1R0_HACKER 2021. 2. 7. 10:47

포맷 스트링 버그는 printf나 sprintf와 같이 포맷 스트링을 사용하는 함수에서 발생하는 취약점입니다.

 

// fsb-1.c
#include <stdio.h>
int main(void) {
    char buf[100] = {0, };
    
    read(0, buf, 100);
    printf(buf);
}

 위 예제는 buf에 100byte를 입력받고 printf 함수를 통해 buf를 출력하는 예제입니다.

사용자가 "Hello" 나 "12345" 같은 문자열을 입력다면

printf("Hello");

printf("12345");

와 같이 정상적으로 문자열이 출력됩니다.

 

하지만 %x %d 와 같은 포맷 스트링을 문자열로 입력한다면,

printf("%x %d")와 같이 인자를 받을 수 있는 함수로 변해버립니다.

하지만 전해줄 인자가 없기 때문에 쓰레기 값을 출력하게 됩니다.


두 번째 예제입니다.

// fsb-2.c
#include <stdio.h>
#include <stdlib.h>
int main(void) {
    FILE *fp = fopen("log.txt", "w");
    char buf[100] = {0, };
    
    read(0, buf, 100-1);
    
    fprintf(fp, "BUFFER-LOG: ");
    fprintf(fp, buf);
    
    fclose(fp);
    return 0;
}

log.txt 파일을 읽기 전용으로 열어서 read 함수로 99byte만큼 buf에 데이터를 저장합니다.

 

fprintf의 원형은 아래와 같습니다.

#include <stdio.h>

int fprintf(FILE* stream, const char* format, ...);

fprintf(fp, "BUFFER-LOG: %s "); 와 같이 포맷스트링이 들어가야 할 곳에 사용자의 입력이 들어갑니다.

예제 1번과 마찬가지로 %x, %d 같은 포맷 스트링을 입력하면 의도치 않은 값이 파일에 저장됩니다.

 

포맷 스트링 버그는 함수의 인자만 잘 검토하면 막기 쉽습니다.

최근에는 컴파일러에서 경고 메시지를 출력하기 때문에 잘 발생하지 않는 취약점입니다.

 

// fsb-easy.c
#include <stdio.h>
int main(void) {
    int flag = 0x41414141;
    char buf[32] = {0, };
    
    read(0, buf, 31);
    printf(buf);
}

 

위 예제는 사용자의 입력을 31byte만큼 printf로 buf를 출력하는 예제입니다.

여기에 포맷 스트링을 입력해 버린다면 의도치 않은 값을 출력할 수 있습니다.

 

 

따라서 %x를 10번 입력하여 flag 값을 출력하도록 합니다.