flawopen.com/Path Traversal/Node.js path.join()
Node.js path.join()으로 Path Traversal을 막을 수 있나요?
참고 페이지
짧은 답변
아니요. path.join()은 경로 세그먼트를 정규화하지만 ..이 의도한 디렉터리 밖으로 나가는 것을 막지 않습니다. 후보 경로를 기준 디렉터리에서 resolve한 뒤 상대 경로가 내부에 남는지 확인하세요. 이 문자열 기반 검사만으로 파일 시스템 심볼릭 링크를 제한할 수는 없습니다.
여전히 취약
const filePath = path.join( BASE_DIR, userFilename ); // userFilename = "../../etc/passwd" // still escapes BASE_DIR
수정됨 — 문자열 기준 포함 검사
const base = path.resolve(BASE_DIR);
const resolved = path.resolve(base, userFilename);
const relative = path.relative(base, resolved);
if (
relative === '' ||
relative === '..' ||
relative.startsWith('..' + path.sep) ||
path.isAbsolute(relative)
) {
throw new Error("Invalid path");
}
path.join()만으로 충분하지 않은 이유
path.join()은 플랫폼 구분자로 경로 세그먼트를 결합하고 결과를 정규화합니다. 여러 경로에서 유효한 ..은 거부하지 않습니다. ../../etc/passwd를 기준 경로와 결합해도 바깥 경로가 될 수 있으므로 join()은 포함 여부를 검사하지 않습니다.
자주 묻는 질문
path.normalize()를 쓰면 도움이 되나요?
path.normalize()는 문자열의 .. 및 . 세그먼트를 정리하지만 결과가 허용된 기준 경로 안에 있는지 확인하지 않습니다. path.relative(base, resolved)를 비교하고 파일이 필요한 경우 빈 결과를 거부하세요. .., .. 뒤에 path.sep이 오는 접두사, 절대 상대 결과도 거부해야 합니다.
이 검사가 심볼릭 링크 탈출도 막나요?
아닙니다. path.resolve()와 path.relative()는 경로 문자열만 비교하며 파일 시스템 심볼릭 링크를 따라가지 않습니다. 공격자가 기준 디렉터리 안에 링크를 만들거나 바꿀 수 있다면 실제 대상을 검증하고 검사와 사용 사이의 경쟁을 막는 파일 접근 방식을 쓰세요. 가능하면 디렉터리 트리의 쓰기 권한을 제한하세요.