-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Updated Clickjacking Cheatsheet . Closes #1577 #1609
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,10 @@ | ||
| # Clickjacking Defense Cheat Sheet | ||
| # Clickjacking and Double Clickjacking Defense Cheat Sheet | ||
|
|
||
| ## Introduction | ||
|
|
||
| This cheat sheet is intended to provide guidance for developers on how to defend against [Clickjacking](https://owasp.org/www-community/attacks/Clickjacking), also known as UI redress attacks. | ||
| This cheat sheet is intended to provide guidance for developers on how to defend against [Clickjacking](https://owasp.org/www-community/attacks/Clickjacking) (also known as UI redress attacks) and [Double Clickjacking](https://www.paulosyibelo.com/2024/12/doubleclickjacking-what.html?m=1) (also called forced multi-click exploitation) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 Much better. |
||
|
|
||
| ## Clickjacking | ||
|
|
||
| There are three main mechanisms that can be used to defend against these attacks: | ||
|
|
||
|
|
@@ -311,3 +313,166 @@ Activate [designMode](https://developer.mozilla.org/en-US/docs/Web/API/Document/ | |
| ```javascript | ||
| document.designMode = "on"; | ||
| ``` | ||
|
|
||
| ## Double Clickjacking | ||
|
|
||
| ### Introduction | ||
|
|
||
| **Double Clickjacking** is an advanced variant of Clickjacking that exploits rapid user interactions by requiring two consecutive clicks to execute a malicious action. Unlike traditional Clickjacking, which typically relies on a single deceptive click, Double Clickjacking increases the attack success rate by bypassing single-click protections and evading common security measures. | ||
|
|
||
| ## Attack Scenario | ||
|
|
||
| 1. The attacker loads a malicious webpage containing a transparent iframe overlaying a legitimate website. | ||
|
|
||
| 2. The user is tricked into clicking an element (e.g., a button or link), thinking it belongs to the attacker’s site. | ||
|
|
||
| 3. The first click moves the transparent iframe into position over a critical UI element of the target website. | ||
|
|
||
| 4. The second click executes a malicious action, such as transferring funds, changing security settings, or posting content without user consent. | ||
|
|
||
| ## Ineffective Defenses | ||
|
|
||
| Traditional Clickjacking protections are ineffective against Double Clickjacking, as noted in research by Paulos Yibelo: | ||
|
|
||
| ### 1. **X-Frame-Options:** | ||
|
|
||
| Attackers manipulate iframe positions dynamically, making this defense ineffective. | ||
|
|
||
| ### 2. **Content Security Policy (CSP) Frame-Ancestors:** | ||
|
|
||
| This protection does not prevent UI manipulation via JavaScript or CSS. | ||
|
|
||
| ### 3. **SameSite Cookies:** | ||
|
|
||
| Attackers do not need cross-site requests, rendering this defense ineffective. | ||
|
|
||
| ## Advanced Mitigation Strategies | ||
|
|
||
| Given the shortcomings of traditional defenses, the following advanced approaches offer stronger protection against Double Clickjacking: | ||
|
|
||
| ### **1. Detect Hidden Iframes Using Intersection Observer** | ||
|
|
||
| **Concept:** Attackers often use transparent or off-screen iframes. This detects and alerts users if such an iframe is capturing interactions. | ||
|
|
||
| ```javascript | ||
| const observer = new IntersectionObserver(entries => { | ||
| entries.forEach(entry => { | ||
| if (!entry.isIntersecting) { | ||
| alert("Warning: A hidden iframe may be attempting a Clickjacking attack!"); | ||
| } | ||
| }); | ||
| }, { threshold: 0.5 }); | ||
|
|
||
| document.querySelectorAll("iframe").forEach(iframe => observer.observe(iframe)); | ||
| ``` | ||
|
Comment on lines
+357
to
+367
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jmanico - I am not enough of a JavaScript expert to be able to discern if this is an effective defense against Double Clickjacking or not. Could you please take a look at this (lines 357-367) and give us your thoughts regarding it's effectiveness? It is very different than Yibelo's client-side JS defense. And I am a little concerned that this may have false positives (the assumption seemingly being it is rare for multiple entities to overlap) and also it may be a time-consuming defense if there are a lot of entities on a page, given that you'd need to check this on every page. |
||
|
|
||
| ✅ Prevents hidden iframe overlays from capturing clicks. | ||
|
|
||
| ✅ Ensures users interact only with visible elements. | ||
|
|
||
| #### **2. Enforce Click-Only on Trusted Domains** | ||
|
|
||
| **Concept:** Attackers host iframes on malicious domains. This script ensures actions only occur if the request comes from a trusted domain. | ||
|
|
||
| ```javascript | ||
| if (document.referrer && !document.referrer.includes("your-website.com")) { | ||
| alert("Warning: Clicks from an untrusted source detected!"); | ||
| } | ||
| ``` | ||
|
Comment on lines
+377
to
+381
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Two things:
At a bare minimum, I will wait until @jmanico looks at this, but if it is valid, it probably needs a better explanation. |
||
|
|
||
| ✅ Blocks interactions initiated from untrusted sites. | ||
|
|
||
| ✅ Prevents attacks executed via external embedding. | ||
|
|
||
| ### **3. Delayed Click Action (Click Delay)** | ||
|
|
||
| **Concept:** Prevents rapid unintended double-clicks by enforcing a minimum delay between clicks. | ||
|
|
||
| ```javascript | ||
| let lastClickTime = 0; | ||
| document.getElementById("submitButton").addEventListener("click", function (event) { | ||
| const now = Date.now(); | ||
| if (now - lastClickTime < 500) { // 500ms delay | ||
| event.preventDefault(); | ||
| alert("Double-click detected! Please click only once."); | ||
| } else { | ||
| lastClickTime = now; | ||
| // Proceed with the action | ||
| } | ||
| }); | ||
| ``` | ||
|
Comment on lines
+391
to
+403
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems feasible. Have you tried this on Yibelo's PoC on his blog post? |
||
|
|
||
| ✅ Makes it harder for attackers to exploit timing tricks. | ||
|
|
||
| ✅ Prevents unintended double-clicks on sensitive actions. | ||
|
|
||
| #### **4. Trusted Interaction Verification** | ||
|
|
||
| **Concept:** Adds an explicit user confirmation step before executing sensitive actions. | ||
|
|
||
| ```javascript | ||
| function confirmAction() { | ||
| let confirmation = confirm("Are you sure you want to proceed?"); | ||
| if (confirmation) { | ||
| // Perform action | ||
| } | ||
| } | ||
| ``` | ||
|
Comment on lines
+413
to
+420
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Um, TBH, I'm beginning to wonder if you are missing the point about how Clickjacking iis exploited in general. The targeted system is just there to entice the user to click or to garner the user's trust. The way this "UI redress" works is the attack places something dangerous (e.g., a site that might download malware) in a transparent overlay over something that the user generally thinks would be safe to click on (the underlying iframe of the targeted system). That overlaid system may or may not overlay "sensitive data". And you surely cannot do this on every page. You couldn't even use it on something like a financial or health insurance site, because there pretty much everything is sensitive on almost every page. Thus using something the above on such a site would be very intrusive. If it did work (and do you really think the average user is going to do a 'view source' or open the browser's web development tools and try to figure it out?), the defense needs to be unobtrusive and not require any special intelligence from the end user. |
||
|
|
||
| ✅ Requires user intent verification before execution. | ||
|
|
||
| ✅ Reduces accidental malicious actions. | ||
|
|
||
| ### **5. Prevent Rapid UI Manipulation Using Mutation Observers** | ||
|
|
||
| **Concept:** Monitors for sudden UI changes (such as iframe repositioning) and blocks suspicious activity. | ||
|
|
||
| ```javascript | ||
| const observer = new MutationObserver(mutations => { | ||
| mutations.forEach(mutation => { | ||
| if (mutation.type === "childList" || mutation.type === "attributes") { | ||
| alert("Suspicious UI changes detected!"); | ||
| } | ||
| }); | ||
| }); | ||
| observer.observe(document.body, { childList: true, subtree: true, attributes: true }); | ||
| ``` | ||
|
|
||
| ✅ Detects hidden UI manipulations in real time. | ||
|
|
||
| ✅ Prevents attackers from dynamically repositioning elements for Clickjacking attacks. | ||
|
|
||
| ### **6. Require Intent-Based Gestures for Critical Actions** | ||
|
|
||
| **Concept:** Instead of a simple click, users must perform a deliberate gesture, like dragging a slider, before confirming actions. | ||
|
|
||
| ```html | ||
| <label for="secureAction">Slide to confirm:</label> | ||
| <input type="range" id="secureAction" min="0" max="100" oninput="checkGesture(this.value)"> | ||
| <script> | ||
| function checkGesture(value) { | ||
| if (value == 100) { | ||
| alert("Confirmed! Action executed."); | ||
| } | ||
| } | ||
| </script> | ||
| ``` | ||
|
Comment on lines
+447
to
+459
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seriously, a slider on every page? Really? Because prior to X-FRAME-OPTIONS and CSP frame-ancestors, we had to put the anti-frame busting JavaScript on every bloody page, so I don't see why this would any different. You can't do something that is going to require an explicit action every time a page loads. |
||
|
|
||
| **How the Slider Works:** | ||
| A slider is an effective method for ensuring deliberate user intent before executing a critical action. Instead of a simple button click—which can be accidental or manipulated—users must perform an intentional gesture, such as sliding to a specific position, to confirm their choice. | ||
|
|
||
| ✅ Users must actively confirm before execution. | ||
|
|
||
| ✅ Prevents forced clicks leading to unintended actions. | ||
|
|
||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, what is so wrong about dropping Yibelo's suggested client-side defense here? (function(){
if (window.matchMedia && window.matchMedia("(hover: hover)").matches) {
var buttons = document.querySelectorAll('form button, form input[type="submit"]');
buttons.forEach(button => button.disabled = true);
function enableButtons() {
buttons.forEach(button => button.disabled = false);
}
document.addEventListener("mousemove", enableButtons);
document.addEventListener("keydown", e => {
if(e.key === "Tab") enableButtons();
});
}
})();Presumably that at least is effective against his PoC. He'd lose a lot of credibility if it wasn't? At a bear minimum, I think we should include it. Also, is there any reason why the standard anti-frame busting script that most companies use (and it probably still mentioned for standard clickjacking in this Cheat Sheet, although no longer as a preferred mechanism), not effective against double-clickjacking as well? Based on the small part that I understand about it, I think that it would. |
||
| ## Conclusion | ||
|
|
||
| **Double Clickjacking** is a sophisticated attack that evades traditional Clickjacking defenses. Implementing a combination of Intersection Observer detection, Click Delay, Pointer Events, Trusted Domain Enforcement, Trusted Interaction Verification, Mutation Observers, and Gesture-Based Confirmations provides robust protection against this emerging threat. A layered security approach is essential to safeguarding users from evolving Clickjacking techniques. | ||
|
|
||
| ### For a more in-depth understanding of double-click jacking and its implications, you can refer to the following articles- | ||
|
|
||
| - [New "DoubleClickjacking" Exploit Bypasses Clickjacking Protections](https://thehackernews.com/2025/01/new-doubleclickjacking-exploit-bypasses.html) | ||
|
|
||
| - [Don’t Click Twice—New Chrome, Edge, Safari Hack Attack Warning](https://www.forbes.com/sites/daveywinder/2025/01/05/dont-click-twice-new-chrome-edge-safari-hack-attack-warning/) | ||
|
|
||
| - [Emerging ‘DoubleClickjacking’ Threat Exploits Double-Clicks for Account Hijacking](https://www.bitdefender.com/en-us/blog/hotforsecurity/emerging-doubleclickjacking-threat-exploits-double-clicks-for-account-hijacking) | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, 2 things here that concern me: