Shikata Ga Nai

Private? There is no such things.

第39回:ディレクトリトラバーサルとその危険性

Hello there, ('ω')ノ

🗂️ ディレクトリトラバーサルとは?

ディレクトリトラバーサルとは、アプリがユーザー入力を使ってファイルを読み書きする際に、 攻撃者が ../(上の階層に移動する記号)を入力に混ぜることで、意図しないファイルにアクセスできてしまう攻撃です。

本来アクセスさせたくないシステムファイルや設定ファイルを読み取られたり、上書きされたりするリスクがあります。


🧪 実際の攻撃パターン

✅ 想定している使い方(安全)

String fileName = "user123.txt";
File file = new File("/data/data/com.example.app/files/" + fileName);

fileName"profile.txt" が入っていれば問題なし。

❌ 危険な使い方(トラバーサル攻撃)

String fileName = "../../../../../etc/passwd";
File file = new File("/data/data/com.example.app/files/" + fileName);

→ 実際にアクセスされるファイル: /data/data/com.example.app/files/../../../../../etc/passwd/etc/passwd


⚠️ Androidで狙われやすいファイル例

ファイルパス 内容
/data/data/com.example.app/shared_prefs/setting.xml アプリ設定ファイル
/proc/version カーネルバージョン
/system/build.prop デバイス情報
他アプリのファイル(※rootや仮想環境で) 他アプリの秘密情報

🔍 診断手順

✅ 1. ファイル操作を探す(静的解析)

MobSFやjadxを使って、以下のようなコードを探しましょう:

new File(path + fileName);
FileInputStream fis = new FileInputStream(userInput);

ユーザー入力(Intent、WebView、フォームなど)を直接パスに使っている場合は要注意。


✅ 2. 実機で試す(動的解析)

対象のファイル操作を呼び出せるボタンやAPIがある場合、入力欄に次のようなパスを試します:

../shared_prefs/setting.xml
../../../system/build.prop

エラーにならずファイルの中身が表示される場合は脆弱性の可能性大です。


🛡️ 対策方法

対策 内容
ファイル名を検証する "../""/" を含まないかをチェックする
ファイルアクセスを固定パターンにする ユーザー名などからファイル名を生成する場合、ホワイトリスト方式にする
getCanonicalPath() で制限をかける アクセスしようとしているパスが、許可されたディレクトリ内かどうかを確認する

例:安全なパス検証

File baseDir = new File("/data/data/com.example.app/files/");
File targetFile = new File(baseDir, userInput);
if (!targetFile.getCanonicalPath().startsWith(baseDir.getCanonicalPath())) {
    throw new SecurityException("不正なファイルアクセスです");
}

🧠 よくある実例

ケース 被害
アップロードされたファイル名を信じて保存 他のファイルを上書きされる
URLパラメータからファイルを読み込む 任意のファイルを読まれて情報漏洩
バックアップ機能で外部ストレージから復元 改ざんされた設定ファイルが読み込まれる

✅ まとめ

  • ディレクトリトラバーサルとは、「../」で階層を遡り、本来アクセスできないファイルにアクセスする攻撃
  • 入力をパスとして扱う場面では、「その入力が安全か?」を常にチェックする必要あり
  • getCanonicalPath() などを使った安全なパスチェックが非常に有効
  • アプリのファイル操作は便利な反面、セキュリティの穴になりやすいポイントなので要注意!

Best regards, (^^ゞ