포맷 스트링 버그

위키백과, 우리 모두의 백과사전.

포맷 스트링 버그[1]취약점 공격에 사용될 수 있는 보안 취약점으로써 1989년 경에 발견되었다. 이전에는 위험하지 않다고 여겨졌지만, 포맷 스트링 익스플로잇은 프로그램을 충돌시키거나 악의적인 코드를 실행 시키는데 사용될 수 있다. 문제는 포맷팅을 수행하는 printf() 같은 특정한 C 함수들에서 검사되지 않은 사용자 입력을 포맷 스트링 파라미터로 사용하는 것으로부터 나온다. 악의적인 사용자는 %s와 %x 포맷 토큰들을 콜 스택 또는 메모리의 가능한 다른 위치의 데이터를 보이게 하는 데 사용할 수 있다. 또한 %n 포맷 토큰을 사용해서 임의적인 데이터를 임의적인 위치로 쓸 수 있는데, 이것은 printf() 와 비슷한 함수들이 많은 바이트들을 스택에 저장된 주소에 쓰게 한다.

상세[편집]

일반적인 익스플로잇은 이러한 기법들의 조합을 사용해서 프로그램이 라이브러리 함수의 주소나 스택의 반환 주소에 악의적인 셸코드를 가리키는 포인터를 겹쳐쓰게 한다. 포맷 명시자들에 대한 패딩 파라미터들은 많은 바이트들의 출력을 제어하는데 사용되며 %x 토큰은 자신이 도달하는 포맷 스트링의 시작까지 스택으로부터 바이트들을 pop하는데 사용된다. 포맷 스트링의 시작은, %n 포맷 토큰이 악의적인 코드(실행할)의 주소로 겹쳐쓸 수 있는 주소를 포함할 수 있게 다듬어 진다.

포맷 버그들이 이전에는 위험하지 않게 여겨졌고 많은 일반적인 툴들의 결과로 나왔기 때문에 이것은 흔한 취약점이다. MITRE의 CVE 프로젝트는 2007년 6월에 500개의 취약한 프로그램들을 보여주었는데, 2001년과 2006년 사이에 9번째로 자주 보고된 취약점 타입이었다.[2]

포맷 스트링 버그들은 프로그래머가 사용자가 제공한 데이터를 포함한 문자열을 print하고자 할 때 가장 흔하게 볼 수 있다. 프로그래머는 실수로 printf(buffer) 를 printf("%s", buffer) 대신에 쓸 수 있다. 첫 번째는 buffer 를 포맷 스트링으로 해석하고 포함하는 어느 포매팅 명령어도 파스(parse)한다. 두 번째는 프로그래머의 의도와 같이 간단하게 문자열을 화면에 보여준다.

포맷 버그들은 C의 인자 전달 컨벤션들이 타입 안전하지 않아서 발생한다. 특히 varargs 메커니즘은 함수들이 어느 개수의 인자들이라도 받아들일 수 있게 하는데(예를 들면 printf) 이것은 원하는 만큼 콜 스택에서 인자들을 pop할 수 있기 때문이다(몇개의 추가적인 인자들이 pop되어야 하는지 그리고 무슨 타입인지를 이전의 인자들이 가리킨다고 믿으며).

포맷 스트링 버그들은 C 외에도 다른 프로그래밍 언어들에도 발생할 수 있다. 하지만 훨씬 적게 발견되며 공격자가 원하는 코드를 실행할 수 있을 만큼 익스플로잇되기도 힘들다.[3]

역사[편집]

포맷 스트링 버그가 발표된 것은 1999 10-15일로 tf8이라는 닉네임으로 보고되었다. 아래는 익스플로잇과 권고문이 바로 그 보고된 것들입니다.


- 익스플로잇: https://dl.packetstormsecurity.net/0006-exploits/wuftpd2600.c

- 보안 권고문 https://www.freebsd.org/security/advisories/FreeBSD-SA-00:29.wu-ftpd.asc


예방[편집]

많은 컴파일러들이 정적으로 포맷 스트링을 검사하고 의심스러운 포맷에 관해서는 경고를 보여준다.

GNU 컴파일러 모음에서 관련있는 컴파일러 플래그들로는, -Wall,-Wformat, -Wno-format-extra-args, -Wformat-security, -Wformat-nonliteral, 그리고 -Wformat=2가 있다.[4]

이것들 대부분은 단지 컴파일 타임 시에 알려진 안좋은 포맷 스트링을 탐지하는데에만 유용하다. 만약 포맷 스트링이 사용자나 애플리케이션의 외부 소스에서 온다면, 애플리케이션은 반드시 그것을 사용하기 전에 검증을 하여야 한다. 또한 애플리케이션이 포맷 스트링을 그때 그때 생성하거나 선택한다면 주의가 필요하다. -Wformat-nonliteral 검사는 더 강력하다.

같이 보기[편집]

각주[편집]

참고 문헌[편집]

외부 링크[편집]