2016-06-16 2 views
1

Я пишу (expressjs) http-сервис, который получает относительный путь как пользовательский ввод для каждого вызова, считывает файл из файловой системы на основе этого пути и обрабатывает его, например:Safe path.resolve без выхода из родителя

app.get("/api", (req, res, next) => { 
    var filePath = path.resolve("./datasource", req.query.path); 
    fs.readFile(filePath, "utf8", (err, data) => { 
     processData(data, (err, processed) => { 
      res.json(processed); 
     }); 
    }); 
}); 

Устранение ошибок для ясности. Проблема заключается в том, что можно вызвать URL /api?path=../../../etc/passwd, и это приведет к утечке информации с самого сервера. Я бы хотел, чтобы этот api не обрабатывал файлы за пределами папки ./datasource. Я думаю, что я мог бы использовать некоторую индивидуальную реализацию path.resolve, которая не позволяет родителям, но похоже, что в модуле path такой функции нет. Некоторые примеры я думал:

saferesolve("./datasource", "a/b") === "./datasource/a/b" 
saferesolve("./datasource", "a/b/../c") === "./datasource/a/c" 
saferesolve("./datasource", "../..") === "./datasource" 
saferesolve("./datasource", "../../a/b") === "./datasource/a/b" 
saferesolve("./datasource", "../../a/b/..") === "./datasource/a" 

Любые идеи, как это сделать, не изобретая весь path модуль?

ответ

2

Это, кажется, проходит тесты:

function saferesolve(base, target) { 
    var targetPath = '.' + path.posix.normalize('/' + target) 
    return path.posix.resolve(base, targetPath) 
} 
+0

Я чувствую себя хорошо об этом подходе, но не работает на окнах. Возможно, использование 'path.posix.resolve' было бы лучше. –

+0

@TamasHegedus Я обновил свой ответ, чтобы добавить бит '.posix' в каждый вызов метода' path', но у меня нет доступа к компьютеру с Windows, чтобы вы могли сообщить мне, что для вас результат? Мне просто интересно, что происходит. – idbehold

+0

Отлично, спасибо, я думаю, это то, что я искал! –

Смежные вопросы