출력 함수(예: printf)에서 포맷 문자열(format string)을 잘못 처리하면, 공격자가 원하는 메모리 주소에 접근하거나 값을 조작할 수 있는 취약점
즉, printf(user_input) 같이 입력값을 포맷 없이 바로 출력하면 공격자가 %x, %n, %s 같은 포맷을 직접 입력해서 메모리 읽기/쓰기가 가능해 진다.
가능 공격
- 메모리 값 읽기 : %x, %s로 스택, 힙의 민감 정보 출력
- 주소 유출 (ASLR 우회) : 함수 주소, libc 주소 노출
- 메모리 쓰기 (%n) : 특정 주소에 값 기록 → 제어 흐름 조작
- 쉘 획득 / 권한 상승 : 버퍼 오버플로우와 결합해 공격 확장
Java – 포맷 스트링 취약점
메모리 조작 기반의 취약점은 거의 없음
Java는 C/C++과 달리
- 직접 메모리 접근 불가 (포인터 없음)
- 스택/힙 구조에 직접 접근 불가
- %n 포맷으로 임의 주소에 쓰기 불가
따라서 버퍼 오버플로우나 포맷 스트링으로 제어 흐름 탈취 같은 건 원천적으로 불가능하다.
하지만 사용자 입력을 포맷 문자열로 사용할 경우, 예외·오류·정보 노출 가능성 있음
Java – 포맷 처리 방법
- 사용자 입력 출력 : System.out.println(userInput) 또는 StringEscapeUtils.escapeHtml() 등 사용
- 로그 처리 : 로그 포맷은 고정하고, 사용자 입력은 인자로 전달
- 포맷 문자열 사용 : String.format(“고정된 포맷”, 사용자 값) ← 포맷은 고정해야 함