Fenix Qiao and Shuyang Wang
As SaaS applications gain popularity and traditional network perimeter fade away, attackers are shifting their focus towards compromising identities. Recently, CrowdStrike published a blog post outlining initial access attack vectors targeting Okta, in which Evilginx was highlighted as an AiTM technique used to bypass MFA and gain unauthorized access. Their analysis, detailed in this article, indicated that effectively phishing Okta users with Evilginx requires a wildcard cross-origin resource sharing (CORS) policy and disabling device matching. However, this claim is misleading. This blog post walks through the concept of CORS and illustrates how Evilginx, when properly configured, is capable of launching AiTM attacks regardless of Okta CORS settings, nor is it affected by the "Enforce device matching for creating sessions" setting.
Evilginx functions as a reverse proxy, acting as a middleman between the victim and the target service. It allows attackers to intercept and manipulate traffic, primarily to steal session cookies, which enables them to bypass MFA and take over accounts.
The attack follows these key steps:
Evilginx is open-source but does not include ready-to-use phishlets by default. While some community-contributed phishlets are available on GitHub, they often come with issues.
We tried to test an out-of-box phishlet from Github, hosted on our phishing testing domain https://dev-49281249.0kta-auth.com
, targeting the legit Okta login page https://dev-49281249.okta.com
. Proxyed login can not be fulfilled with CORS errors shown in the browser developer console.
So, what is CORS?
To understand CORS, we first need to look at the Same-Origin Policy (SOP). Two URLs are considered to have the same origin if they share the same protocol, host, and port (if specified). If any of these differ, the URLs are treated as cross-origin.
By default, browsers enforce the Same-Origin Policy (SOP) as a security measure that restricts cross-origin reads while generally allowing cross-origin writes and cross-origin embedding. This means:
<a>
), redirects, and form submissions (<form>
).<img>
), scripts (<script>
), stylesheets (<link>
), and iframes (<iframe>
).A threat actor-controlled page on https://attacker.com
therefore can not read data from https://yourbank.com
. While enforcing SOP is critical to stop cross-origin web attacks, there are legitimate use cases that require relaxing the policy, for example:
https://frontend.com
→ https://api.backend.com
)To allow controlled cross-origin access, browsers enforce CORS, which requires server-side approval for cross-origin reads.
When a web page tries to fetch data from a different origin via fetch()
or XMLHttpRequest (XHR)
, the browser first checks if the server allows it.
To explicitly allow cross-origin access, the server must send appropriate CORS headers in its HTTP response.
According to Okta's documentation, all cross-origin web requests and redirects from Okta to your organization's websites must be explicitly allowed. Therefore, by default, all cross-origin requests are denied.
In the out-of-box Evilginx phishlet setup, we found that only a subset of requests are configured to be proxied through Evilginx itself, with the rest going to the legit Okta login page directly from the browser. Since the phishing origin https://dev-49281249.0kta-auth.com
isn’t added to the CORS allow list in the Okta setting, CORS is blocked by the browser.
To troubleshoot, we can proxy traffic to Burp Suite and identify pages that are still referencing the original domain.
In the login request flow, a POST request is sent to /idp/idx/introspect
, which returns a JSON response with a MIME type of application/ion+json
. This response contains a URL for subsequent requests.
However, this URL still uses the original legitimate domain, leading to a bypass of the phishing proxy.
So, how does Evilginx automatically replace content in the response?
In Evilginx, auto_filter
is enabled by default in the proxy_hosts
configuration of the phishlet, causing Evilginx to automatically generate sub_filters
rules. These rules dynamically modify the proxied website's content by replacing legitimate URLs with phishing proxy URLs, ensuring that the victim remains within the phishing session and is not redirected to the legitimate website before completing authentication.
So, the core issue is that Evilginx does not handle this specific MIME type.
To address this, we can create a custom sub_filters
rule to replace the legitimate URL with the phishing proxy URL:
However, a new problem arises:
Some JSON responses also contain parameters for subsequent requests, such as redirect_uri
. Evilginx does not automatically extract and replace parameters for GET or POST requests. As a result, the substitution may be overly aggressive, potentially corrupting the request flow.
To resolve this issue, we need to explicitly extract and handle these parameters. This can be done using:
force_get
:
Forces Evilginx to extract parameters from a URL and rewrite them correctly. (Not supported by default and requires patching Evilginx.)force_post
:
Ensures Evilginx correctly processes modified POST request parameters.
Once these minor issues are fixed, Evilginx can execute an AiTM attack and capture session cookies. Here, we assume the user is using MFA with a code or push notification.
In short, Okta’s default deny-all CORS policy is a standard security practice to block unauthorized cross-origin access. However, this does not effectively stop Evilginx-based attacks. It only requires attackers to make minor adjustments to the phishlet configuration, adding some complexity but not preventing the attack.
CrowdStrike's blog also mentions that Okta also mitigates Evilginx attacks by enforcing "Device Binding for Creating Sessions.” According to Okta's documentation, this feature ensures that authentication redirects remain within the same browser where they were initiated by comparing the device identifier in requests. If the values do not match, access to any application is denied, and no new IDP session is permitted.
This option is enabled by default and has no impact on our testing, as Evilginx hijacks the entire authentication process.
To test if Okta sessions are device-bound and whether a stolen session cookie can be used in another browser, we set up a controlled environment with a different device (operation system), user agent, and IP.
This setup allows us to simulate an attacker attempting to reuse stolen session tokens in a completely different environment.
When testing the stolen session cookie in this environment setup, it works for regular users but fails for admins. Even if an attacker steals the session cookie, it remains unusable for admins under Okta’s default settings, resulting in a 403 error.
Moreover, stolen session cookies become immediately invalid.
We also switched from Tor to a mobile hotspot to keep the location shift minimal, but the outcome was still the same.
After configuring the VM to use the Evilginx server's proxy, the VM and Evilginx remain in the same network environment while still being separate devices with distinct user agents. Under these conditions, the stolen admin session cookie successfully worked, contradicting Okta’s claim as device-bound.
These together suggest that Okta primarily relies on IP address verification to protect admin sessions. According to this article (Protecting Administrative Sessions in Okta), Okta has several measures to protect admin sessions, such as ASN Session Binding and IP Session Binding. This aligns with our test results.
In AiTM-based attacks like Evilginx, IP/ASN bound session defense doesn’t raise the bar much because the entire Okta session is entirely controlled by attackers, including the IP and ASN. In contrast, in post-authentication attacks, like token theft from victims’ devices, threat actors would have to mimic victims’ network environment more closely. That said, it is still possible through residential proxy. Our previous blog has covered this topic.
These Okta settings mentioned in CrowdStrike's article can't effectively mitigate Evilginx attacks. Organizations should adopt stronger security measures to protect against phishing threats.
Start in minutes and secure your critical SaaS applications with continuous monitoring and data-driven insights.
Get a Demo