Important: #108604 - Mitigate deserialization flaws
See forge#108604
Description
TYPO3 introduces new serialization infrastructure to protect against PHP object injection attacks. Two complementary strategies are applied depending on how long the serialized data lives:
Cache frontend (
Variable) — HMAC-authenticated serialization
\TYPO3\ (the default cache
frontend) now uses
\TYPO3\ for both
writing and reading cache entries. On every
set call the payload is
serialized and an HMAC is appended; on every
get call the HMAC is
validated before deserialization proceeds.
Because caches are temporary and written exclusively by the server that reads them, this approach provides a strong integrity guarantee: an attacker cannot craft a malicious serialized payload that the server would accept, since they cannot forge the HMAC without knowing the encryption key.
Cache entries written by an older TYPO3 version (without an HMAC) are handled
gracefully: if the payload contains no PHP class tokens it is deserialized
safely with
allowed_; if it does contain class tokens it
is discarded and treated as a cache miss, causing the entry to be regenerated
transparently.
Registry (
\TYPO3\) — gadget denylist
\TYPO3\ (the persistent key-value store backed by the
sys_ table) deserializes stored payloads through
\TYPO3\. Before deserialization
the class names embedded in the payload are checked against a gadget deny list.
The deny/allow decision for each class is resolved lazily via
\Reflection on first encounter and then cached in
cache:
(HMAC-signed for integrity) so that reflection is not repeated for the same
class within a cache lifetime. A class is considered a gadget when it carries a
user-defined
__ or an exploitable
__ — that is,
a
__ not provided solely by
\TYPO3\. If any gadget class is
referenced in a payload, a
\TYPO3\ is thrown and
deserialization is aborted.
A denylist strategy (block known-bad, allow unknown) is used intentionally for the registry to avoid breaking changes to long-lived persisted data.
Impact
Cache (
Variable)
Existing cache entries that contain serialized PHP objects will be treated as cache misses on the next read. No exception is thrown; the entry is simply discarded and the cache is repopulated on the next request. This is transparent to callers.
Registry
Extensions or third-party code that stores serialized PHP objects in
Registry may encounter a
Deserializer at read time if
the serialized object graph contains a class with a user-defined
__ or
__ method.
Migration & Insights
In most cases no migration is required. The sections below aim to provide some insights into internal details and general suggestions.
Cache (
Variable)
No migration is required. Stale or legacy cache entries are automatically
treated as misses and regenerated. If code stores object graphs in a
Variable-backed cache it will continue to work as long as the
server reads the entry it wrote (same encryption key).
Registry — preferred approach: avoid object serialization
Review what is stored in the registry. Plain PHP arrays and scalar values are not affected by this protection and should be preferred over serialized object graphs wherever possible.
Registry — alternative: restructure the stored value
If an object must be stored, ensure that neither the object itself nor any
object reachable from it through public or serialized properties carries a
user-defined
__ or
__ method.
Registry — last resort: explicit class allowlist
If neither of the above is feasible in the short term, the affected class can be
added to the site-level allowlist in config/ (or
the legacy typo3conf/):
$GLOBALS['TYPO3_CONF_VARS']['SYS']['deserialization']['allowedClassNames'][] =
\Vendor\MyExtension\Domain\Model\MyObject::class;
Warning
The allowlist setting bypasses the deserialization gadget protection for
the listed classes. It should only be used as a last resort after carefully
reviewing the class and confirming that its
__ or
__ implementation cannot be abused in a PHP object injection
attack chain. Remove the entry as soon as the underlying serialization is
refactored.