#!/coding/blatt
Sammelsurium mit Schwerpunkten Linux & IT-Sicherheit

Virtual Machine Manager & QEMU/KVM: VMs ohne Root-Rechte ausführen

Standardmäßig verbindet sich Virtual Machine Manager (VMM) über die URI qemu:///system mit dem lokalen libvirt-Dienst, der wiederum zur Kommunikation mit QEMU/ KVM dient. Der libvirt-Dienst wird bereits beim Systemstart gestartet und läuft mit Root-Rechten. Alle virtuellen Maschinen (VMs) die unter dieser VMM-Verbindung ausgeführt werden, laufen somit mit Root-Rechten.

Aus Sicherheitsgründen ist es empfehlenswert, VMs bevorzugt ohne Root-Rechte und nur mit Benutzerechten auszuführen. Im folgenden Beitrag erfahrt ihr, wie ihr eure VMs mit VMM über qemu:///session und somit ohne Root-Rechte ausführt.

Folgende Software wurde verwendet:
  • Ubuntu v20.04 LTS
  • Virtual Machine Manager (virt-manager) v2.2.1
  • QEMU/KVM (qemu-kvm) v4.2.1

qemu:///system vs qemu://session

Der Virtual Machine Manager verbindet sich über eine URI mit dem entsprechenden libvirt-Dienst. Im Fall von QEMU gibt es folgende zwei relevante URIs (siehe auch libvirt-FAQ):

  • qemu:///system
    Verbindung mit libvirt-Dienst, der mit Root-Rechten läuft. Dieser Dienst wird bereits beim Systemstart durch systemd gestartet. Die VMs laufen hier mit Root-Rechten.
  • qemu:///session
    Verbindung mit libvirt-Dienst, der mit den Rechten des angemeldeten Benutzers läuft. Dieser Dienst wird "on the fly" gestartet, wenn sich VMM verbinden möchte und der Dienst noch nicht läuft. Die VMs laufen hier nur mit Benutzerrechten.
Hinweis VMs mit Root-Rechten, obwohl kein Root-Passwort abgefragt?

Das bei Verwendung von qemu:///system kein Root-Passwort abgefragt wird, liegt daran, dass im Hintergrund Polkit verwendet wird.

Für den Zugriff auf Netzwerkinterfaces werden im Allgemeinen Root-Rechte benötigt. Da bei Verwendung von qemu:///session eine VM nur mit Benutzerrechten ausgeführt wird, hat diese keinen Zugriff auf die Netzwerkinterfaces. Aus diesem Grund laufen die VMs nur mit einem eingeschränkten Netzwerkinterface (siehe QEMU-Usermode-Network).

Virtual Machine Manager - VMs mit Benutzerrechten ausführen

Beim ersten Start von Virtual Machine Manager wird eine Verbindung zum libvirt-Dienst via qemu:///system hergestellt:

Virtual Machine Manager: Verbindung mit libvirt-Dienst, der mit Root-Rechten läuft

Die entsprechend verwendete URI lässt sich wie folgt anzeigen: Rechtsklick auf die markierte Verbindung und Klick auf Details im angezeigten Kontextmenü:

Virtual Machine Manager: URI einer Verbindung anzeigen

In der Konsole kann folgender Befehl genutzt werden, um noch einmal bestätigend zu sehen, dass der libvirt-Dienst mit Root-Rechten läuft:

ps aux | grep libvirt
root         723  2.6  0.8 1363128 35104 ?       Ssl  10:27   0:00 /usr/sbin/libvirtd
Terminal / Konsole

Vielleicht auch noch erwähnenswert ist, dass der laufende libvirt-Dienst mit Root-Rechten IP-Forwarding aktiviert:

cat /proc/sys/net/ipv4/ip_forward
1
Terminal / Konsole

Verbindung zu qemu:///session herstellen

Damit sich VMM mit dem libvirt-Dienst, der nur über Benutzerrechte verfügt, verbindet, klickt im Menü auf Datei - Verbindung hinzufügen. Im sich öffnenden Dialog wählt als Hypervisor QEMU/KVM Benutzer-Session aus und klickt auf Verbinden.

Virtual Machine Manager: Verbindung hinzufügen

VM mit Benutzerrechten erstellen & ausführen

