CakePHP 5.4.2 - Alto - Remoto - Unserialize - i motori di cache deserializzano oggetti senza allowlist di classi
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · cakephp-cache-unserialize
Classe: Object injection Reach: Remoto (scrittura Redis/Memcached) / Locale (FileEngine)
CakePHP 5.4.2 (887b641) - Cake Software Foundation
La 5.3.7 ha aggiunto allowedClasses per Redis proprio per questo motivo e ha lasciato il default a true (consenti tutto) per retrocompatibilità. RedisEngine chiama ancora unserialize() nudo quando vale quel default. FileEngine non ha alcuna allowlist. MemcachedEngine ha ancora serialize impostato di default a php.
Chi può impostare una chiave cake_ su Redis, o scrivere un file di cache, piazza un oggetto serializzato. La successiva Cache::read (o un caricamento CacheSession) lo esegue nel worker PHP.
| ID | nessuna CVE al momento |
| Classe | Object injection |
| Reach | Remoto quando Redis o Memcached sono scrivibili dall'attaccante. Locale per FileEngine su tmp/cache. |
| CWE | CWE-502 |
| CVSS | Alto: 8.8 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H (richiede scrittura sul cache store). FileEngine è AV:L. |
| Prodotto | CakePHP |
| Affetto | 5.4.2 (887b641de9f7aba06071f98f17edcbc573cbcf63) |
| Auth | scrittura sul cache store (Redis SET, Memcached set, o un file di cache). Non HTTP non autenticato verso un Redis localhost bloccato. |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1 |
Piazzare un oggetto serializzato nella cache dell'app. La lettura successiva esegue PHP nel worker. Questo lab si ferma a un file testimone. Non dimostra una gadget chain né una shell.
Dimostrato nel lab (integrità)
cake_<key> poi Cache::read. Il prefisso di default è cake_. unserialize() di RedisEngine usa unserialize($value) nudo quando allowedClasses è il default true. Un oggetto LabMarker piazzato, istanziato come LabMarker, e __wakeup ha scritto il file testimone con l'UID PHP.{expiry}\n{serialize($obj)} sotto il percorso di cache. FileEngine::get() chiama ancora unserialize($data) nudo. Stesso marker, stesso testimone. Il nome del file è prefix più la chiave (cake_labfile).allowedClasses => false rifiuta gli oggetti. Lo stesso payload Redis è tornato come __PHP_Incomplete_Class. __wakeup non è stato eseguito. Il file testimone era assente.Inferito (non esercitato qui)
CacheSession::read è lo stesso sink quando la sessione ha defaults => cache. Ogni caricamento di sessione diventa un unserialize di byte di cache controllati dall'attaccante.serialize => php è la stessa classe di bug. Questo lab non ha avviato Memcached.Chiuso / non questo residuo
cakephp/app stock che non espone Redis.allowedClasses => false (o una lista ristretta) blocca già gli oggetti quando un operatore lo imposta. Non è il default.Altri residui dello stesso pin: window SQLi, collate SQLi, attachment CRLF.
Ho fissato cakephp/cakephp 5.4.2 dopo l'ondata 2026 di FunctionsBuilder / jsonValue / Smtp CRLF / View element. RedisEngine documenta l'opzione e la lascia comunque aperta di default:
* - `allowedClasses` ... Defaults to `true` (allow all) for backwards compatibility.
...
'allowedClasses' => true,
Percorso di lettura:
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 non ha un'opzione equivalente:
if ($data !== '' && !empty($this->_config['serialize'])) {
$data = unserialize($data);
Vicoli ciechi già registrati: trattare un Redis localhost bloccato come RCE HTTP non autenticato; distribuire una gadget chain; sostenere che FileEngine sia remoto; una reverse shell. Teatro. L'oracolo è un marker __wakeup che scrive un file flag.
python3 cakephp-cache-unserialize-Abraxas-Labs.py
oppure
cd lab
./run.sh
Target solo 127.0.0.1:19470. CakePHP 5.4.2 live dal tag 5.4.2 dentro Docker. Redis 7 con protected-mode off così l'host può fare SET. PHP 8.3 con ext-redis. Classe marker LabMarker con __wakeup che scrive /tmp/CAKEPHP-CACHE-UNSERIALIZE-WITNESS. Nessuna 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
Impostare allowedClasses di Redis di default a false, o a una lista ristretta di classi che l'app memorizza effettivamente. Aggiungere la stessa opzione a FileEngine e rispettarla in get(). Impostare serialize di Memcached di default a json. Documentare che CacheSession eredita la policy di unserialize del cache engine.
887b641de9f7aba06071f98f17edcbc573cbcf63)RedisEngine.php · FileEngine.phpGNU Affero GPL v3.0. Vedi LICENSE. Solo lab su loopback. Nessuna garanzia.