포맷 스트링 버그는 대표적으로 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
참고
dreamhack - Linux Exploitation & Mitigation Part 2: FSB
'Hacking > Pwnable' 카테고리의 다른 글
[Pwnable] Lazenca - RTL(x64) 정리 (0) | 2021.03.21 |
---|---|
[Pwnable] Lazenca - RTL(x86) 정리 (0) | 2021.03.20 |
[P4C] 우리집에 GDB 있는데… 메모리 보고갈래? (3) 정리 (0) | 2021.03.13 |
[P4C] 우리집에 GDB 있는데… 메모리 보고갈래? (2) 정리 (0) | 2021.03.12 |
[P4C] 우리집에 GDB 있는데… 메모리 보고갈래? 정리 (0) | 2021.03.11 |