Multi-Factor Mixup: Who Were You Again?
- A weakness in the Microsoft ADFS protocol for integration with MFA products allows a second factor for one account to be used for second-factor authentication to all other accounts in an organization.
- After being notified about the vulnerability and independently validating it, Microsoft produced a patch to address it. See CVE-2018-8340.
- This vulnerability is best addressed within ADFS and it likely affects all MFA products for ADFS.
- Organizations running Microsoft ADFS are advised to patch their systems.
Malicious actors often compromise passwords to initiate and expand security breaches. To help protect themselves, many organizations implement Multi-Factor Authentication (MFA) — requiring that users demonstrate access to an additional factor, such as a phone, in order to log in to critical systems. Due to a weakness in the MFA protocol for Microsoft’s authentication system, Active Directory Federated Services (ADFS), if an attacker obtains a single user’s password and second factor, the attacker can use the second factor to complete the second-factor challenge for any account in the organization. This is similar to turning a room key into a master key for every door in the building – but in this building, each door has a second lock that accepts a passcode. The exploit makes it much easier for an attacker who has obtained limited access to expand their reach toward more valuable targets.
Many organizations rely on ADFS to manage identities and resources across their entire enterprise. In this role, ADFS functions as an organizational gatekeeper. ADFS Agents are extensions of ADFS that enable it to interoperate with an MFA provider by delegating second-factor authentication to the provider. MFA providers include Microsoft itself and third-party vendors like Authlogics, Duo, Gemalto, Okta, RSA, and SecureAuth. For ADFS version 3.0, this attack affects all tested MFA solutions (“ADFS Agents”) using the official integration API1.
Requirements for the Attack
If the following conditions are met, the attacker can gain access to a target account, “Alice,” without the associated second factor:
- The attacker has the username/password for Alice.
- The attacker also has access to another account, “Bob”. That is, the attacker has both the username/password and the second factor for Bob.
- Bob and Alice are in the same Active Directory (AD) organization.
The most stringent requirement listed above is access to both the password and second factor to Bob’s account. Here are a few ways to meet this requirement: First, the attacker may be an insider threat, so the “Bob” account is his legitimate account (see Figure 1). Second, Bob could be someone that does not need their account and simply has not logged in and enrolled a second factor yet (see Figures 2a and 2b). A third possibility is that the “Bob” account does not belong to an individual, and is only used for automation purposes; therefore, it does not need a second factor. Finally, the attacker could social engineer the IT help desk into resetting the second factor2. Each of these scenarios is easier to achieve with a lower-privileged account. For example, an attacker could more easily persuade the IT help desk to reset the second factor for an account with low privileges rather than high privileges.
While the figures show password compromise via phishing, other possibilities include compromising a database and cracking password hashes, compromising a host with some plaintext passwords still in memory, guessing common passwords, and guessing common modifications of compromised passwords from a different environment, but for the same person3.
Figure 1: An insider threat obtains Alice’s username and password.
To fulfill the exploit requirements, an attacker who already has an account just needs to compromise the username and password for the target account, Alice. This can be accomplished through phishing. An insider threat who has physical proximity to the target can also shoulder surf, implant a USB keylogger, and exploit Bluetooth vulnerabilities like CVE-2018-5383.
Figure 2a: An external attacker compromises the username and password for both Alice and Bob, where Bob is an account not protected by a second factor.
In addition to obtaining Alice’s credentials, an external attacker who does not have access to an account can obtain it by compromising the credentials of a user for whom an account was created but who never used it. Since Bob has never logged in, he has not enrolled a second factor, and the MFA provider allows the attacker to set it up using their own phone (see Figure 2b).
Although Bob has never logged in, he can still be phished. The attacker could send the phishing message to Bob’s personal account and trick Bob into logging into his ADFS account on a fake site, which sends the attacker Bob’s ADFS password. Another possibility is that Bob uses an email system that is incompatible with MFA and therefore has its own special authentication system, or he always logs in from an on-site terminal where an alternative authentication flow is provided. If Bob’s account in this alternative authentication flow has the same password as Bob’s account on ADFS, the attacker could obtain Bob’s ADFS password by phishing the password for the alternative authentication system.
Figure 2b: After obtaining Bob’s credentials (see Figure 2a), the external attacker sets up their own phone as a second factor for Bob.
When the MFA provider sees that Bob is not enrolled in a second factor, it usually goes through the enrollment process with the attacker. This grants the attacker access to Bob’s account. Alongside the credentials stolen from Alice (see Figure 2a), the attacker has now fulfilled the requirements for exploiting this vulnerability. While phone notifications are a concrete example, the attack works equally well with other forms of second factor. The MFA Context and MFA Token are used by the AD server and the MFA provider to coordinate the second-factor authentication flow. See the next section for details.
Executing the Attack
First, the attacker submits the credentials for Alice and Bob at the AD login page, in two separate browsers, one for each account. The attacker observes the responses from the AD server4, and finds the information associated with the second factor authentication flow for each user, the MFA Context and MFA Token. The context is easy to find because it is labeled as “id=‘context’” in the page’s HTML, and the token appears in a script just below the context. The responses also come with new session cookies. By combining Bob’s MFA Context with Alice’s session cookie, the attacker can finish logging in as Alice using Bob’s second factor and MFA Token. The attacker does not need Alice’s second factor to log into her account — Alice’s second factor could meanwhile stay safe and sound in her pocket as her account is being compromised (see Figures 3a and 3b). The official technical report provides additional information.
Figure 3a: Login page for the AD server.
The attacker enters the username and password for the Alice and Bob accounts in separate browsers.
Figure 3b: The MFA Context and MFA Token are in the HTML response received after submitting the username/password.
The attacker can simply copy and paste these pieces of text over from the Bob browser to the Alice browser, then complete second-factor authentication using their own phone.
Thus far, we have briefly touched on three key items in the protocol: the session cookie, the MFA Token5, and the MFA Context. The session cookie and MFA Token perform familiar roles of identifying sessions — one for the AD server and one for the MFA provider. That leaves the MFA Context, which is like an envelope that the AD server puts a copy of the token into, and then seals (encrypts and signs) before sending it out. When the AD server unseals (verifies and decrypts) the context, it checks for its own signature on the context. Unless the cryptographic signature scheme is broken, the scheme is incorrectly implemented, or the signing key is stolen, the AD server will detect if an attacker has modified the context. Incidentally, the cookie, token, and context are passed over cryptographically protected channels, mitigating the possibility that the attacker can simply steal them from Alice by spying on communications.
Figure 4a: Attacker obtains session cookies, MFA Contexts, and MFA Tokens for Alice and Bob.
When the attacker submits Alice’s username and password, the AD server requests a new MFA Token for Alice via a back channel to the MFA provider, which is invisible to the attacker. The MFA provider generates a new MFA Token, and initializes an associated second-factor authentication flow. The token uniquely identifies the authentication flow. The AD server makes a new session cookie and seals a copy of the MFA Token inside a new MFA Context, then sends these three items to the attacker. A similar sequence occurs when the attacker submits Bob’s username and password.
Figure 4b: Attacker mixes Bob’s MFA Context with Alice’s session to log in as Alice.
After obtaining the session cookies, MFA Contexts, and MFA Tokens for Alice and Bob (see details in Figure 4a), the attacker completes second-factor authentication with Bob’s MFA Token, then sends Bob’s MFA Context with Alice’s session cookie to the AD server. The AD server confirms with the MFA provider that Bob’s token was approved, then it logs the attacker in as Alice.
The MFA Context contains an encrypted and signed copy of the MFA Token, using the AD server’s certificate/key pair to encrypt and sign. Therefore the AD server can verify that it issued the MFA Token. However, the AD server does not verify the relationship of the MFA Token to the identity being logged in, allowing the attacker to log in as Alice using Bob’s second factor. One way to verify that relationship would be for Microsoft to include the username in the signed data of the MFA Context.
After the attacker enters Alice’s username and password, the AD server asks the MFA provider for a new MFA Token for Alice. The token tracks a session for the MFA provider. It is similar to a session cookie, but it is transferred differently and not stored in the browser. The MFA provider creates a new token and an associated fresh second-factor authentication flow for Alice that the token uniquely identifies, and sends the token to the AD server. The MFA provider keeps a record of each token it issues, and whenever someone succeeds in second-factor authentication, it records that the corresponding token was approved.
When the AD server receives the token, it puts a copy of the token in an MFA Context and seals it. The AD server also generates a new cookie that is associated with the partially completed login flow for Alice. The AD server sends the cookie, context, and token to the attacker (see Figure 4a). The attacker cannot proceed with second-factor authentication using Alice’s token, because the attacker doesn’t have the second factor for Alice.
A similar sequence occurs when the attacker submits Bob’s username and password. The attacker receives a session cookie, MFA Context and MFA Token for Bob. However, this time the attacker can complete the second-factor authentication flow for Bob’s token. This involves sending Bob’s token to the MFA provider, which then sends a notification to the attacker’s phone, where the attacker can press “Approve”. The MFA provider then records that the flow for Bob’s token has been approved.
Now the AD server expects to receive Bob’s MFA Context along with Bob’s session cookie from the attacker. The AD server would then unseal the context, retrieve the token inside, and ask the MFA provider if the token was approved. The MFA provider would affirm, then the AD server would allow the attacker access to the account associated with the cookie: Bob’s account. Instead, the attacker submits Bob’s MFA Context along with Alice’s cookie, and is logged into Alice’s account (see Figure 4b).
Discussion and Mitigation
With ADFS, the AD server functions as a central gatekeeper for other resources, meaning that the attacker gains access to all of these other resources that are provided to Alice. For many companies, this includes email, chat services, internal documents, HR systems, administrative panels, and private intellectual property.
This vulnerability is due to a failure to cryptographically enforce the integrity and authenticity of relationships between the two pieces of identity — the primary credentials and the second factor. Although Microsoft cryptographically signs the MFA Context before passing it to the user, then checks the signature when the user sends it back, this only enforces its internal integrity and authenticity.
The solution Okta recommended to Microsoft was to put the username that belongs to the MFA Context in the context before signing it and passing it to the user, then confirming that the username in the context belongs to the session when the context is received back from the user; details on the remediation are available here. This solution expands the role of the MFA Context to contain both the original context and its relationship to the identity of the primary credentials. One might consider retrieving the identity associated with the MFA Token from the MFA provider and comparing it to the identity associated with the primary credentials. Although this appears straightforward, only the ADFS Agent can query the identity associated with the token. Furthermore, ADFS does not provide the agent with a reliable way to obtain the identity associated with the primary credentials when checking for completion of second-factor authentication. Passing an identity across the boundary would mean coordinating an update to the interface between the various ADFS Agents and ADFS, which are developed by different parties.
Recommendation for Organizations Running ADFS With MFA
Organizations that have set up ADFS with an ADFS MFA Agent should consider updating Microsoft ADFS. Microsoft’s patch should fix the vulnerability without applying any update to ADFS agents. No changes were necessary to Okta’s ADFS Agent. For ADFS Agents from other vendors, please check with the vendor.
How the Vulnerability Was Discovered
Reviewing the Okta ADFS Agent led to the discovery of this vulnerability, as part of a larger effort by the Okta Research and Exploitation (REX) team to help Okta developers secure their code.
The rigorous pursuit of security goals often impels the matching of informal and implicit objectives to explicit specifications, the breaking apart of complex specifications into simple ones, and finally the gathering of supporting evidence for whether each specification is met. The product’s main goal is to enable MFA with ADFS. More explicitly, this means that a user can only log into an ADFS account if they have access to both the primary credentials — username and password — and the second factor for the account in question6. Breaking this complex specification down into simple pieces leads to:
- If a person logs into some account, “Alice”, they must have presented credentials.
- The credentials must belong to Alice.
- If a person logs into the Alice account, they must have completed second factor authentication.
- The second factor must belong to Alice.
Although it may seem excessive to break things apart into such simple components, each piece becomes complicated when implemented in software. Generally, a vulnerability is created when the people involved in the development process overlook a security requirement. This often happens when people attempt to juggle too many objects in their memory at one time while considering complex systems. Separating goals into simple components, and focusing on one at a time, reduces the number of items in simultaneous contemplation and the chances of overlooking something important. Indeed, the last component listed above was previously overlooked, even though it seems easy to remember after having broken things apart7.
After briefly exploring the code and its runtime behavior with the aid of a debugger, ADFS appeared to be properly checking the credentials, and the code for the Okta agent was clearly checking for a second factor. Digging deeper, the information pertaining to the second factor (the MFA Context) was signed and later checked by the AD server. The AD server only put tokens it requested from the MFA provider into the context, and refused to proceed if the context it received back from the user failed the signature verification. This attested that the second factor belonged to a valid user on the AD server. Still, thus far nothing implied that the second factor had to be associated with the actual account being logged into. Something needed to bind the primary authentication flow with the second factor authentication flow. In the code for initiating second-factor authentication, ADFS passed the agent both the MFA Context and the identity being authenticated. However, when checking for completion of second-factor authentication, ADFS omitted the identity being authenticated, passing the agent only the MFA Context and some other information associated with the ADFS session.
Ultimately, no piece of the agent’s code checked the relationship between the two parts of authentication, and considering the design of the interface between ADFS and the agent, the most natural place to check the relationship was in the ADFS code itself. Microsoft’s concealment of the ADFS source code stoked the development of a proof-of-concept exploit — an exploit which successfully misled ADFS into letting an actor use Bob’s second factor to log in as Alice.
March 23, 2018 — Okta researcher Andrew Lee discovers vulnerability and reports internally at Okta.
April 2, 2018 — Okta attempts a mitigation in the Okta ADFS Agent by including the session cookie in the MFA Context, then checking that the cookie in the context is the same as the one in the request header when the user sends the MFA Context back to the agent to complete the login flow.
April 18, 2018 — Okta receives a bug report that the attempted fix is not compatible with all ADFS environments.
April 19, 2018 — Okta reports vulnerability to Microsoft.
Apr 23, 2018 — Microsoft responds that they are able to internally reproduce the issue.
May 4, 2018 — Microsoft Security Response Center (MSRC) case created. Patch date set.
July 11-13, 2018 — Microsoft files CVE-2018-8340.
August 14, 2018 — Microsoft releases patch, vulnerability is published.
1 Other ADFS versions before Microsoft patched the bug on August 14, 2018 were not tested. They may also be affected. Testing was done with ADFS running on Windows Server 2012 R2.
2 The latter three scenarios for attacking MFA were presented by Rob Ragan of Bishop Fox at the Okta REX talks in March 2018. They were taken from real-world penetration tests. See 37:46 of his talk, 9Tail: Tools, techniques, and war stories from the security researchers at Bishop Fox.
3 Rob Ragan also presented these routes to compromising passwords at 2:14 of his Okta REX talk.
4 For convenience, I combine the three components, Active Directory (AD), AD Federated Services (ADFS), and ADFS Agent, as a single entity, the AD server. The AD server plays the role of identity provider, managing identities for the organization. It has been preconfigured to coordinate with a particular MFA provider to authenticate users.
5 Other MFA providers may have a different name for the token, but the usage is similar.
6 MFA is usually specified to also limit the time and distance separation between primary and secondary authentication. Here, I focus on the parts relevant to this attack.
7 This technique is common to managing complexity in any form.