An der Erstellung einer neuen VM, die nur mit Benutzerrechten läuft, ändert sich im Vergleich zur Erstellung einer VM mit Root-Rechten nichts. Bei der Erstellung müsst ihr nur darauf achten, dass ihr als Verbindung QEMU/KVM Benutzer-Session auswählt. Außerdem stellt man bei der Auswahl des zu verwendenden Netzwerks einen Unterschied fest, weil als Standardauswahl Benutzermodus-Netzwerk vorausgewählt ist. Dabei handelt es sich, wie bereits oben erwähnt, um ein eingeschränktes Netzwerkinterface, für welches keine Root-Rechte benötigt werden.

Virtual Machine Manager: VM mit eingeschränktem Netzwerk erstellen

Optional: libvirt-Dienst für qemu:///system deaktivieren

Wer möchte kann, den libvirt-Dienst, der über qemu:///system angesprochen und beim Systemstart mit Root-Rechten gestartet wird, deaktivieren. Hierzu trennt und löscht die QEMU/KVM-Verbindung. Danach sind noch folgende Befehle in der Konsole auszuführen:

sudo systemctl disable libvirtd.service
sudo systemctl disable libvirt-guests.service
Terminal / Konsole

Nach einem Neustart des Rechners sollte nach dem Start von VMM nur noch ein libvirt-Prozess mit Benutzerrechten laufen:

ps aux | grep libvirt
sl          1391  5.7  0.9 1357060 37908 ?       Sl   10:36   0:00 /usr/sbin/libvirtd --timeout=120
Terminal / Konsole

Des Weiteren sollte IP-Forwarding, sofern ihr es nicht manuell aktiviert habt, deaktiviert sein:

cat /proc/sys/net/ipv4/ip_forward
0
Terminal / Konsole

Zugriff auf Netzwerkinterfaces ohne qemu:///system

Möchtet ihr mit eurer VM nur eine einfache Verbindung zum Internet herstellen, dann ist das eingeschränkte "QEMU-Usermode"-Netzwerkinterface ausreichend. Sobald aber bestimmte Netzwerkfunktionen, wie z.B. Zugriff auf den Host, oder spezielle Netzwerkkonfigurationen benötigt werden, braucht es Zugriff auf die nicht eingeschränkten Netzwerkinterfaces, welche bei Verwendung von qemu:///system zur Verfügung stehen.

Hierfür gibt es als Lösung ein Script namens qemu-bridge-helper, welches sich bei Ubuntu unter /usr/lib/qemu/ befindet. Mithilfe dieses Scripts ist es möglich, dass eure VM weiterhin nur mit Benutzerrechten läuft, aber Zugriff auf die Netzwerkinterfaces, die Root-Rechte benötigen, erhält. Wie ihr diesbzgl. vorgehen müsst, könnt ihr hier nachlesen:

Hinweis SUID-Bit wird benötigt

Für den Einsatz der qemu-bridge-helper-Lösung ist für das Script explizit das SUID-Bit zu setzen. Scripts mit gesetztem SUID-Bit sind, wenn sie Sicherheitslücken enthalten, ein bewährtes Mittel bzw. Einfallstor für Privilege Escalation. SUID-Bits sollten also mit Bedacht gesetzt werden.

Unter Ubuntu - soweit ich das beim kurzen Überfliegen gesehen habe - enthält das AppArmor-Profil (siehe /etc/apparmor.d/usr.sbin.libvirtd) für libvirt auch Anweisungen für qemu-bridge-helper.

Für eine VM könnt ihr anschließend bei der Erstellung oder im Nachhinein das gewünschte Netzwerkinterface angeben. Dazu müsst ihr bei Netzwerk-Auswahl die Option Name des gemeinsam verwendeten Geräts angeben auswählen und den Namen des Netzwerkinterfaces eintragen.

Virtual Machine Manager: qemu-bridge-Helper - Root-Netzwerkinterface verwenden

Die Namen der verfügbaren Netzwerkinterfaces findet ihr z.B. raus, indem ihr in VMM per Rechtsklick auf die markierte qemu:///system-Verbindung klickt und dann auf Details. Anschließend wählt den Tab Virtuelles Netzwerk:

Virtual Machine Manager: Netzwerkinterfaces anzeigen

Fazit

Virtuelle Maschinen lassen sich mittels dem Virtual Machine Manager anstatt mit Root-Rechten auch ausschließlich mit den Rechten des Benutzers ausführen. In diesem Fall steht der VM zwar nur ein eingeschränktes Netzwerkinterface zur Verfügung, aber für einfache Anwendungsfälle sollte das ausreichen. Alternativ kann sonst das im Beitrag erwähnte qemu-bridge-helper-Script verwendet werden. Hiermit können VMs, die nur mit Benutzerechten laufen, trotzdem auf die nicht eingeschränkten Root-Rechte benötigten Netzwerkinterfaces zugreifen.