Home FSB
Post
Cancel

FSB

Format String Bug

Format String


Format String이란 데이터의 형식을 정해주는 지정해주는 문자열이다.

Format StringTypeMeaning
%dint정수
%ffloat실수
%cchar문자
%sstring문자열
%udecimal10진수
%xhexadecimal16진수
%nint출력된 문자의 개수


아래와 같이 printf 함수에서 자주 볼 수 있다.

1
2
3
4
5
// 1번
printf("%d", number);

// 2번
printf(number);


위 두 코드는 number 변수를 출력하는 같은 기능을 수행하는 코드이다.


코드만 보았을 때 두 코드에 차이점은 Format String 사용 여부이다.
그렇다면 좀 더 코드 길이가 짧은 2번 코드가 좋은 코드라고 생각할 수 있다.


하지만 2번 코드는 FSB 취약점을 가지고 있다.



printf 함수


printf 함수의 원형을 보자

1
2
3
#include <stdio.h>

int printf(const char * restrict format, ...);


인자로 Format이 들어가는 것을 알 수 있다.

만약 Format을 정하지 않으면 어떻게 될까?
간단한 코드를 통해 확인해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// printf_test.c

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

int main(int argc, char **argv){

        char buf[100];

        if(argc != 2)
        	return 0;
 
        strcpy(buf, argv[1]);
        printf(buf);
        printf("\n");
 
        return 0;
}


입력받은 두 번째 인자를 buf에 복사하고 출력하는 코드이다.
abc를 입력해보자.

1


printf 함수에 Format을 정하지 않았지만, 출력은 문제없이 작동한다.
이번에는 Format String을 입력해보자.

2


오류는 일어나지 않았지만 %x를 사용해 변수와 상관없이 Stack에서 4byte만큼 pop해서 출력된 것을 볼 수 있다.

3


AAAA를 입력 후 %x를 8번 출력했을 때 0x41414141 즉, AAAA가 저장되어있는 buf 배열인 것을 알 수 있다.
또한 printf 함수의 인자와 buf 배열에 거리가 %x * 7 = 28byte인 것을 알 수 있다.


Format String Bug ( FSB )


Format String을 통해 현재 메모리 주소와 원하는 메모리 주소 등 메모리 구조를 추측할 수 있다.
이를 통해 공격자들은 Format String Bug을 통해 메모리를 보거나 변조한다.


메모리 변조를 위해서는 변조할 주소와 변조를 통해 이동할 주소를 알아야 한다.
변조할 주소는 Debugging이나 Format String을 이용해 알아낼 수 있다.
변조를 통해 이동할 주소 즉, RET 주소는 Debugging이나 환경변수를 통해 알아낼 수 있다.


워게임으로 Format String Bug를 실습해보자.

실습 환경

가상머신 : VMware workstation
iso : exploit-exercises-protostar-2
ID : user
PW : user
워게임 : Protostar
문제 : format2


로그인 후 셸을 실행시켜준다.

4


문제를 풀기 위해 /opt/protostar/bin 디렉터리로 이동하자.

5


format2 문제를 풀어보자.
우선 파일을 Debugging 하기 위해 tmp 디렉터리로 복사 후 이동하자.

6


gdb를 통해 format2 파일을 Debugging 해보자.

7


main 함수를 disassemble 해봤지만, vuln 함수 호출 외에 다른 코드가 없는 것을 보니 vuln 함수를 보도록 하자.

8


vuln 함수는 입력받은 값을 512byte 변수에 저장하고 변수를 출력 후 0x80496e4 값이 64가 아니면 0x80496e4 값을 포함해 출력하고, 64가 맞다면 문자열만 출력한다.

9


코드를 확인해보면 0x80496e4가 변조해야 할 target 변수에 주소인 것을 알 수 있다.


다음으로는 %x를 이용해 printf와 buffer 사이 거리를 구해보자.

10


%x를 4번 출력했을 때 buffer 배열이 나온다.
printf와 buffer 사이 거리는 24byte인 것을 알 수 있다.


이제 거리와 주소를 알아냈으니 FSB를 통해 target 변수를 변조해보자.


메모리를 볼 때는 %x를 이용했다.
메모리를 변조할 때는 %n을 이용할 것이다.
%n은 출력된 바이트 수를 지정된 변수에 저장하는 Format String이다.
%n을 사용해 target 변수에 주소가 들어있는 배열에 64를 저장하면 문제를 해결할 수 있다.

11


target 변수가 변조되어 출력되는 것을 확인할 수 있다.
하지만 64가 아니라 문제가 해결되지는 않았다.
1byte를 출력하는 Format String인 %c를 이용해보자.

12


target 변수가 64로 변조되어 문제가 해결된 것을 볼 수 있다.


마무리하며


Format String Bug는 메모리를 볼 수 있고, 메모리를 변조할 수 있어 다양한 공격에 활용될 수 있다.
대응 방안으로는 FSB는 Format을 정해주지 않아서 발생하는 취약점이므로 코드를 작성할 때 정확한 Format String 지정이 필요하다.

참고

포맷스트링 공격(Format String Attack) - eli_ez3r Hacking Blog
작은 실수에서 오는 취약점, 포맷 스트링 - Knowllipop 놀리팝
Format Two :: Andrew Griffiths’ Exploit Education

This post is licensed under CC BY 4.0 by the author.