MOKSHA-2026-0082: VDI Lifecycle Behavior Manipulation via VDI.other_config on_boot/cbt_enabled

Advisory IDMOKSHA-2026-0082
Semantic IDDOC-3
Published2026-04-24
CVSS 3.13.1 Low
CVSS 3.1 VectorAV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
CVSS 4.05.3 Medium
CVSS 4.0 VectorAV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N
XAPI ObjectVDI
XAPI Fieldother_config:on_boot, other_config:cbt_enabled
Entry Rolevm-admin
ResearcherJakob Wolffhechel, Moksha

Affected Products

VendorProductVersions
Citrix / Cloud Software GroupXenServer / Citrix Hypervisorall versions (shared XAPI codebase)
VatesXCP-ng8.3.0

Summary

A vm-admin in XAPI-based hypervisors (XenServer, XCP-ng) can modify VDI lifecycle behavior by writing to the on_boot and cbt_enabled keys in VDI.other_config. The on_boot key controls whether a VDI resets to its snapshot state on boot (used for non-persistent desktops), and cbt_enabled is an other_config mirror of the first-class CBT (Change Block Tracking) field read by SM drivers at VDI.py:831-837. Manipulation changes whether a VDI is persistent or non-persistent (data loss on reboot) and whether change block tracking is active. The VDI.other_config field has map_keys_roles entries only for UI keys (folder, XenCenter.CustomFields.*); all infrastructure keys are unprotected.

Vulnerability Description

VDI.other_config is a Map(String, String) field defined at datamodel.ml:6310-6315 with _R_VM_ADMIN as the minimum write role. The map_keys_roles entries protect only folder and XenCenter.CustomFields.* - UI keys. All infrastructure keys are writable by vm-admin.

The on_boot key interacts with the VDI reset-on-boot mechanism. When set to reset, the VDI reverts to its parent snapshot on every VM boot. XAPI reads this value at xapi_xenops.ml:312-327 in the rtc_timeoffset_of_vm function, where it determines whether to apply the timeoffset override from VDI.other_config. The on_boot behavior is primarily controlled by the first-class VDI.on_boot field, but the other_config key creates an alternative control path.

The cbt_enabled key is read by SM drivers at VDI.py:831-837 as an other_config mirror of the first-class VDI.cbt_enabled field. The SM driver checks this key during VDI operations to determine whether change block tracking is active for the VDI. A vm-admin can set cbt_enabled=true on a VDI that does not have CBT formally enabled, or cbt_enabled=false on one that does, creating inconsistency between the first-class field and the other_config mirror.

Neither key is validated at write time. Live host verification confirms arbitrary values are accepted without error.

Root Causes

  1. Missing RBAC protection. VDI.other_config has map_keys_roles entries only for UI keys. The on_boot and cbt_enabled infrastructure keys are writable by vm-admin without restriction.

  2. Dual control paths. Both on_boot and cbt_enabled have first-class VDI fields AND other_config mirrors. The other_config mirrors bypass any validation on the first-class fields.

  3. No consistency enforcement. XAPI does not verify that other_config values match the corresponding first-class fields. SM drivers read the other_config mirror directly without cross-checking.

  4. set_other_config RBAC bypass. The set_other_config method replaces the entire map atomically and bypasses map_keys_roles per-key checks.

Affected Systems

Directly Affected

Indirectly Affected

Exploitation Scenarios

Scenario Impact Pre-conditions Status
Persistence change Persistent VDI becomes non-persistent, data lost on next reboot vm-admin, VDI with snapshot Source-traced
CBT state desync SM driver reads wrong CBT state from other_config mirror vm-admin, CBT-enabled VDI Live-tested (key injection confirmed)
Reverse persistence Non-persistent VDI becomes persistent, consuming storage vm-admin, reset-on-boot VDI Source-traced
BOC-1 chain vm-admin manipulates lifecycle behavior across all VDIs via RBAC collapse vm-admin, BOC-1 Source-traced

Chaining Analysis

Detection

Remediation

Short-Term Mitigations

Long-Term Fix

Remove the other_config mirror pattern. SM drivers should read from the first-class VDI.cbt_enabled field, not from an unprotected other_config key. The other_config mirror creates a bypass path around any validation on the first-class field.

Add map_keys_roles protection. Restrict on_boot and cbt_enabled to _R_POOL_ADMIN in datamodel.ml.

Upstream patches exist. They are held privately pending coordinated disclosure.

Disclosure

Disclosure:

References

Credits

Discovered and reported by Jakob Wolffhechel, Moksha.

Jakob Wolffhechel · Moksha · Copenhagen
jakob@wolffhechel.dk · +45 3170 7337
Published 2026-04-24 08:00 CEST · cna.moksha.dk · shittrix.moksha.dk