
printf 함수 하나로 메모리 내용을 훔쳐보는 /etc/passwd)에 데이터를 덮어쓰게 됩니다./tmp 디렉토리에 임시 파일을 생성할 때 주로 발생합니다.#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main() {
char *filename = "/tmp/temp_file";
char *data = "root_data";
// [Check] 파일이 존재하지 않는지(접근 가능한지) 확인
if (access(filename, F_OK) != 0) {
// [공격 포인트] Check와 Use 사이의 틈 (Race Condition)
// 공격자가 이때 /tmp/temp_file을 /etc/passwd로 심볼릭 링크를 건다면?
sleep(1);
// [Use] 파일 생성 및 쓰기
FILE *fp = fopen(filename, "w");
if (fp) {
fprintf(fp, "%s", data);
fclose(fp);
}
}
return 0;
}access 함수와 fopen 함수 사이의 틈을 타서 /tmp/temp_file을 /etc/passwd를 가리키는 심볼릭 링크로 만들어 버리면, 이 프로그램은 관리자 권한으로 /etc/passwd를 덮어쓰게 됩니다.mkstemp 함수 등을 사용하여 예측 불가능한 임시 파일명을 생성해야 합니다.open 함수의 O_CREAT | O_EXCL 플래그를 사용하여 "파일이 없을 때만 생성"하는 동작이 한 번에(원자적으로) 이루어지도록 합니다.umask를 적절히 설정하여 타인이 접근하지 못하게 합니다.printf, fprintf, sprintf 등 포맷 스트링을 사용하는 함수에서 입력값 검증을 제대로 하지 않을 때 발생합니다.
개발자의 사소한 코딩 습관 차이가 치명적인 결과를 낳습니다.#include <stdio.h>
int main(int argc, char *argv[]) {
if (argc < 2) return 1;
// [취약] 사용자의 입력을 포맷 인자 없이 그대로 출력
// 사용자가 "%x" 같은 문자를 입력하면 메모리 내용이 출력됨
printf(argv[1]);
// [안전] 포맷 스트링을 명시적으로 지정
// 사용자가 "%x"를 입력해도 단순 문자열로 출력됨
printf("%s", argv[1]);
return 0;
}printf(argv[1]))에 사용자가 %x나 %n 같은 포맷 문자를 입력하면, 프로그램은 이를 문자가 아닌 %x%x%x...)하면 스택에 저장된 민감한 정보(Canary 값, RET 주소, 암호화 키 등)를 유출할 수 있습니다. (AAAA%x를 주입했다고 가정해 봅시다.printf("AAAA%x")를 실행합니다.AAAA가 출력됩니다.%x를 만나면, printf 함수는 스택에서 다음 4바이트 값을 가져와 16진수로 출력합니다.AAAA61ff0c 처럼 메모리 값이 노출됩니다.%n을 사용한다면, 공격자가 원하는 주소(예: %s)을 명시해야 합니다.// [X] 위험: 사용자가 포맷 문자를 넣으면 그대로 실행됨
printf(user_input);
// [O] 안전: 사용자가 입력한 내용을 단순 문자열로 취급함
printf("%s", user_input);%n 사용을 제한하는 옵션을 제공하기도 합니다.
하지만 가장 확실한 것은 시큐어 코딩입니다.printf 함수에 포맷 인자를 지정하지 않았을 때 발생합니다.
%x로 메모리를 읽고, %n으로 메모리를 변조하여 시스템을 장악할 수 있습니다."%s")을 명시하는 것입니다.다음 시간에는 시스템 공격의 결정체인 악성코드를 다루는1.8 악성코드 분석: 웜, 바이러스, 랜섬웨어 비교편을 진행하겠습니다. 비슷해 보이지만 확연히 다른 악성코드들의 전파 방식과 특징을 명확히 구분해 보겠습니다.