Daniel Berrange discovered that libvirt fails to check whether connection to libvirtd is in read-only or read-write mode, possibly allowing non-privileged users with access to the host machine to perform certain actions that should be restricted to administrative users only.
The following methods in libvirt.c are missing a check against the read-only connection flag:
virDomainMigrate virDomainMigratePrepare virDomainMigratePerform virDomainMigrateFinish virDomainMigratePrepare2 virDomainMigrateFinish2 virDomainBlockPeek virDomainMemoryPeek virDomainSetAutostart virNetworkSetAutostart virConnectFindStoragePoolSources virStoragePoolSetAutostart
In recent versions, libvirt uses PolicyKit to authorize connections from users. Default policy allows any local user to connect in the read-only mode.
Older versions of libvirt, or version not compiled with PolicyKit or with PolicyKit authorization disabled, default to allow read-only connections to all local users.
Thus out of the box unprivileged local users may be able to migrate VMs, set or unset the autostart flag for domains, networks & storage pools, and access privileged data in the VM memory, or disks.
All TCP remote connections are read-write, and fully authenticated, thus not impacted.
A vulnerability was found in libvirt >= 4.1.0 in the virtlockd-admin.socket and virtlogd-admin.socket systemd units. A missing SocketMode configuration parameter allows any user on the host to connect using virtlockd-admin-sock or virtlogd-admin-sock and perform administrative tasks against the virtlockd and virtlogd daemons.
Commit 632180d1 introduced memory corruption in xenDaemonListDefinedDomains() by starting to populate the names array at index -1, causing all sorts of havoc in libvirtd such as aborts like the following
Error in /usr/sbin/libvirtd': double free or corruption (out): 0x00007fffe00ccf20
The xenDaemonListDefinedDomains() function is reached by the virConnectListDefinedDomains() public API, which can be used on read-only connections.
Introduced in: libvirt v1.1.1
Introduced by: http://libvirt.org/git/?p=libvirt.git;a=commit;h=632180d1
Fixed by: http://libvirt.org/git/?p=libvirt.git;a=commit;h=0e671a16
A flaw was found in libvirt where libvirtd could crash due to how XML was parsed [1]. With the introduction of ACL permissions in libvirt 1.1.0, this flaw could be manipulated to allow a remote user with connect:read privileges to elevate them to the more permissive domain:write privilege.
This vulnerability was introduced in libvirt 1.1.0.
[1] https://bugzilla.redhat.com/showbug.cgi?id=1012196;
The qemuDomainGetBlockIoTune function in qemu/qemudriver.c in libvirt before 1.2.9, when a disk has been hot-plugged or removed from the live image, allows remote attackers to cause a denial of service (crash) or read sensitive heap information via a crafted blkiotune query, which triggers an out-of-bounds read.
It was reported that the libvirt daemon using RBD leaks ceph key/id in the process list:
As a non-privileged user you can run ps -ef | grep libvirt and see the below output. In this you can see libvirt using the ceph key as part of the command to run the VM. In particular this section
~~~ -drive file=rbd:mgmt/os-network:id=libvirt:key=AQA/H4dUwLYnORAAhWv2E+67eN72ue3rrl2klg==:authsupported=cephx none,if=none,id=drive-virtio-disk0,format=raw,cache=writeback ~~~
With the 'id' and 'key' values, any user can perform any operations on the cluster which that key provides. Typically, that would be the ability to create/delete RBDs within the cinder pool.
Full output: ~~~ qemu 13924 1 33 Dec10 ? 2-23:31:12 /usr/libexec/qemu-kvm -S -M rhel6.1.0 -enable-kvm -m 8000 -smp 8,sockets=8,cores=1,threads=1 -name os-network -uuid f0ede7e8-c15a-4813-900e-971988d494c1 -nodefconfig -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/os-network.monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no-shutdown -device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 -drive file=rbd:mgmt/os-network:id=libvirt:key=AQA/H4dUwLYnORAAhWv2E+67eN72ue3rrl2klg==:authsupported=cephx none,if=none,id=drive-virtio-disk0,format=raw,cache=writeback -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x9,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1 -netdev tap,fd=21,id=hostnet0,vhost=on,vhostfd=27 -device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:64:92:b6,bus=pci.0,addr=0x3 -netdev tap,fd=28,id=hostnet1,vhost=on,vhostfd=29 -device virtio-net-pci,netdev=hostnet1,id=net1,mac=52:54:00:f7:50:e2,bus=pci.0,addr=0x4 -netdev tap,fd=30,id=hostnet2,vhost=on,vhostfd=31 -device virtio-net-pci,netdev=hostnet2,id=net2,mac=52:54:00:14:3b:33,bus=pci.0,addr=0x5 -netdev tap,fd=32,id=hostnet3,vhost=on,vhostfd=33 -device virtio-net-pci,netdev=hostnet3,id=net3,mac=52:54:00:fd:86:aa,bus=pci.0,addr=0x6 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -device usb-tablet,id=input0 -vnc 127.0.0.1:5 -vga cirrus -device intel-hda,id=sound0,bus=pci.0,addr=0x8 -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x7 ~~~
The virDomainListPopulate function in conf/domainconf.c in libvirt before 1.2.9 does not clean up the lock on the list of domains, which allows remote attackers to cause a denial of service (deadlock) via a NULL value in the second parameter in the virConnectListAllDomains API command.
It was found that libvirt did not honour the user defined main disk format in guest XML when looking up disk backing stores in the security drivers. This could be possibly exploited by priviledged guest user to access arbitrary files on the host.
It was found that libvirt did not explicitly set the user defined backing store format when creating new image. This results in images being created with an potentialy insecure configuration, preventing applications from opening backing stores without resorting to probing. A priviledged guest user could use this flaw to access arbitrary files on the host.
It was found that libvirt did not extract the defined disk backing store format when recursing into disk image backing stores in the security drivers. This could be possibly exploited by priviledged guest user to access arbitrary files on the host.
A flaw was found in the RPC library APIs of libvirt. The RPC server de-serialization code allocates memory for arrays before the non-negative length check is performed by the C API entry points. Passing a negative length to the gnew0 function results in a crash due to the negative length being treated as a huge positive number. A local unprivileged user could use this flaw to perform a denial of service attack by causing the libvirt daemon to crash.
A race condition leading to a stack use-after-free bug was found in libvirt. Due to a bad assumption in the virNetClientIOEventLoop() method, the data pointer to a stack-allocated virNetClientIOEventData structure ended up being used in virNetClientIOEventFD callback while the data pointer's stack frame was concurrently being "freed" when returning from virNetClientIOEventLoop().
Quoting libvirt maintainer Daniel P. Berrangé: The 'virtproxyd' daemon can be used to trigger requests which could potentially exercise the bug. If libvirt is configured with fine grained access control, this could in theory let a user escape their otherwise limited access. A local unprivileged user can access virtproxyd without authenticating. Remote users would need to authenticate before they could exercise it.
A refactor of the code fetching the list of interfaces for multiple APIs introduced a corner case on platforms where allocating 0 bytes of memory results in a NULL pointer.
This corner case would lead to a NULL-pointer dereference and subsequent crash of virtinterfaced if virConnectListInterfaces() is called requesting 0 networks to be filled.
The bug was introduced in libvirt-10.4.0 and reproduces only on platforms where allocation of 0-length memory returns NULL instead of a valid pointer.
Upstream fix: https://gitlab.com/libvirt/libvirt/-/commit/8dfb12cb77996519901b8d52c754ab564ebd10e8
An invalid free flaw in the libxl driver in libvirt resulted in libvirt crashing if "virsh numatune" was run on an inactive domain. It may be possible, but unlikely, for an attacker to leverage this flaw for arbitrary code execution.
This issue affects the version of libvirt in Fedora 20. It does not affect the versions of libvirt in Red Hat Enterprise Linux 5 and 6 as those versions do not use libxl.
A vulnerability was found in libvirt, where an incorrect permissions on the UNIX domain socket. A local attacker could use this issue to access libvirt and escalate privileges.
References: https://bugs.mageia.org/27038
It was found that libvirt did not extract the defined disk backing store format when recursing into disk image backing stores in the security drivers. This could be possibly exploited by priviledged guest user to access arbitrary files on the host.
It was found that libvirt did not honour the user defined main disk format in guest XML when looking up disk backing stores in the security drivers. This could be possibly exploited by priviledged guest user to access arbitrary files on the host.
Jeremy Nickurak reported an issue with how libvirt creates iptables rules when guest systems are setup for masquerading. The iptables rule will be of the following format:
iptables-save -t nat Generated by iptables-save v1.4.7 on Wed Jun 9 14:59:03 2010 nat :PREROUTING ACCEPT [45:5146] :POSTROUTING ACCEPT [889:54117] :OUTPUT ACCEPT [889:54117] -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j MASQUERADE COMMIT Completed on Wed Jun 9 14:59:03 2010
With masquerading, outgoing connections will have their source-port mapped to a NAT-selected port, and the iptables default is for privileged ports to be mapped to privileged (<1024) ports.
This will allow users in guests that have root privileges (in the guest, independent of their privileges on the host), to obtain privileged resources on the host, as well as being able to access other resources by using it. One example is with standard NFS exports now being accessible to the guests, because the guests will appear to be from the same IP as a possibly trusted host.
To illustrate:
regular-user@host-machine:~$ ssh guest-machine Last login: Wed Jun 9 11:33:13 2010 from host-machine regular-user@guest-machine:~$ sudo mount -t nfs -o udp,rw,soft remote-nfs-server:/some-export /mnt/tmp
(get UID of resources on the remote NFS server, and create a user in the guest with that UID> (su to that new UID)
user-with-same-uid@guest-machine:~$ cp -R /mnt/tmp/secret-data /home/mycopy; rm -Rf /mnt/tmp/secret-data
A normal user account would not normally be able to do something like this because they cannot bind to the privileged port, however in this case the NAT rules permits it.
An example modified set of iptables rules that may solve the problem was supplied as well:
/sbin/iptables -t nat -A POSTROUTING -p tcp -o $(IFACE) -j MASQUERADE --to-ports 1024-65535 /sbin/iptables -t nat -A POSTROUTING -p udp -o $(IFACE) -j MASQUERADE --to-ports 1024-65535 /sbin/iptables -t nat -A POSTROUTING -p icmp -o $(IFACE) -j MASQUERADE
The above uses the --to-ports option that forces iptables' masquerading module to only map guest reqursts to non-privileged ports.
Acknowledgements:
Red Hat would like to thank Jeremy Nickurak for reporting this issue.
Upstream Commit 29fe5d7 (released in 1.1.1) introduced a latent problem for any caller of virSecurityManagerSetProcessLabel and where the domain already had a uid:gid label to be parsed. Such a setup would collect the list of supplementary groups during virSecurityManagerPreFork, but then ignores that information, and thus fails to call setgroups() to adjust the supplementary groups of the process.
Introduced by: http://libvirt.org/git/?p=libvirt.git;a=commit;h=29fe5d745fbe207ec2415441d4807ae76be05974
Upstream fix: http://libvirt.org/git/?p=libvirt.git;a=commit;h=fe11d34a6d46d6641ce90dc665164fda7bb6bff8
It was found that libvirt did not explicitly set the user defined backing store format when creating new image. This results in images being created with an potentialy insecure configuration, preventing applications from opening backing stores without resorting to probing. A priviledged guest user could use this flaw to access arbitrary files on the host.
A flaw was found in the libvirt virStoragePoolLookupByTargetPath API. The storagePoolLookupByTargetPath() function does not properly release a locked object (virStoragePoolObj) on ACL permission failure. Clients connecting to the read-write socket with limited ACL permissions could use this flaw to acquire the lock and prevent other users from accessing storage pool/volume APIs, resulting in a denial of service condition.
Upstream fix: https://libvirt.org/git/?p=libvirt.git;a=commit;h=447f69dec47e1b0bd15ecd7cd49a9fd3b050fb87