A vm-admin in XAPI-based hypervisors (XenServer, XCP-ng) can manipulate the guest VM's RTC clock by setting the timeoffset key in VDI.other_config. When a VDI has on_boot=reset, the timeoffset value from VDI.other_config overrides the VM's platform-level timeoffset setting during domain creation (xapi_xenops.ml:312-327). Arbitrary strings are accepted - no type validation enforces the expected integer format. A corrupted timeoffset causes the guest OS to boot with an incorrect clock, affecting Windows license validation, certificate expiration checks, Kerberos authentication, scheduled task execution, and audit trail integrity. The VDI.other_config field has no map_keys_roles entries for infrastructure keys.
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 timeoffset override logic at xapi_xenops.ml:312-327:
let rtc_timeoffset_of_vm ~__context ~vm =
...
if vdi.API.vDI_on_boot = `reset then
match
(List.assoc_opt Vm_platform.timeoffset record.API.vDI_other_config)
with
| Some timeoffset -> timeoffset
| None -> ...
When a VDI has on_boot=reset (common for snapshot-based VDIs), the timeoffset from VDI.other_config takes precedence over the VM platform setting. The value is expected to be an integer string representing the RTC offset in seconds from UTC, but no validation enforces this:
"not_a_number") are passed to the domain builder"999999999") shift the clock years into the futureThe attack requires the target VDI to have on_boot=reset set. This is common in environments using non-persistent VDIs or snapshot-based provisioning.
Missing type validation. The timeoffset value is expected to be an integer but any string is accepted without validation at write time.
Missing RBAC protection. VDI.other_config has map_keys_roles entries only for UI keys (folder, XenCenter.CustomFields.*). The timeoffset key is writable by any vm-admin.
VDI-level override of VM-level setting. The VDI.other_config timeoffset overrides the VM.platform timeoffset when on_boot=reset. This creates a secondary control path that bypasses any validation applied to the VM.platform field.
set_other_config RBAC bypass. The set_other_config method replaces the entire map atomically and bypasses map_keys_roles per-key checks.
| Scenario | Impact | Pre-conditions | Status |
|---|---|---|---|
| Clock shift forward | Windows license validation fails, certificates appear expired | vm-admin, VDI with on_boot=reset | Source-traced |
| Clock shift backward | Kerberos authentication fails (clock skew), scheduled tasks delayed | vm-admin, VDI with on_boot=reset | Source-traced |
| Audit trail corruption | Log entries have incorrect timestamps, breaking forensic timeline | vm-admin, VDI with on_boot=reset | Modeled |
| BOC-1 chain | vm-admin corrupts timeoffset on all reset-boot VDIs pool-wide | vm-admin, BOC-1 | Source-traced |
on_boot=reset, causing pool-wide guest clock corruption on next boot cycle.VDI.other_config writes for the timeoffset keydisclosure/vendor-detection-guidance.mdVDI.other_config entries for unexpected timeoffset valueson_boot=reset for timeoffset manipulationAdd write-time validation. Validate that timeoffset is a valid integer within a reasonable range (e.g., -86400 to 86400 seconds).
Add map_keys_roles protection. Restrict the timeoffset key to _R_POOL_ADMIN in datamodel.ml.
Upstream patches exist. They are held privately pending coordinated disclosure.
Disclosure:
datamodel.ml:6310-6315 (VDI.other_config field definition), xapi_xenops.ml:312-327 (rtc_timeoffset_of_vm - VDI timeoffset override logic)disclosure/advisories/doc-security-advisory.md (DOC-6)research/investigations/vdi-other-config.mdDiscovered and reported by Jakob Wolffhechel, Moksha.