포맷 스트링 버그는 printf나 sprintf와 같이 포맷 스트링을 사용하는 함수에서 발생하는 취약점으로, "%x"나 "%s"와 같이 프로그래머가 지정한 문자열이 아닌 사용자의 입력이 포맷 스트링으로 전달될 때 발생하는 취약점이다.
예시 코드를 봐보자면,
#include <stdio.h>
int main(void) {
char buf[100] = {0, };
read(0, buf, 100);
printf(buf);
}
진짜 매우 간단해보이는 코드임에도, read가 100자리 문자열을 받는데 그 문자열이 만약 "%x" 나 "%s"와 같은 포멧 스트링으로 넣는다면????
허허......
bf3977c0 100
우리가 원한대로 친 값을 출력해주긴 한데... 이런 버그같은 취약점이 실행되어버린거다.
그러나 "%x %d"와 같은 포맷 스트링을 문자열로 입력한다면, printf(buf)는 printf("%x %d")가 된다.
printf("%x %d")에는 두 번째 인자와 세 번째 인자가 전달되지 않기 때문에 쓰레기 값을 인자로 취급해 출력한다. 이건 기억해두자.
게다가, fprintf 도 printf와 똑.같.이 작용하니 진짜 조심하자. 뭣도 모르다가 포멧 스트링 버그가 날 수 있다.
포맷 스트링 버그는 포맷 스트링을 사용하는 함수의 인자만 잘 검토하면 되기 때문에 다른 취약점들에 비해 막기 쉽다.
특히 최신 컴파일러에서는 포맷 스트링으로 전달되는 인자가 문자열 리터럴이 아닐 경우 경고 메시지를 출력하기 때문에 요즘에는 잘 발생하지 않는 취약점이다.