Skip to content

QEMU Command Injection via OCI Annotation causing args.Command Split on Spaces #666

Description

@MayankSharmaCSE

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:

  1. Attacker controls the container image OCI annotation that populates args.Command
  2. Malicious payload: quiet -drive file=/dev/sda
  3. strings.Split parses -drive and file=/dev/sda as separate QEMU arguments
  4. 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:

  1. Build arguments as a slice from the beginning
  2. Use append(exArgs, "-append", args.Command) while treating args.Command as a single argument
  3. 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  

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions