Response to "TunnelCrack" vulnerability disclosure
Mullvad is mostly unaffected by the TunnelCrack VPN vulnerabilities. This is our response to the recently disclosed set of attack vectors on VPNs.
TLDR: On Windows, Linux, macOS and Android we are not vulnerable to the LocalNet attack. We never leak traffic to public IPs outside the VPN tunnel. However, on iOS we are affected by this attack vector.
On Windows, Linux, macOS and Android where we have the local network sharing setting, it is disabled by default. This means all traffic outside the tunnel is blocked by default. When the local network sharing setting is enabled, our app does not just allow traffic to all networks advertised by the DHCP server or set up as local networks in the routing table. We specifically allow traffic only to known standardized local network ranges. These are IPs that can only ever exist on local networks, and are not valid public IPs. If you want to get into the nitty gritty details, here is the list of allowed local IP network ranges in our app’s source code.
What this means is that if a rogue AP advertises some public IP ranges as local network ranges to the victim’s device, our app will block any traffic to those IPs. The traffic will neither go inside nor outside the tunnel, it will be stopped from leaving the device altogether.
Even if LocalNet is not a traffic leak with Mullvad on desktop, it can be classified as a denial of service attack. The attacker can prevent the victim from communicating with certain IP ranges. The TunnelCrack paper outlines this aspect in section 4.1.2. The paper claims that this poses a security risk since it might block security cameras and software security updates.
We at Mullvad have been aware of this for a long time but not considered it a practical or important attack vector in the scope of being fixed by a VPN app. If an attacker controls the router/AP, which they need to do to perform this attack, they can block any traffic from the victim’s device anyway. We do not believe that being able to do it selectively for certain IP ranges changes anything significant. Any device that is configured in such a way that it connects to unauthenticated (the only type that can be spoofed like this) WiFi access points is susceptible to denial of service attacks, period.
When a VPN is connected on Android, the VPN app decides which IP networks go inside and outside the tunnel. These rules from the VPN app overrule the local routing table. This means that on Android all traffic to public IPs are sent inside the tunnel even if Local network sharing is enabled and a rogue AP falsely advertised public IP networks as part of the local network.
We do not agree with the conclusion in the TunnelCrack paper where they give the Mullvad VPN Android app a black check mark (“Secure by default LAN-Access-Setting”). We think our app should have a green check-mark. We find no way of triggering either a leak, or a block with our Android app.
On iOS we sadly do not offer any Local network sharing setting and local networks are always allowed in the current versions of our app. This is stated in our feature table in the readme of our app’s source code. However, we do confess that we could have made this caveat much more discoverable and visible to users. We can definitely improve on this.
This means that the device will always send any network traffic to the local network outside the tunnel. Including public IPs advertised by rogue APs and similar.
The only solution we know against these leaks on iOS is to enable a flag called includeAllNetworks in iOS VPN terminology. We have been aware of this flag for a long time, and we have wanted to enable it for just as long. The problem is that the underlying tunnel implementation that we and most other WireGuard apps on iOS use, wireguard-go, is simply not compatible with includeAllNetworks. We are currently replacing wireguard-go with something allowing us to enable this security feature. We actually have been working on this for quite some time. But it is a pretty large task and we are not there yet.
TLDR: Mullvad’s app is not vulnerable to any part of the Server IP attack vector on any platform.
Tricking the VPN client into using the wrong server IP
This part of the attack is about tricking the VPN client into using an attacker controlled IP as the VPN server IP.
The Mullvad VPN app does not use DNS in any way to obtain VPN server IPs. Our app fetches the list of VPN server IPs from our own API. We also do not use DNS to find the IP to our API server. All API communication is encrypted with https (TLS 1.3) and uses certificate pinning. This means the app cannot be tricked to talk to, or trust information from the wrong servers. This is true for all platforms.
Sending traffic to the VPN server IP outside the tunnel
This part of the attack is about leaking traffic outside the VPN tunnel to the IP address of the VPN server. This attack is possible in many VPN clients due to them often routing and allowing all traffic to the VPN server IP outside the VPN tunnel.
Windows, Linux and macOS
Our client has never allowed all traffic to to the VPN server IP. Our firewall rules were designed from the start to only allow outgoing traffic outside the VPN tunnel to the VPN server IP, port and protocol combination our tunnel were going to use, not any other port or protocol.
During a security audit in 2020, Cure53 found a vulnerability in our app (named MUL-02-002 WP2) that is very similar to the ServerIP attack described in TunnelCrack. However, it is a special case of the attack. This attack was possible even when the firewall only allowed traffic on a specific port and protocol. We responded by patching this so that our firewall rules would be even more strict. The app now only allows outgoing traffic to the VPN server IP+port+protocol from the root user on Linux and macOS and only from the mullvad-daemon.exe process on Windows. This effectively stops all forms of both the ServerIP attack and the attack found by Cure53 and has done so since app version 2020.5.
Android and iOS
Neither mobile platform is affected by the ServerIP attack vector. This is because they do not use the routing table to exclude the VPN traffic from the VPN tunnel itself. Instead they provide more fine grained mechanisms to allow the VPN apps to exclude the encrypted VPN traffic from being looped back into the VPN itself again.