アプリ開発ときどきアウトドア

主にJavaを使ったアプリ開発やトラブルシューティング等のノウハウ、キャンプや登山の紹介や体験談など。

1. システムエンジニアリング Java

Javaにおけるファイルパスの正規化

投稿日:


サーバ側でのzipファイルの解凍等の際に、意図しないディレクトリやファイル(ディレクトリトラバーサル攻撃)へのアクセスを防ぐための検証として、絶対パスを正規化したい場合がある。
Fileクラスを使ったサンプルはあるが、Pathを使ったサンプルがなかったため、検証してみた。

検証結果

結果として次の通りでした。
検証で使ったコードは次節を参照のこと。

  • Fileクラスを使う場合、File#getCanonicalPath()で絶対パスを正規化できる。File#getAbsolutePath()は正規化されず、., ..が残るので注意。
  • Pathクラスを使う場合、normalize()で正規化できそうだが、相対パスで帰ってくる場合があるので、絶対パスに変換してから正規化(path.toAbsolutePath().normalize())が必要である。実在パスの検証がされても良いのであれば、path.toRealPath()を使用できる。
    実在検証 パス種別 コード例 備考
    不要 絶対パス path.toAbsolutePath().normalize()
    相対パス path.normalize()
    必要 絶対パス path.toRealPath() パスが実在しない場合、NoSuchFileExceptionがスローされる。
    相対パス (該当なし)

検証コードと実行結果

検証で使ったサンプルコードや実行結果を記載します。
サンプルで使用するパスには動作確認のためにスラッシュとバックスラッシュを混在させています。

package example;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

public class FilePathTest {

	public static void main(String[] args) throws IOException{

		String str1 = "C:\\test\\work1\\.\\work1-1/..\\..\\work2";
		String str2 = ".\\work1\\.\\work1-1/..\\..\\work2";
		
		System.out.println("original               : " + str1);
		File f1 = new File(str1);
		System.out.println("File.getPath()         : " + f1.getPath());
		System.out.println("File.getAbsolutePath() : " + f1.getAbsolutePath());
		System.out.println("File.getCanonicalPath(): " + f1.getCanonicalPath());
		Path p1 = Paths.get(str1);
		System.out.println("Path.toString()        : " + p1.toString());
		System.out.println("Path.toAbsolutePath()  : " + p1.toAbsolutePath());
		System.out.println("Path.normalize()       : " + p1.normalize());
		System.out.println("Path.toRealPath()      : " + p1.toRealPath());
		
		System.out.println();

		System.out.println("original               : " + str2);
		File f2 = new File(str2);
		System.out.println("File.getPath()         : " + f2.getPath());
		System.out.println("File.getPath()         : " + f2.toString());
		System.out.println("File.getAbsolutePath() : " + f2.getAbsolutePath());
		System.out.println("File.getCanonicalPath(): " + f2.getCanonicalPath());
		Path p2 = Paths.get(str2);
		System.out.println("Path.toString()        : " + p2.toString());
		System.out.println("Path.toAbsolutePath()  : " + p2.toAbsolutePath());
		System.out.println("Path.normalize()       : " + p2.normalize());
		System.out.println("Path.toRealPath()      : " + p2.toRealPath()); // NoSuchFileException
		System.out.println("Path other             : " + p2.toAbsolutePath().normalize());

	}

}

実行結果は次の通り。
Path.toRealPath()は実行時に該当パスがないとNoSuchFileException例外がスローされます。

original               : C:\test\work1\.\work1-1/..\..\work2
File.getPath()         : C:\test\work1\.\work1-1\..\..\work2
File.getAbsolutePath() : C:\test\work1\.\work1-1\..\..\work2
File.getCanonicalPath(): C:\test\work2
Path.toString()        : C:\test\work1\.\work1-1\..\..\work2
Path.toAbsolutePath()  : C:\test\work1\.\work1-1\..\..\work2
Path.normalize()       : C:\test\work2
Path.toRealPath()      : C:\test\work2

original               : .\work1\.\work1-1/..\..\work2
File.getPath()         : .\work1\.\work1-1\..\..\work2
File.getPath()         : .\work1\.\work1-1\..\..\work2
File.getAbsolutePath() : C:\jee7devkit\workspace\example\java-example\.\work1\.\work1-1\..\..\work2
File.getCanonicalPath(): C:\jee7devkit\workspace\example\java-example\work2
Path.toString()        : .\work1\.\work1-1\..\..\work2
Path.toAbsolutePath()  : C:\jee7devkit\workspace\example\java-example\.\work1\.\work1-1\..\..\work2
Path.normalize()       : work2
Path.toRealPath()      : C:\jee7devkit\workspace\example\java-example\work2
Path other             : C:\jee7devkit\workspace\example\java-example\work2


(adsbygoogle = window.adsbygoogle || []).push({});


(adsbygoogle = window.adsbygoogle || []).push({});

-1. システムエンジニアリング, Java

執筆者:

関連記事

パスワード情報の保管方式の比較

Webアプリの開発でパスワードを使ったユーザ認証を設計・実装する機会がよくある。 後輩への説明や勉強会ネタとして、この辺の話を纏めてみようと思う。 概要 オンラインバンキングやネットショッピングのサイ …

PowerPointの削除できない個人情報を消す

PowerPointで「個人情報の削除」を実行するとこで、作成者や会社名等の個人情報を削除できます。しかしながら、特定の項目に入った個人情報については、PowerPointやWindowsの標準機能で …

Webアプリテスト用のHTTPヘッダの追加

フロントに配置されたリバースプロキシサーバやロードバランサで設定されたHTTPヘッダを使用するWebアプリを開発することが多々あります。 このようなシナリオでは、設計に基づいて実装することはできますが …

OfficeアプリのコントロールはPowerShellかVBAか?

Windowsサーバの監視のお仕事での話です。 月次で各サーバのパフォーマンスモニタのログファイル(.blg)が送られてきます。このデータ群から、各種のグラフや表を作成して、PowerPointでそれ …

CentOS7のマルチホーム化

サイトの存在を隠しつつも、sftpサーバを公開し、後輩と1G以上のファイルのやりとりしたい。 パブリック側のIPアドレスを教えてしまうと、どこのサーバだろうかとブラウザで開いたりするとサイトの存在がわ …

プロフィール ゆっきーです。
都内でシステムエンジニアをやっています。
もっと詳細を見る