GHSA-2ff2-mx52-q8wp
October CMS: PHP Object Injection via Backend Widget Session Storage
Packages
| Ecosystem | Package | Affected | Fixed in |
|---|---|---|---|
| Packagist | october/system | < 3.7.17 | 3.7.17 |
| Packagist | october/system | >= 4.0.0, < 4.2.23 | 4.2.23 |
Details
As written in the advisory (Markdown source, shown as plain text).
The backend `SessionMaker` trait stored widget session state as `base64(serialize(...))` and consumed it with `unserialize()` without an `allowed_classes` restriction. Any code path that could write to a `widget.*` session key with attacker-controlled bytes could trigger PHP object injection the next time the widget read its session state, allowing instantiation of arbitrary classes and reachable PHP gadget chains.
**This issue only affects installations running with `cms.safe_mode` enabled.** Safe Mode is a niche opt-in feature, primarily used for demo installations and multi-tenant or shared-editor scenarios where untrusted users are deliberately granted access to the CMS markup editor. In standard production deployments Safe Mode is off, backend access is restricted to trusted administrators, and a markup editor can already execute arbitrary PHP directly. The session-write path that reaches this sink is gated by the Safe Mode sandbox, so installations without Safe Mode enabled are not exposed.
**Scope of impact is narrow even with Safe Mode enabled.** The standard backend code paths that populate widget session state (search terms, sort options, selected IDs, filter values) wrap the input inside a known array shape before serializing, so user-supplied values never reach `unserialize()` as a controllable serialized payload. Exploitation requires the Safe Mode session-write path together with a suitable PHP gadget chain reachable from the installed dependency set. The hardening below removes the underlying object-injection sink so the class of issue is closed off regardless.
### Impact
- Arbitrary PHP code execution as the web server user, via a gadget chain deserialized from a widget session key, triggered the next time the affected widget is rendered
- Requires `cms.safe_mode` to be enabled, and a backend user with CMS markup editing access who is not intended to be trusted as a full administrator
- A suitable PHP gadget chain must be reachable from the installed dependency set
- Not exploitable when Safe Mode is disabled
### Patches
The vulnerability has been patched in v3.7.17 and v4.2.21. Two changes were applied:
- `Backend\Traits\SessionMaker` now stores widget session state as plain JSON instead of `base64(serialize(...))`, eliminating the object-injection sink entirely for new writes. Reads transparently fall back to the legacy format for one upgrade cycle so existing sessions retain their saved widget state.
- The legacy `unserialize()` fallback path now sets `allowed_classes => false`, so even values written before the upgrade cannot instantiate objects.
### Workarounds
If upgrading immediately is not possible, restrict CMS markup editing access to fully trusted administrators only, the standard October CMS recommendation for any deployment.
### References
- Reported by EndlssNightmare
References
External links from the advisory. They lead to third-party sites.