MAC/IP takeover possible in libvirt networks despite nwfilter (this is no CVE issue!)

On a Fedora 35 workstation installation (up to date as of 14 Dec 21), I have libvirt/qemu/kvm (all fedora repo default; the virtual network is provided by libvirt) installed to use it as hypervisor. Additional to the dependencies, I also installed libvirt-daemon-config-nwfilter.x86_64, which is active (only the default filters!):

virsh # nwfilter-list

8bf54fb0-4457-493d-af73-40bac359addd allow-arp
d8b311a1-3505-4be2-b3fe-69d3cb343278 allow-dhcp
47ea7204-5104-4fb2-85bd-f8de21e738f6 allow-dhcp-server
fe76208b-dd17-47ab-981d-d3496771a455 allow-dhcpv6
77f2a2e7-294e-4fd1-bfcf-af640c4542e3 allow-dhcpv6-server
b707a316-10ff-45ae-beca-1c8d3ea97ce1 allow-incoming-ipv4
199efef0-c712-4adc-813e-166b5ddc1ba7 allow-incoming-ipv6
9010ee69-7487-4677-b5d1-4f68412ae338 allow-ipv4
bcb4631a-087a-4e08-964e-b62cbe760e43 allow-ipv6
402b6fba-8d8b-40f2-ae70-10403f3241bf clean-traffic
571b5e60-b7ab-4f6d-bf57-119c6ae32113 clean-traffic-gateway
bcef96f1-1647-4966-9b7a-fe328735cfb8 no-arp-ip-spoofing
bb1def76-da7e-4e04-9331-ccc041070a2a no-arp-mac-spoofing
d59c0c2f-6c7f-4570-9abe-c21fb22286ac no-arp-spoofing
3dcb4abb-208a-4e80-8790-cd5e33c58c7e no-ip-multicast
4c655884-137f-4ecc-b448-db546fd4e962 no-ip-spoofing
041caf65-ab98-4be5-8df3-8cd783537fc3 no-ipv6-multicast
c7839bfb-1620-4a00-9cb7-61b4255f1053 no-ipv6-spoofing
a5049971-6f16-4669-bfbd-ce5e5059a8fa no-mac-broadcast
ab3a05dd-d875-4adb-a7ee-1e14dbcfd01b no-mac-spoofing
55700c58-ece2-4223-b764-7a30201b4093 no-other-l2-traffic
b5eab4fe-6499-4d83-91d8-d96af8789765 no-other-rarp-traffic
8d93052a-7bcc-4b43-a512-1f1aa4eeaa63 qemu-announce-self
6d3ccb1b-83e6-4fb6-983e-d78e796f8dfe qemu-announce-self-rarp

The test environment within my qemu/kvm/libvirt contains in its virtual network (all in one subnet of course; as it is configured by default): one client** vm that connects nc <ip server> 8080, one server** vm that offers nc -l 8080, one attacker vm that aims to take over the MAC & IP of the server. All is Fedora 35, just like the host (but the client/server vm’s are Fedora Server, not workstation), up to date as of 14 Dec 21. I used just the standard tools to do all of this: nc, ip, nmcli, ifconfig (including the attacker vm; no penetration tools or such).

Nevertheless, despite nwfilter + libvirt-daemon-config-nwfilter on the hypervisor, MAC and IP takeover is still very easy: the attacker machine can change the MAC to the targeted machine, then deactivate+activate network interface, and the default DHCP of the hypervisor does the rest: IP of the target gets assigned to the attacker; no warning and no indication at any level.

When this has happened, requests are forwarded to the machine that was active last (simple ping via ICMP is sufficient for that; thus, its easy to keep the attacker dominant for the majority of requests).

This is a minor issue on workstations, but in corporate or cloud environments (relevant mostly for the upstream distributions) this could be exploitable if one machine from the given network was taken over (and far too many machines are often combined in a virtual network instead of separating the subnets where it is possible or reasonable). Many SMBs have less sophisticated administration capabilities (which may include SMB cloud providers). About two years ago, I asked around informally at events etc. about who was aware of the issue when setting up libvirt networks (also including occupational admins). Most did not know anything about it (of course this informal survey was not representative).

