Summary
A command injection vulnerability exists in the QEMU hypervisor implementation where user-controlled data from OCI annotations (args.Command) can be interpreted as additional QEMU command-line flags rather than kernel command-line arguments.
Vulnerability Details
File: pkg/unikontainers/hypervisors/qemu.go:145-146
Root Cause:
The BuildExecCmd() function constructs the QEMU command as a string, then uses strings.Split(cmdString, " ") to convert it to a slice. When args.Command(derived from OCI annotations via unikernel.CommandString()) contains whitespace-separated values, they are incorrectly parsed as separate QEMU arguments instead of a single kernel command-line string.
Attack Vector:
- Attacker controls the container image OCI annotation that populates
args.Command
- Malicious payload:
quiet -drive file=/dev/sda
strings.Split parses -drive and file=/dev/sda as separate QEMU arguments
- Arbitrary QEMU flag injection is achieved
Impact:
- Critical - Allows arbitrary QEMU flag injection from malicious container images
- Host filesystem access via
-drive file=/host/path
- Potential VM escape
- Privilege escalation on the host
Severity: Critical (CVSS 3.1 score should be calculated)
Proof of Concept
An attacker could set the OCI annotation (e.g., org.unikernel.cmdline) to:
quiet -drive file=/dev/sda
This would inject the -drive flag into the QEMU command line, enabling disk access to the host device.
Suggested Fix
Construct exArgs as a []string from the start using append() calls, similar to how Cloud Hypervisor already does. Never split a pre-built string. The fix should:
- Build arguments as a slice from the beginning
- Use
append(exArgs, "-append", args.Command) while treating args.Command as a single argument
- Avoid string concatenation followed by space-splitting
Example approach:
exArgs := []string{q.binaryPath}
exArgs = append(exArgs, "-m", qemuMem+"M")
// ... build as slice throughout
exArgs = append(exArgs, "-append", args.Command)
System Info
- urunc version: [current]
- Arch: x86_64/arm64
- VMM: QEMU
- Unikernel: any (virtiofs-based)
Steps to Reproduce
1. Create a container image with a malicious OCI annotation for the command string
2. Run the container with urunc using QEMU hypervisor
3. Observe that the injected flags appear in the QEMU command line
Summary
A command injection vulnerability exists in the QEMU hypervisor implementation where user-controlled data from OCI annotations (
args.Command) can be interpreted as additional QEMU command-line flags rather than kernel command-line arguments.Vulnerability Details
File:
pkg/unikontainers/hypervisors/qemu.go:145-146Root Cause:
The
BuildExecCmd()function constructs the QEMU command as a string, then usesstrings.Split(cmdString, " ")to convert it to a slice. Whenargs.Command(derived from OCI annotations viaunikernel.CommandString()) contains whitespace-separated values, they are incorrectly parsed as separate QEMU arguments instead of a single kernel command-line string.Attack Vector:
args.Commandquiet -drive file=/dev/sdastrings.Splitparses-driveandfile=/dev/sdaas separate QEMU argumentsImpact:
-drive file=/host/pathSeverity: Critical (CVSS 3.1 score should be calculated)
Proof of Concept
An attacker could set the OCI annotation (e.g.,
org.unikernel.cmdline) to:quiet -drive file=/dev/sda
This would inject the
-driveflag into the QEMU command line, enabling disk access to the host device.Suggested Fix
Construct
exArgsas a[]stringfrom the start usingappend()calls, similar to how Cloud Hypervisor already does. Never split a pre-built string. The fix should:append(exArgs, "-append", args.Command)while treatingargs.Commandas a single argumentExample approach: