파일 검사 후 사용 사이의 경쟁 조건

파일 검사 후 사용 사이의 경쟁 조건

설명

파일 이름으로 존재 여부나 접근 가능 여부를 검사한 뒤 같은 경로를 다시 열거나 쓰면 검사와 사용 사이에 공격자가 파일을 바꿀 수 있습니다. 특히 임시 디렉터리나 공유 디렉터리에서는 심볼릭 링크 또는 선점 생성으로 의도하지 않은 파일을 덮어쓸 수 있습니다.

잠재적 영향

  • 공격자가 검사 이후 대상 경로를 심볼릭 링크로 바꿔 민감 파일을 덮어쓰게 만들 수 있습니다.
  • 존재 여부 검사와 파일 생성 사이에 다른 프로세스가 파일을 선점할 수 있습니다.
  • 읽기 전 검사 결과가 실제 사용 시점의 파일 상태와 달라 정보 노출 또는 권한 우회가 발생할 수 있습니다.

해결 방법

  • 파일 이름 재검사 대신 파일 디스크립터 기반 API를 사용하세요.
  • 새 파일 생성에는 O_CREAT | O_EXCL 같은 원자적 플래그를 사용하세요.
  • 임시 파일은 안전한 전용 API와 비공개 디렉터리에서 생성하세요.

예시

변경 전

javascript
const fs = require("fs");
const os = require("os");
const path = require("path");

const targetPath = path.join(os.tmpdir(), "report.txt");
if (!fs.existsSync(targetPath)) {
  fs.writeFileSync(targetPath, "report");
}

변경 후

javascript
const fs = require("fs");
const os = require("os");
const path = require("path");

const targetPath = path.join(os.tmpdir(), "report.txt");
const fd = fs.openSync(
  targetPath,
  fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY,
  0o600,
);
try {
  fs.writeFileSync(fd, "report");
} finally {
  fs.closeSync(fd);
}

설명:

  • 변경 전: existsSync 검사 이후 writeFileSync를 호출하기 전까지 대상 경로가 바뀔 수 있습니다.
  • 변경 후: 원자적 생성 플래그로 검사와 생성을 하나의 파일 시스템 연산으로 처리합니다. 경로가 이미 있으면 실패하므로 호출하는 코드에서 오류를 처리해야 합니다.

참조