본문으로 이동
메뉴 여닫기
환경 설정 메뉴 여닫기
개인 메뉴 여닫기
로그인하지 않음
지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.
Format String Attack; 형식 문자열 공격
printf 계열 함수에 사용자 입력을 형식 문자열 자리에 그대로 넘겼을 때 메모리를 읽거나 쓸 수 있게 되는 취약점

C 의 printf 계열 함수는 형식 문자열에 들어 있는 변환 지정자의 개수만큼 스택에서 인자를 꺼내 쓴다. 형식 문자열을 공격자가 정할 수 있으면 인자의 개수와 종류도 공격자가 정하게 된다.

printf(user_input);          // 취약하다
printf("%s", user_input);    // 안전하다

위쪽은 user_input 이 그대로 형식 문자열이 되므로, 입력에 %x 를 넣으면 실제로는 넘기지 않은 스택의 값이 출력된다.

  • %x, %p — 스택의 내용을 차례로 꺼내 출력시킨다. 메모리 구조와 값이 노출된다
  • %s — 스택의 값을 주소로 보고 그 위치의 문자열을 읽는다. 잘못된 주소면 프로그램이 죽는다
  • %n — 지금까지 출력한 문자 수를 인자가 가리키는 주소에 써 넣는다.
 출력 폭을 조절하면 원하는 값을 원하는 주소에 쓸 수 있어, 함수 포인터나 복귀 주소를 바꿔 코드 실행까지 이어진다

읽기만 가능한 다른 지정자와 달리 %n 이 쓰기를 가능하게 하는 핵심이다.

  • 형식 문자열을 상수로 고정한다. 사용자 입력은 반드시 인자로 넘긴다
  • 컴파일러 경고를 켠다. -Wformat -Wformat-security 가 이 패턴을 잡아 준다
  • %n 을 막는 라이브러리 설정을 쓴다
  • 스택 보호 기법과 주소 공간 배치 무작위화로 악용 난이도를 높인다

버퍼 오버플로와의 차이

편집 원본 편집

버퍼 오버플로는 경계 검사를 하지 않아 버퍼 밖으로 넘겨 쓰는 것이고, 포맷 스트링 공격은 함수에 넘기는 형식 문자열 자체를 조작해 함수가 스스로 읽고 쓰게 만드는 것이다. 둘 다 임의 코드 실행으로 이어질 수 있지만 원인과 방어 지점이 다르다.