IT/시스템 보안

[Format String Bug] with Variable length arguments

kykyky 2024. 4. 15. 13:14

💡Format String Bug (FSB)란?

위와 같이,

format functions에서,

format string 내의 format specifier의 개수 != format string을 제외한 argument의 개수

인 경우,

짝이 없는 format specifier는 메모리 내의 임의의 데이터를 출력해낸다.

memory disclosure 취약점이 발생하는 것이다. 

 

 

※ format function의 종류

 

※ format specifier란?

 

※ format string란?

format specifier가 포함된 string

 

 

💡배경 지식: Variable length arguments를 이용하는 함수는 어떻게 구현돼있을까?

 

✅Variable length arguments를 이용하는 함수의 아주 기초적인 구조는 아래와 같다.

#include <stdarg.h>

int myfunc(int x, ...) {
    va_list list_a;
    va_start(list_a, x);
}

 

※ <stdarg.h> 안에 va_start() 등이 정의되어 있는 것이다.

 

 

✅그럼 이런 구조를 가진 예시 함수 myprint()를 보자.

- va_list 포인터는 optional argument에 접근한다.

- va_start()

   Narg의 시작 주소를 얻고,

   data의 type을 바탕으로 크기를 파악한 뒤,

   va_list의 시작 위치를 세팅한다.

🚩

- va_arg()는 format specifier가 발견될 때마다 호출되어 ap(va_list)가 가리키는 argument를 반환하며, ap를 해당 argument의 type의 크기만큼 위(higher address)로 이동시킨다.

- 모든 optional arguent가 접근 완료된 후에는, va_end()가 호출된다. 

 

- myprint(2, 2, 3.5, 3, 4.5);에서의 스택 프레임은 아래와 같다.

 

 

✅printf() 역시 variable length arguments를 가진다.

: format string은 필수, 그 이후는 선택

 

printf()의 동작 과정을 보자. 예시 코드는 아래와 같다.

 

- printf()가 호출되면 argument들은 stack에 push된다.

- format string은 처음부터 쭉 scan되면서,

   format specifier가 발견될 때마다 va_arg()가 호출되고,

   이 함수는 va_list가 가리키는 optional argument를 반환하며, 다음 argument로 이동한다.

 

 

💡이럴 때 FSB가 발생한다

 

바로 위 예시와 쪼끔만 달라진 아래 코드를 보자.

뭐가 달라졌는가? 바로 optional argument가 하나 줄어들어서, 이제 갯수가 매치되지 않는단 것이다.

그럼 아래와 같이, 

🚩

'마지막 format specifier에 대응되는 optional argument가 있었어야 할 위치', 즉 '주소가 현재의 va_list값인 곳'에서 냅다 fetch해와버린다.

즉, memory disclosure가 발생하는 것이다.

물론 va_list는 optional argument가 하나 빠진 줄 모르고 여전히 멍청히 이동을 계속한다.

 

printf(user_input); 처럼,

사용자의 임의의 입력이 printf()의 유일한 argument로 들어가며 format string 형태인 경우 FSB 취약점이 생긴다.

 

 

 

💡FSB에 대한 countermeasure

 

✅안전한 함수 사용

개발자는 format function이 아니라 strcpy() 등을 사용해야 한다.

 

✅ASLR

조작하려는 메모리의 주소나 셸코드의 주소를 추론하기 어렵게 한다.

 

✅NX bit?

하지만 이건 ROP나 return to libc에 뚫린다.

 

✅Stack canary?

는 소용 없다. FSB는 조작하려는 메모리만 수정할 뿐, 다른 메모리는 오염시키지 않기 때문이다.