CakePHP 5.4.2 – Hoch – Remote – Unserialize – Cache-Engines deserialisieren Objekte ohne Klassen-Allowlist
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · cakephp-cache-unserialize
Klasse: Object Injection Reichweite: Remote (Redis/Memcached Write) / Lokal (FileEngine)
CakePHP 5.4.2 (887b641) - Cake Software Foundation
5.3.7 fügte Redis allowedClasses aus diesem Grund hinzu und beließ den Standardwert aus Gründen der Abwärtskompatibilität bei true (alle erlauben). RedisEngine ruft weiterhin blankes unserialize() auf, wenn dieser Standardwert gilt. FileEngine hat überhaupt keine Allowlist. MemcachedEngine setzt serialize weiterhin standardmäßig auf php.
Wer einen cake_-Schlüssel auf Redis SETZEN oder eine Cache-Datei schreiben kann, platziert ein serialisiertes Objekt. Der nächste Cache::read (oder ein CacheSession-Ladevorgang) führt es im PHP-Worker aus.
| ID | noch keine CVE |
| Klasse | Object Injection |
| Reichweite | Remote, wenn Redis oder Memcached vom Angreifer beschreibbar ist. Lokal für FileEngine unter tmp/cache. |
| CWE | CWE-502 |
| CVSS | Hoch: 8.8 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H (erfordert Schreibzugriff auf den Cache-Store). FileEngine ist AV:L. |
| Produkt | CakePHP |
| Betroffen | 5.4.2 (887b641de9f7aba06071f98f17edcbc573cbcf63) |
| Auth | Schreibzugriff auf den Cache-Store (Redis SET, Memcached set oder eine Cache-Datei). Kein unauthentifiziertes HTTP auf ein abgeriegeltes localhost-Redis. |
| Lizenz | GNU Affero GPL v3.0 |
| Lab | nur 127.0.0.1 |
Ein serialisiertes Objekt im App-Cache platzieren. Der nächste Lesevorgang führt PHP im Worker aus. Dieses Lab endet bei einer Witness-Datei. Es demonstriert keine Gadget-Chain und keine Shell.
Im Lab nachgewiesen (Integrität)
cake_<key> dann Cache::read. Standardpräfix ist cake_. RedisEngine unserialize() verwendet blankes unserialize($value), wenn allowedClasses den Standardwert true hat. Ein platziertes LabMarker-Objekt, instanziiert als LabMarker, und __wakeup schrieb die Witness-Datei als PHP-UID.{expiry}\n{serialize($obj)} unter dem Cache-Pfad. FileEngine::get() ruft weiterhin blankes unserialize($data) auf. Gleicher Marker, gleiche Witness. Der Dateiname ist prefix plus Key (cake_labfile).allowedClasses => false verweigert Objekte. Dieselbe Redis-Payload kam als __PHP_Incomplete_Class zurück. __wakeup wurde nicht ausgeführt. Die Witness-Datei fehlte.Abgeleitet (hier nicht ausgeführt)
CacheSession::read ist derselbe Sink, wenn Session defaults => cache gesetzt ist. Jeder Session-Ladevorgang wird zu einem Unserialize von angreiferkontrollierten Cache-Bytes.serialize => php ist dieselbe Fehlerklasse. Dieses Lab hat Memcached nicht gestartet.Geschlossen / nicht dieser Rest
cakephp/app, das Redis nicht exponiert.allowedClasses => false (oder eine enge Liste) blockiert Objekte bereits, wenn ein Betreiber es setzt. Es ist nicht der Standard.Weitere Reste desselben Pins: window SQLi, collate SQLi, attachment CRLF.
Ich habe cakephp/cakephp 5.4.2 nach der Welle 2026 FunctionsBuilder / jsonValue / Smtp CRLF / View element gepinnt. RedisEngine dokumentiert die Option und lässt sie weiterhin standardmäßig offen:
* - `allowedClasses` ... Defaults to `true` (allow all) for backwards compatibility.
...
'allowedClasses' => true,
Lesepfad:
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 hat keine entsprechende Option:
if ($data !== '' && !empty($this->_config['serialize'])) {
$data = unserialize($data);
Bereits festgehaltene Irrwege: abgeriegeltes localhost-Redis als unauthentifizierte HTTP-RCE behandeln; eine Gadget-Chain ausliefern; behaupten, FileEngine sei remote; eine Reverse Shell. Theater. Das Orakel ist ein Marker-__wakeup, der eine Flag-Datei schreibt.
python3 cakephp-cache-unserialize-Abraxas-Labs.py
oder
cd lab
./run.sh
Ziel nur 127.0.0.1:19470. Live CakePHP 5.4.2 aus Tag 5.4.2 in Docker. Redis 7 mit deaktiviertem protected-mode, damit der Host SET ausführen kann. PHP 8.3 mit ext-redis. Marker-Klasse LabMarker mit __wakeup, die /tmp/CAKEPHP-CACHE-UNSERIALIZE-WITNESS schreibt. Keine Shell.
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 standardmäßig auf false setzen, oder auf eine enge Liste von Klassen, die die App tatsächlich speichert. Dieselbe Option zu FileEngine hinzufügen und sie in get() beachten. Memcached serialize standardmäßig auf json setzen. Dokumentieren, dass CacheSession die Unserialize-Richtlinie der Cache-Engine erbt.
887b641de9f7aba06071f98f17edcbc573cbcf63)RedisEngine.php · FileEngine.phpGNU Affero GPL v3.0. Siehe LICENSE. Nur Loopback-Lab. Keine Gewährleistung.