flawopen.com/Path Traversal/Node.js path.join()
Защищает ли Node.js path.join() от Path Traversal?
Нет. path.join() нормализует сегменты, но не мешает .. выйти за пределы целевого каталога. Разрешите кандидатный путь относительно базового и проверьте, что относительный путь остаётся внутри. Эта лексическая проверка не учитывает символические ссылки файловой системы.
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.relative(base, resolved) и отклоняйте пустой результат, если требуется файл, .., префикс .. с path.sep и абсолютный относительный результат.
Нет. path.resolve() и path.relative() сравнивают строки и не переходят по символическим ссылкам файловой системы. Если атакующий может создавать или заменять ссылки внутри базы, проверяйте реальную цель и предотвращайте гонку между проверкой и использованием. По возможности ограничьте запись в дерево каталогов.