A vulnerability in the EAP client implementation was discovered in strongSwan. All versions since 4.1.2 are affected.
Zhuowei Zhang reported a bug in the EAP authentication client code that may allow to bypass the client and in some scenarios even the server authentication, or could lead to a denial-of-service attack.
Incorrect Handling of Early EAP-Success Messages
When using EAP authentication (RFC 3748), the successful completion of the authentication is indicated by an EAP-Success message sent by the server to the client. strongSwan's EAP client code handled early EAP-Success messages incorrectly, either crashing the IKE daemon or concluding the EAP method prematurely, leading to varying outcomes depending on the configuration. Affected are all strongSwan versions since 4.1.2, depending on the configuration.
CVE-2021-45079 has been assigned for this vulnerability.
Introduction to EAP Authentication With IKEv2
IKEv2 clients request EAP authentication by omitting the AUTH payload in the initial IKE_AUTH request. The VPN server or an AAA server on its behalf will then initiate an EAP method to authenticate the client by sending an EAP-Request message in the IKE_AUTH response. This and any subsequent EAP messages are encapsulated in EAP payloads that are exchanged in further IKE_AUTH exchanges.
Once the EAP authentication is complete and the client received an EAP-Success message, it will finally send an AUTH payload, which might incorporate a Master Session Key (MSK) established by the EAP method, in its final IKE_AUTH request. The VPN server confirms this by including an AUTH payload in its final IKE_AUTH response (likewise incorporating any established MSK, which it may have received via RADIUS from the AAA server). It's important to note that not all EAP methods are key-generating, in which case
SK_pi|r is used instead of an MSK to build the AUTH payload.
For the server authentication there are two variations when using EAP:
- In the regular case defined in RFC 7296, the VPN server will authenticate itself with a certificate right away and include an AUTH payload in the first IKE_AUTH response. The client won't continue with the authentication if it fails to validate the server's authentication at this point.
- However, if the client and server both support EAP-only authentication (RFC 5998), the server may omit the AUTH payload in the initial IKE_AUTH response. In this case, the server won't be authenticated until the EAP method is concluded and the client validated the AUTH payload received in the final IKE_AUTH response. Note that this is only permitted for mutual, key-generating EAP methods that are resistant to dictionary attacks (e.g. EAP-TLS, EAP-TTLS or EAP-AKA).
Crash Caused by Very Early EAP-Success Messages
To trigger a crash, the VPN or AAA server can send an EAP-Success message right away, without first initiating a specific EAP method. The client code incorrectly assumed that an instance of an EAP method will exist whenever an EAP-Success message is received and unconditionally called the
get_msk() method to retrieve any MSK established by the assumed EAP method, crashing the daemon due to a NULL-pointer dereference.
Authentication Shortcut Due to Early EAP-Success Messages
Early EAP-Success messages sent after initiating an EAP method lead to different results depending on the EAP method and whether EAP-only authentication is used.
The culprit is again the
get_msk() call mentioned above. Due to the non-key-generating EAP methods that don't establish an MSK, the code ignored a negative result of that call. The AUTH payload was just generated without MSK if none was available, even for methods that would actually be key-generating but were never completed.
EAP-only authentication will not be in use in many common setups, and the VPN server will be required to authenticate with a certificate first. For clients that are configured as such, the EAP/AAA server may shortcut the EAP authentication (depending on the method, see below) but the client can still be sure that the connection is established with the correct VPN server. In these scenarios, the authentication of the EAP/AAA server is usually less important for mutual EAP methods.
However, with EAP-only authentication, e.g. if both peers are configured to authenticate via EAP-TLS only, a rogue VPN server is able to not only bypass the client authentication but also its own. This could then allow such an attacker to read any unencrypted traffic sent by the client through the VPN tunnel, or may even allow it to access hosts behind the client if its local traffic selector included one or more subnets. The latter might be the case in EAP-TTLS/TNC scenarios with mutual attestation (e.g. the tnc/tnccs-20-mutual-eap test scenario).
Not all EAP methods can be shortcut (and for some, like EAP-GTC or EAP-MD5, there is no difference as they are completed after the client sent its first and only EAP-Response). One particular example is EAP-MSCHAPv2, which is a mutual, key-generating method. While it can't be used for EAP-only authentication because it's prone to dictionary attacks, it still establishes an MSK. And since that MSK incorporates the client's password, an attacker will only be able to produce an MSK and AUTH payload accepted by the client if it knows the client's password.
Remote code execution is not possible due to this issue.
As mentioned in the introduction, credit to Zhuowei Zhang (@zhuowei) for finding this vulnerability.
Setups that don't use EAP authentication are not vulnerable, as are configurations that don't use EAP-only authentication and the VPN server is required to authenticate with a certificate first (both our Android client and NetworkManager plugin are configured like that), unless a mutual EAP method is used and the AAA server identity/authentication is important in that particular scenario.
The just released strongSwan 5.9.5 fixes this vulnerability. For older releases, we provide patches that fix the vulnerability and should apply with appropriate hunk offsets (please note that we don't provide patches for versions < 5.0.1).
If you maintain a custom EAP method/plugin, make sure to change the return value of
NOT_SUPPORTED if the method does not generate an MSK, otherwise, return
FAILED until the method is complete and an MSK has been established.