profile image

L o a d i n g . . .

article thumbnail image
Published 2021. 3. 18. 23:57

포맷 스트링 버그는 대표적으로 printf sprintf와 같은 포맷 스트링을 사용하는 함수에서 사용자가 포맷 스트링 문자열을 통제할 수 있을 때 발생하는 취약점이다. 

 

포맷 스트링에는 다양한 종류가 있고, 주어진 인자에 대해 각 포맷 별로 정해진 기능을 수행한다. 만약 공격자가 이러한 포맷 스트링을 조작할 수 있다면, printf 함수의 인자가 저장되는 스택의 내용을 읽거나 %n 혹은 %s 등 메모리 참조 포맷 스트링을 이용해 메모리 커럽션을 유발할 수 있다.

 

 

다음은 실습에 쓸 fsb.c 파일이다.

// gcc -o fsb1 fsb1.c -m32 -mpreferred-stack-boundary=2

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

char flag_buf[50];

void initialize() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
}


int main()
{
	FILE *fp;
	char buf[256];
    
	initialize();
    
	memset(buf, 0, sizeof(buf));
    
	fp = fopen("./flag", "r");
	fread(flag_buf, 1, sizeof(flag_buf), fp);
    
	printf("Input: ");
	read(0, buf, sizeof(buf)-1);
    
	printf(buf);
	return 0;
}

fsb은 중요 파일인 "flag" 파일을 읽고 전역 변수 flag_buf에 저장한다. 그리고 지역 버퍼인 buf에 입력을 받고 printf를 사용하여 출력하되 사용자의 입력이 포맷 스트링으로 그대로 들어가기 때문에 포맷 스트링 버그가 발생한다.

 

해당 예제의 목표는 flag_buf에 저장되어 있는 "flag" 파일의 내용을 포맷 스트링 버그를 통해 읽는 것이다.

 

우선 포맷 스트링 버그가 존재하면 포맷 스트링이 참조하는 버퍼에 공격자의 값을 쓸 수 있는지, 그리고 입력한 데이터가 몇 번째 포맷 스트링에 참조되는지를 먼저 알아내야 한다. 변조 가능한 데이터가 포맷 스트링에 의해 참조된다면 공격자가 임의 주소에 값을 쓰거나 읽는 것이 가능해진다.

 

fsb를 확인해보면 처음 입력 값 "AAAA"가 두 번째 포맷 스트링에 의해 참조되는 것을 확인할 수 있다.

만약 처음에 입력한 4 바이트의 값이 특정 메모리 주소라면, 해당 포인터를 참조하는 포맷 스트링을 사용했을 때 입력한 주소에 값을 쓰거나 읽을 수 있다.

 

 

"AAAA%x.%n"을 입력했을 때 printf 함수가 실행되면서 프로그램이 비정상 종료한 것을 알 수 있다.

 

 

비정상 종료가 발생한 명령어와 레지스터를 gdb를 통해 확인해보면, 0x41414141이 "%n" 포맷 스트링을 통해 참조되어 값을 쓰다가 Segmentation fault가 발생되는 것을 알 수 있다.

 

 

 

"%n" 포맷 스트링을 이용하면 원하는 주소를 참조하여 값을 쓸 수 있다는 것을 알았다. 그러나 fsb1에서는 전역 변수 flag_buf에 저장된 내용을 읽어야 한다. flag_buf의 주소는 심볼을 이용해 gdb에서 다음과 같이 알아낼 수 있다.

 

-> 입력의 첫 4 바이트에 0x804a080 주소를 입력하여 두 번째 포맷 스트링을 참조할 때 해당 주소를 참조하도록 한다.

특정 문자열을 출력할 때는 "%s" 포맷 스트링을 사용하여 다음과 같이 지정된 주소의 문자열을 출력할 수 있다.

다음은 printf("%s", 0x804a080)의 결과를 출력한다.

실제로 성공적으로 "flag" 파일의 내용인 "test: 문자열이 출력된 것을 확인할 수 있다.

 

 

그렇다면 임의의 주소에 원하는 값을 쓰는 것도 가능할텐데, 이때는 %n 포맷 스트링을 이용한다.

이에 대해서는 다음 블로그를 참조해 공부해보았다.

shayete.tistory.com/entry/5-Format-String-Attack-FSB

 

5. Format String Attack (FSB)

Shayete 입니다. 5번째 강의는 포맷스트링 버그에 대해 알아보도록 하겠습니다. 포맷스트링버그는 개발자가 printf()함수 구현 시, 해킹 공격을 고려하지 않고 개발하여 생긴 보안 취약점입니다.  p

shayete.tistory.com

 

 

참고
dreamhack - Linux Exploitation & Mitigation Part 2: FSB
복사했습니다!