What is Clone Phishing?
Today, we’re releasing two new versions of tokens. They alert you when attackers use Man-in-the-Middle (MitM) clone phishing attacks against one of your sites. Another benefit is that the new tokens can be deployed on assets where you have limited administrative access, such as Azure tenant portals or hosted blogs.
In this article, we briefly review MitM phishing, the limitations of JavaScript-based clone site tokens, and how we built new CSS-based site tokens. Finally, we’ll show you how to install our CSS into the Azure Entra ID login portal with just a few clicks — offering high-quality alerts if your users become targets.
The folks at Zolder.io (partners with Thinkst) independently built a very stylish and similar token. Check out their blog post for more details.
1. AitM Phishing
Early phishing websites were static clones of victim websites, replicating HTML/CSS and JavaScript. They stored entered credentials and sometimes redirected victims to legitimate sites after stealing their credentials. These static sites struggled with dynamic login processes and MFA (multi-factor authentication).
Nowadays, tools like EvilGinx and Modlishka enable attackers to set up a reverse proxy server between users and victim sites. This allows dynamic modification of JavaScript to reflect phishing sites (configurable to avoid triggering non-obfuscated clone site tokens), seamlessly passing users to victim sites after session theft. Because the attacker acts as a proxy, victim sites are dynamically presented to users, enabling bypass of various types of MFA as users log in and accept pushes or enter SMS/TOTP codes.
Microsoft’s diagram illustrates the steps of a classic AitM phishing attack:
![Clone Phishing Attacks](https://www.ids-sax2.com/wp-content/uploads/2024/07/image-8.png)
2. Jawask Slip Clone Site
As detailed in Casey’s blog, our classic clone site CanaryToken is valuable for companies worldwide. Simply generate a small (optionally obfuscated) JavaScript snippet to add to your website. When the client-side loads the page, the JavaScript checks if the site is served from the expected parent domain; otherwise, it triggers an alert.
Side-Note:
It’s worth noting that no external requests are made to Canarytokens servers when the site loads from the expected parent domain. We only receive requests in very rare cases where clone sites are detected.
![](https://www.ids-sax2.com/wp-content/uploads/2024/07/image-9-1024x233.png)
This token operates very effectively, especially when obfuscating simple domain replacements for AitM servers. However, it requires the ability to insert JavaScript into the page, a requirement that many third-party service providers do not allow.
3. CSS Clones the Website Token
We spent some time trying to determine if there was a clever CSS trick similar to only alerting Canarytokens servers when there’s a domain anomaly, but due to significant restrictions on CSS interpreters in browsers to mitigate risks from third-party CSS imports, we couldn’t find a viable solution. Our approach involves creating a reference to an invisible background image on our server using the url() function. On our server, we check the Referer HTTP header to ensure it’s loaded from the correct domain. This means that simply adding a CSS rule allows us to insert the token into your web page.
3.1 Version 0.1
Some services allow us minor customization (primarily for appearance and feel), but do not permit us to upload custom JavaScript (which prevents us from using trusted clone site tokens). Therefore, we began looking into CSS as a secondary option. CSS is relatively limited, but we can initially achieve our goals by creating references to invisible background images hosted on our controlled server using the url() function.
![](https://www.ids-sax2.com/wp-content/uploads/2024/07/image-10.png)
On this server, we can check the Referer HTTP header to ensure the CSS is loaded from the correct domain.
This method works for many AitM phishing attacks (since attackers cannot control the Referer header privacy policies on browsers), but certain browsers may omit or spoof this header in various ways.
Another drawback is that our Canarytokens server now needs to be reloaded for every page load, increasing latency for legitimate site users and potentially adding significant load to our server, especially when deployed on popular portals like Azure tenant login portals.
3.2 Lambdas, Functions and Edges
To manage this and obfuscate the purpose of CSS references (as many Canary Token detectors essentially grep for the string “canarytokens.com”), we aim to use a popular cloud-based provider to filter legitimate requests and only pass suspicious ones to our server.
Our initial thought was AWS Lambda or Azure Function as alternatives, but their startup times could degrade user experience and incur high costs. AWS offers a range of other serverless functions to balance cost, latency, and functionality. In light of this, we explored Lambda@Edge functions, which automatically execute in all regions (reducing latency), but they come with certain runtime environment restrictions.
3.3 Cloudfront Function
In the trade-off between scalability/functionality, CloudFront Functions takes it a step further.
![](https://www.ids-sax2.com/wp-content/uploads/2024/07/image-11.png)
They run extremely fast (with a maximum execution time of ~1ms) but are (deliberately) very limited in functionality. Then, the goal is to figure out how to take advantage of limited features to deliver a cost-effective and high-performance experience.
How to Prevent Clone Phishing Attacks
We deployed a function to all CloudFront APs that parses two encoded data in the incoming request string: the expected Referer and the Canarytoken ID associated with it. If the Referer header matches the expected header, the function will terminate by returning a 1×1 transparent GIF, otherwise it will issue an HTTP redirect to the Canarytoken server with the resolution ID. The following diagram shows the flow when a user signs in to an Azure tenant:
![](https://www.ids-sax2.com/wp-content/uploads/2024/07/image-12.png)
The following diagram shows what happens when an AitM phishing server is deployed between user login pages:
![](https://www.ids-sax2.com/wp-content/uploads/2024/07/image-13.png)
This design wins. It offers very low latency, global deployment, and lightweight features, and because CloudFront is a CDN, linking to CDN assets doesn’t cast suspicion on adversaries.
Now we just need to make it easy to deploy!
Use CSS Tokens on the Web
In order to deploy one of these tokens to a site with limited editing scope (e.g. a site where you can only add HTML and not Javascript), I’ll show you how to add an invisible site to my personal site that alerts when it doesn’t load through the correct domain name.
![](https://www.ids-sax2.com/wp-content/uploads/2024/07/image-14-1024x544.png)
First, I navigate to the Canarytokens site and select the CSS-clone website token from the drop-down list. Then I enter my email address and my desired domain name (my web page is jacobtorrey.com). It’s also important to put a helpful memo in mind to remind myself in a few months of time where it will be placed when it happens to raise an alert to help me react. Click Create, and a token will be generated:
![](https://www.ids-sax2.com/wp-content/uploads/2024/07/image-15-1024x444.png)
This CSS is designed to copy and paste (or auto-install) the url() function into your Azure Entra ID tenant, but the url() function can be used elsewhere. I create an empty style=”display: hidden; background: url(’https[:]//dakg4cmpuclai[.] cloudfront[.] net/h6jf84z88jbpfuc1at5n5/amFjb2J0b3JyZXku/img.gif’); And save it. When I look at this page as expected, it doesn’t look any different and I don’t get any alerts:
![](https://www.ids-sax2.com/wp-content/uploads/2024/07/image-16.png)
However, if I use EvilGinx to phished this site and navigate to it, it looks the same:
![](https://www.ids-sax2.com/wp-content/uploads/2024/07/image-17.png)
I immediately received an email reminder:
![](https://www.ids-sax2.com/wp-content/uploads/2024/07/image-18.png)
It has the client IP address and referring domain name, as well as a reminder that I set myself. That’s great! I can see where this site is served from, and if it’s a real phishing site, I’ll know its URL, can go ahead and file an abuse report, or block the domain from my network. Clicking on “More Info” will provide the following information (review IP and hostname):
![](https://www.ids-sax2.com/wp-content/uploads/2024/07/image-19.png)
This technique works with most blogging platforms (e.g., WordPress) and other hosting platforms that allow some HTML editing, but not Javascript.
Refine the Details
Now that we have a new cloned website token based on CSS, it’s time to make the user experience even simpler to deploy. We estimate that the Azure portal will be a popular use case, and in our testing we found that the steps required to upload custom CSS were cumbersome. It’s important to note that the custom branding feature in the Entra UI requires an Entra ID P1 or P2 subscription. To make it as easy to deploy as possible, we explored how to build Azure applications that can be authorized to install custom-branded CSS on behalf of your tenant.
We built an Azure application that can request access to automatically install CSS files when a user signs in to their tenant with sufficient admin privileges (but only if there are no conflicting CSS files). When CSS is installed, Azure applications revoke their own permissions, reducing risk. We’ve noticed that sometimes it takes a few minutes to a few hours to propagate custom CSS to Azure’s CDN, but it’s installed. The following screenshot shows this simplified process for securing your Azure tenant:
To start in the same way, we create a token, this time choosing the Azure Entra ID login. Again, we’d like to give ourselves a helpful reminder about tokens:
![](https://www.ids-sax2.com/wp-content/uploads/2024/07/image-20-1024x541.png)
After clicking “Create”, we see that the token has been generated:
![](https://www.ids-sax2.com/wp-content/uploads/2024/07/image-21.png)
This time, we have the option to follow an automated installation process or manually download and install the CSS into an Azure tenant. Clicking on the “Automatic” option will open a new tab prompting me to log in or select the Azure account to log into. This account must be an admin account on the tenant to grant the necessary permissions:
PS: The installer requires Organization.ReadWrite.All and Application.ReadWrite.All permissions to create/update company branding with CSS, and removes itself from the tenant respectively. User.Read is the default permission required for application authentication. All permissions will be revoked at the end of the installation attempt.
![](https://www.ids-sax2.com/wp-content/uploads/2024/07/image-22.png)
I select the account for the tenant I want to protect with this token and send it to the authorization page asking if I want to authorize the application and the permissions I need.
![](https://www.ids-sax2.com/wp-content/uploads/2024/07/image-23.png)
Accepting this prompt will redirect you back to the Token page:
![](https://www.ids-sax2.com/wp-content/uploads/2024/07/image-24-1024x437.png)
That’s it! Later, your Azure sign-in page will now include this CSS, and you’ll be alerted when an attacker tries to use the AitM phishing proxy to attack your users, along with the domain name the attacker is using.
Conclusion
Phishing remains a highly effective method for account theft, and tools have matured to make all technologies except FIDO2/security key MFA vulnerable to AitM phishing and session hijacking. While our existing JavaScript tokens remain popular and provide valuable alerts about phishing site creation, we aim to cover more users of online services. Our new CSS-based tokens and seamless Azure login portal clone site tokens offer another way to quickly detect compromises in third-party service providers you rely on to protect your organization. These tokens rely on client-side behavior to trigger alerts, making them part of an overall security strategy (which should include token-based MFA!), rather than a singular solution. We’d love for you to give them a try and let us know how it goes!