MOKSHA-2026-0006: Storage Migration Redirection via VDI.other_config maps_to

Advisory IDMOKSHA-2026-0006
Semantic IDDOC-2
Published2026-04-24
CVSS 3.18.5 High
CVSS 3.1 VectorAV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H
CVSS 4.08.8 High
CVSS 4.0 VectorAV:N/AC:L/AT:P/PR:L/UI:N/VC:N/VI:H/VA:H/SC:H/SI:H/SA:H
XAPI ObjectVDI
XAPI Fieldother_config:maps_to
Entry Rolevm-admin
ResearcherJakob Wolffhechel, Moksha

Affected Products

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

Summary

The maps_to key in VDI.other_config is used during cross-pool migration to map local VDIs to their remote destinations. An attacker with root access (obtainable via BOC-1, MOKSHA-2026-0001) can modify maps_to in the XAPI database mid-migration, redirecting disk operations to an attacker-controlled VDI on the destination pool. The import code reads the modified value via Ref.of_string() with no validation. This enables cross-tenant data exfiltration and data corruption during live migration - a critical window where disk state is in transit between pools.

Vulnerability Description

VDI.other_config is a Map(String, String) field writable by vm-admin. The maps_to key stores a VDI reference used during inter-pool migration to map local VDIs to their remote counterparts.

Migration Data Flow

During cross-pool migration, XAPI writes the maps_to key to VDI.other_config on the source pool:

(* xapi_vm_migrate.ml:593-601 *)
Db.VDI.set_other_config
  ~__context ~self:vdi
  ~key:Constants.storage_migrate_vdi_map_key    (* "maps_to" *)
  ~value:(Ref.string_of remote_vdi)

On the destination pool, import.ml:991-997 reads the maps_to key and uses it to look up the target VDI via Ref.of_string():

let mapto =
  try Some (Ref.of_string (List.assoc "maps_to" other_config))
  with _ -> None

No validation occurs on the value. Ref.of_string() accepts any string and returns it as a VDI reference. If the attacker has modified this value to point to a different VDI, the migration engine maps the source VM's disk to the wrong destination VDI.

Attack Window

XAPI overwrites maps_to at migration start. A vm-admin cannot pre-set the value before migration and have it survive - XAPI's write at line 593 replaces it. The attack requires modifying the value after XAPI sets it but before the destination reads it. This mid-flight modification requires root access to the XAPI database, which BOC-1 S3 provides.

Root Causes

  1. Missing per-key RBAC. VDI.other_config has map_keys_roles protection only for folder and XenCenter.CustomFields.* (UI keys). The maps_to key has no per-key protection.

  2. Migration-internal state in user-writable field. The maps_to key stores migration engine internal state in a user-writable map field. This state should be in a protected internal-only field.

  3. No validation on import. import.ml reads maps_to via Ref.of_string() without verifying that the reference points to a VDI on the correct SR, belongs to the correct migration session, or was set by a trusted code path.

Affected Systems

Directly Affected

Indirectly Affected

Exploitation Scenarios

Scenario Impact Pre-conditions Status
Migration disk swap Migrated VM boots with attacker-controlled disk data on destination BOC-1 root access + active cross-pool migration Write confirmed; mid-flight exploitation modeled
Cross-tenant data exfiltration Source VM's disk mapped to attacker-accessible VDI on destination Same as above + multi-tenant environment Modeled
Data corruption Source VM's disk data written to wrong VDI, corrupting destination data Same as above Modeled

Detection

Remediation

Short-Term Mitigations

Long-Term Fix

Separate maps_to from other_config. Migration-internal state should not be stored in a user-writable map field. Move maps_to to a protected internal-only field that cannot be modified via the map API.

Add map_keys_roles. Add per-key RBAC for maps_to requiring _R_POOL_ADMIN in datamodel.ml.

Validate on import. import.ml should verify that the maps_to VDI reference points to a VDI on the expected SR and was set as part of the current migration session.

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