2016-06-16 9 views
1

私は(expressjs)httpサービスを書いています。これは、あらゆる呼び出し時にユーザー入力として相対パスを取得し、そのパスに基づいてファイルシステムからファイルを読み込み、安全なパス。親から逃げないで解決してください

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を呼び出して、サーバー自体から情報が漏れることがあるということです。私は./datasourceフォルダの外のファイルを処理しないようにこのapiを望みます。私は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

私はこのアプローチについて良い感じていますが、Windows上では動作しません。たぶん 'path.posix.resolve'を使用する方が良いでしょう。 –

+0

@TamasHegedusそれぞれの 'path'メソッド呼び出しに' .posix'ビットを追加する答えを更新しましたが、Windowsコンピュータにアクセスできないので、出力があなたのものであることを教えてください。私は何が起きているのか不思議です。 – idbehold

+0

すごく、ありがとう、私はそれが私が探していたと思います! –

関連する問題