42

私は Java サーバーの実装 (問題がある場合は TFTP) を使用しており、利用できないファイルや場所へのアクセスを許可するパス トラバーサル攻撃の影響を受けないようにしたいと考えています。

これまでの防御における私の最善の試みは、一致するすべてのエントリを拒否し、パスからコンポーネントを解決することFile.isAbsolute()に依存することです。最後に、結果のパスがまだサーバーの必要なルート ディレクトリ内にあることを確認します。File.getCanonicalPath().././

public String sanitize(final File dir, final String entry) throws IOException {
    if (entry.length() == 0) {
        throw new PathTraversalException(entry);
    }

    if (new File(entry).isAbsolute()) {
        throw new PathTraversalException(entry);
    }

    final String canonicalDirPath = dir.getCanonicalPath() + File.separator;
    final String canonicalEntryPath = new File(dir, entry).getCanonicalPath();

    if (!canonicalEntryPath.startsWith(canonicalDirPath)) {
        throw new PathTraversalException(entry);
    }

    return canonicalEntryPath.substring(canonicalDirPath.length());
}

これが見逃しているセキュリティ上の問題はありますか? 同じ結果を確実に達成するためのより良い/より速いものはありますか?

コードは、Windows と Linux で一貫して機能する必要があります。

4

3 に答える 3

13

以下が役立つ場合があります。正規パスと絶対パスを比較し、それらが異なる場合は失敗します。Mac/Linux システム (Windows なし) でのみテストされています。

これは、ユーザーが絶対パスではなく相対パスを指定できるようにし、親ディレクトリの参照を許可しない場合です。

public void failIfDirectoryTraversal(String relativePath)
{
    File file = new File(relativePath);

    if (file.isAbsolute())
    {
        throw new RuntimeException("Directory traversal attempt - absolute path not allowed");
    }

    String pathUsingCanonical;
    String pathUsingAbsolute;
    try
    {
        pathUsingCanonical = file.getCanonicalPath();
        pathUsingAbsolute = file.getAbsolutePath();
    }
    catch (IOException e)
    {
        throw new RuntimeException("Directory traversal attempt?", e);
    }


    // Require the absolute path and canonicalized path match.
    // This is done to avoid directory traversal 
    // attacks, e.g. "1/../2/" 
    if (! pathUsingCanonical.equals(pathUsingAbsolute))
    {
        throw new RuntimeException("Directory traversal attempt?");
    }
}
于 2016-01-07T15:00:17.677 に答える
2

これを UNIX マシンで実行している場合 (Windows にも同様の機能があるかどうかはわかりませんが、ある可能性があります)、chroot を参照してください。誰かがいくつかのディレクトリを参照するためにすべての方法をヒットしたと思ったとしても、オペレーティング システムがその事実を強制するのは素晴らしいことです。

(chroot は「/」が他のディレクトリを参照するようにするため、「/」は「/home/me/project」であり、「/../../..」は「/home/me/project」のままである可​​能性があります。 )

編集:

chroot システム コールと chroot コマンドライン ツールがあります。Java にネイティブ メソッドがあるかどうかはわかりませんが、コマンド ライン ツールを使用してサーバーを実行することを妨げるものは何もありません。もちろん、これは、他のパス操作を防ぐために最善を尽くすことに加えて行う必要があります。

于 2010-03-03T23:48:01.430 に答える
-2

ファイル名で許可されている文字 ( http://en.wikipedia.org/wiki/Filename ) を確認し、許可されていないすべての文字を除外して (ホワイト リスト)、そこにファイル名があることを確認できます。

于 2010-03-04T09:55:23.440 に答える