MOKSHA-2026-0026: Python Module Import Injection via Host.other_config multipathhandle

Advisory IDMOKSHA-2026-0026
Semantic IDHOC-1
Published2026-04-24
CVSS 3.17.2 High
CVSS 3.1 VectorAV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
CVSS 4.07.5 High
CVSS 4.0 VectorAV:N/AC:L/AT:P/PR:H/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
XAPI ObjectHost
XAPI Fieldother_config:multipathhandle
Entry Rolepool-operator
ResearcherJakob Wolffhechel, Moksha

Affected Products

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

Summary

A pool-operator can inject a controlled Python module name via Host.other_config:multipathhandle. The SM driver's SR._mpathinit() at SR.py:474-475 passes this value directly to Python's __import__() function as mpath_<value>. While an os.path.exists() check at line 469 verifies the file exists, this requires a file write primitive to place a .py file in /opt/xensource/sm/. Combined with BOC-1, a vm-admin can write mpath_evil.py to the SM driver directory and then set multipathhandle=evil to achieve arbitrary code execution as root during the next SR operation. Standalone, this requires pool-operator plus an independent file write capability.

Vulnerability Description

Host.other_config is a Map(String, String) field writable by pool-operator. The multipathhandle key controls which multipath module the SM driver imports at runtime.

The code path:

  1. pool-operator calls Host.add_to_other_config(host, "multipathhandle", "evil")
  2. On the next SR operation, SR._mpathinit() is called
  3. SR.py:469 checks os.path.exists("/opt/xensource/sm/mpath_evil.py")
  4. SR.py:474-475 calls __import__("mpath_evil")
  5. The attacker-controlled module is loaded and executed as root

The only valid values for multipathhandle are dmp and null, corresponding to mpath_dmp.py and mpath_null.py. No allowlist is enforced - any value that corresponds to an existing file in the SM directory is accepted.

BOC-1 Chain

With BOC-1, the attack becomes a two-step vm-admin-to-root chain:

  1. Step 1: vm-admin uses BOC-1 to mount the host root filesystem as a guest VBD
  2. Step 2: Write mpath_evil.py to /opt/xensource/sm/
  3. Step 3: vm-admin grants self pool-operator via BOC-1 S3 RBAC collapse
  4. Step 4: Set multipathhandle=evil
  5. Step 5: Next SR operation imports the malicious module as root

This chain escalates from vm-admin to persistent root code execution.

Root Causes

  1. Missing RBAC protection. Host.other_config has zero map_keys_roles entries for the multipathhandle key. Any pool-operator can modify it.

  2. Unsafe dynamic import. __import__() with unsanitized user input is a known code execution primitive. The os.path.exists() check is not a security control - it verifies the file exists, not that it is authorized.

  3. Missing allowlist. Only dmp and null are valid values, but no allowlist restricts the input.

Affected Systems

Directly Affected

Indirectly Affected

Exploitation Scenarios

Scenario Impact Pre-conditions Status
Module import injection (standalone) Root code execution during SR operations pool-operator + file write to /opt/xensource/sm/ Source-traced (High confidence)
BOC-1 + HOC-1 chain vm-admin achieves persistent root code execution BOC-1 available Modeled (multi-step chain)

Detection

Remediation

Short-Term Mitigations

Long-Term Fix

Replace __import__() with explicit allowlist. Replace the dynamic import with conditional logic that only accepts dmp and null. Reject all other values.

Add map_keys_roles. Protect multipathhandle in datamodel.ml at _R_POOL_ADMIN.

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