
CakePHP 5.4.2 - 高 - リモート - アンシリアライズ - キャッシュエンジンがクラス許可リストなしでオブジェクトをアンシリアライズする
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · cakephp-cache-unserialize
解説記事: https://abraxaslabs.tech/research/cakephp-cache-unserialize
クラス: オブジェクトインジェクション 到達範囲: リモート (Redis/Memcached への書き込み) / ローカル (FileEngine)
CakePHP 5.4.2 (887b641) - Cake Software Foundation
5.3.7 ではこの理由から Redis の allowedClasses が追加されましたが、後方互換性のためにデフォルトは true (すべて許可) のままでした。RedisEngine は、そのデフォルトが維持されている場合、依然として素の unserialize() を呼び出します。FileEngine には許可リストがまったくありません。MemcachedEngine は依然として serialize のデフォルトを php にしています。
Redis 上で cake_ キーを SET できる者、またはキャッシュファイルを書き込める者は、シリアライズされたオブジェクトを仕込みます。次回の Cache::read (または CacheSession のロード) が、それを PHP ワーカー内で実行します。
| ID | CVE 未割当 |
| クラス | オブジェクトインジェクション |
| 到達範囲 | 攻撃者から Redis または Memcached に書き込み可能な場合は リモート。tmp/cache 上の FileEngine の場合は ローカル。 |
| CWE | CWE-502 |
| CVSS | High: 8.8 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H (キャッシュストアへの書き込みが必要)。FileEngine は AV:L。 |
| 製品 | CakePHP |
| 影響を受けるバージョン | 5.4.2 (887b641de9f7aba06071f98f17edcbc573cbcf63) |
| 認証 | キャッシュストアへの書き込み (Redis SET、Memcached set、またはキャッシュファイル)。ロックダウンされた localhost の Redis に対する未認証 HTTP ではありません。 |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1 のみ |
アプリケーションのキャッシュにシリアライズされたオブジェクトを仕込みます。次回の読み取りが、PHP ワーカー内でそれを実行します。このラボは証跡ファイルを書き込むところで止まります。ガジェットチェーンやシェルの実証は行いません。
ラボで実証済み (完全性)
cake_<key> を SET してから Cache::read。 デフォルトのプレフィックスは cake_ です。RedisEngine の unserialize() は、allowedClasses がデフォルトの true の場合、素の unserialize($value) を使用します。LabMarker としてインスタンス化された仕込み済みの LabMarker オブジェクトの __wakeup が、PHP の UID で証跡ファイルを書き込みました。{expiry}\n{serialize($obj)} を仕込む。 FileEngine::get() は依然として素の unserialize($data) を呼び出します。同じマーカー、同じ証跡。ファイル名は prefix にキーを加えたもの (cake_labfile) です。allowedClasses => false はオブジェクトを拒否する。 同じ Redis ペイロードは __PHP_Incomplete_Class として返されました。__wakeup は実行されませんでした。証跡ファイルは存在しませんでした。推測 (ここでは実証していない)
defaults => cache の場合、CacheSession::read も同じシンクです。すべてのセッションロードが、攻撃者が制御するキャッシュバイトの unserialize になります。serialize => php も同種のバグです。このラボでは Memcached を起動していません。対象外 / この残存問題ではないもの
cakephp/app に対する未認証 HTTP。allowedClasses => false (または厳格なリスト) は、運用者が設定すればすでにオブジェクトをブロックします。ただしそれはデフォルトではありません。同じピン留めの残り: window SQLi、collate SQLi、attachment CRLF。
2026年の FunctionsBuilder / jsonValue / Smtp CRLF / View element の波の後、cakephp/cakephp 5.4.2 をピン留めしました。RedisEngine はこのオプションを文書化していながら、依然としてデフォルトで開いたままです:
* - `allowedClasses` ... Defaults to `true` (allow all) for backwards compatibility.
...
'allowedClasses' => true,
Read path:
protected function unserialize(string $value): mixed
{
if (preg_match('/^[-]?\d+$/', $value)) {
return (int)$value;
}
$allowedClasses = $this->getConfig('allowedClasses');
if ($allowedClasses !== true) {
return unserialize($value, ['allowed_classes' => $allowedClasses]);
}
return unserialize($value);
}
FileEngine には同等のオプションがありません:
if ($data !== '' && !empty($this->_config['serialize'])) {
$data = unserialize($data);
誤った方向性はすでに記録済みである。ロックダウンされた localhost Redis を未認証 HTTP RCE として扱うこと、ガジェットチェーンを出荷すること、FileEngine をリモートと主張すること、リバースシェル。すべて芝居である。オラクルは、フラグファイルを書き込むマーカー __wakeup である。
python3 cakephp-cache-unserialize-Abraxas-Labs.py
または
cd lab
./run.sh
対象は 127.0.0.1:19470 のみ。Docker 内でタグ 5.4.2 から起動した実際の CakePHP 5.4.2。Redis 7 は protected-mode を無効化しているため、ホストから SET が可能。PHP 8.3 に ext-redis を導入済み。マーカークラス LabMarker は __wakeup を持ち、/tmp/CAKEPHP-CACHE-UNSERIALIZE-WITNESS に書き込む。シェルはなし。
SUCCESS cakephp-cache-unserialize redis-default-wakeup=yes redis-denied-wakeup=no file-wakeup=yes pin=5.4.2 sha=887b641de9f7aba06071f98f17edcbc573cbcf63 how=live CAKEPHP-CACHE-UNSERIALIZE-WITNESS
Redis の allowedClasses をデフォルトで false にするか、アプリが実際に保存するクラスの厳格なリストに設定します。同じオプションを FileEngine に追加し、get() でそれを尊重します。Memcached の serialize をデフォルトで json にします。CacheSession がキャッシュエンジンの unserialize ポリシーを継承することを文書化します。
887b641de9f7aba06071f98f17edcbc573cbcf63)RedisEngine.php · FileEngine.phpGNU Affero GPL v3.0。LICENSE を参照してください。ループバックラボ専用です。保証はありません。