포맷스트링취약점 (Format String Vulnerability)
쉽게 풀면
일부 프로그래밍 언어의 출력 함수는 "이 자리에 숫자를 넣어라", "이 자리에 문자열을 넣어라"와 같은 서식 지시자를 이용해 값을 화면에 표시합니다. 정상적인 프로그램이라면 이 지시자는 개발자가 미리 정해둔 값이어야 하는데, 만약 사용자가 입력한 내용이 검증 없이 그대로 이 지시자 자리에 들어가면, 공격자는 마치 프로그램에게 "저 안쪽 서랍에 있는 걸 꺼내 보여줘"라고 명령하듯 메모리 내용을 몰래 들여다보거나 심지어 덮어쓸 수 있게 됩니다. printf(user_input) 처럼 서식 문자열 없이 사용자 입력을 직접 넘기는 코드 패턴이 전형적인 취약 원인입니다.
왜 중요한가
포맷스트링취약점은 간단해 보이는 출력 함수 하나가 메모리 유출과 임의 코드 실행으로까지 이어질 수 있음을 보여주는 사례로, 정보보안학의 시스템 및 운영체제 보안 연구에서 입력 검증의 중요성을 설명하는 대표적인 예로 다루어집니다. 단순 정보 유출을 넘어 %n 지정자를 이용하면 메모리 임의 쓰기가 가능해져 코드 실행으로까지 확대될 수 있어, 버퍼 오버플로우와 함께 초기 메모리 손상 취약점의 대표 사례로 다뤄집니다.
논문에서는 이렇게 쓰입니다
로그 처리 코드에서 취약점이 발생하는 전형적 사례를 보여주는 예문입니다.
취약점 자동 탐지 기법을 다루는 문맥입니다.
조금 더 깊게 보면
포맷스트링취약점은 공격자가 서식 지시자를 조합해 스택에 쌓인 값을 순서대로 읽어내거나, 특정 서식 지시자를 이용해 메모리 임의 위치에 값을 기록하는 방식으로 악용될 수 있습니다. 이러한 위험 때문에 현대의 컴파일러와 정적 분석 도구는 서식 문자열 인자에 변수가 직접 사용되는 코드를 경고로 표시하도록 발전해 왔습니다. 포맷 스트링 취약점은 C 언어의 printf 계열 함수에서 사용자 입력을 포맷 문자열 인자로 직접 전달할 때 발생하며, %x나 %n 같은 지정자를 악용해 스택 메모리를 읽거나 임의 주소에 값을 쓸 수 있습니다.
주의할 점
포맷스트링취약점은 서식 문자열 자리에 사용자 입력이 직접 들어가는 특정 패턴에서만 발생하며, 서식 문자열이 항상 고정된 상수로 지정되어 있다면 이 취약점은 발생하지 않습니다.