I was trying to find an easy to implement solution, but I could not find one. In fact, I couldn’t get rid of the exploitation possibility within one virtual net at all. In a mail to the libvirt team about two years ago, I was told that it is possible to solve this with nwfilter (I had no success with it; I also tested it with a simple HTTP server, not just nc, and all with Fedora and CentOS). The default filters no-arp-ip-spoofing, no-arp-mac-spoofing and no-arp-spoofing (see nwfilter-list output above) I installed automatically with libvirt-daemon-config-nwfilter.x86_64 made no difference (at least not by default config). Currently, I do not see a difference in defining further filters (feel free to challenge this assumption) …

Any ideas how to solve or mitigate the issue?

If so, it could be thought of making such a solution to the default configuration since most materials potential admins use to config their systems do not make aware of such issues (although this is more serious in the upstream distributions). Theoretically, an adjustment of the default config could include to make libvirt-daemon-config-nwfilter.x86_64 a dependency of libvirt-daemon-driver-nwfilter.x86_64 as it increases security, even if that specific issue remains (I don’t see any negative impact of this). I am a big fan of not shifting such issues to the assumption that any admin of such environments will know about it :slight_smile:

Just to avoid the discussion: don’t forget that at this level, DNS-dependent solutions cannot mitigate that issue. Currently, the only mitigations I see are

  • asymmetric crypto means, or the increased use of subnets (which can be cumbersome and/or annoying for (or simply unknown to) many admins and cause them not to implement it; especially in complex and fast-changing corporate/cloud environments in today’s organizational architectures; but also for normal users of VM technologies).
  • adjusting the management of the ARP table (how to mitigate here without creating noticeable effects?)

Ideas of how to do the latter? Alternatives?

I know that I merge a bit a discussion thread and an ask thread, but as the technical issue (that indeed contains open questions) is the foundation of any related discussion, I thought it makes sense to keep it together, and to start here. Especially as ask.fedora is more active in terms of technical issue handling. The question for a problem solution is the focus for now.

firewalld configuration:

  • Client vm: no open ports (Fedora Server Default)
  • Server vm: 8080/tcp 8080/udp (Fedora Server default + firewall-cmd --add-port=8080/tcp + firewall-cmd --add-port=8080/udp)
  • Hypervisor is Fedora Workstation default, but this is unrelated to the issue.

Looking forward to your ideas!


You need to reference the filters in the VM interface config:

Note that some filters may include others:

Keep in mind that there’s more than a single solution.
Zero trust model with mutual authentication can mitigate this kind of problem.

1 Like

Thanks for the information! That is indeed difficult to find if you do not know in advance about the need for adjustments in the VM-specific configurations.

I added one line each in the xml-file of the client VM and in that of the server VM in /etc/libvirt/qemu/:

The interface section of one of the two original xml files:

\<interface type="network">
	\<mac address="52:54:00:05:e5:fd"/>
	\<source network="default"/>
	\<model type="virtio"/>
	\<address type="pci" domain="0x0000" bus="0x01" slot="0x00" function="0x0"/>
> ...

The same interface section with the added line (<filterref filter="no-arp-spoofing"/>) to include the filter:

\<interface type="network">
	\<mac address="52:54:00:05:e5:fd"/>
	\<filterref filter="no-arp-spoofing"/>
	\<source network="default"/>
	\<model type="virtio"/>
	\<address type="pci" domain="0x0000" bus="0x01" slot="0x00" function="0x0"/>

After I restarted the service, this type of attack was indeed no longer possible.

Nevertheless, I think I will open a discussion thread in the coming days about this because I think it makes sense to talk about adding the libvirt-daemon-config-nwfilter.x86_64 to the dependencies of libvirt-daemon-driver-nwfilter.x86_64, and also to adjust the creation of the VMs’ xml files (at least when this is done by Fedora’s components). I think it makes sense that the critical filters are enabled in new VM’s xml files by default. If a new network interface is created in a VM, it is not much adjustment to make the interface section to then also include the line about arp spoofing (and maybe other critical filter) by default instead of just the remaining lines.

1 Like