DEV Community

Cover image for Implementing Clickjacking Defense Techniques in JavaScript
Amr Saafan for Nile Bits

Posted on • Originally published at nilebits.com

Implementing Clickjacking Defense Techniques in JavaScript

The emergence of sophisticated assaults like clickjacking has made security a primary issue in today's online world. By deceiving consumers into clicking on something that differs from what they initially see, attackers deploy a nefarious method called "clickjacking," which can have disastrous results. Attacks of this kind have the potential to trick people into downloading malware, sending private information, or even doing things they didn't mean to, like buying anything. In order to protect against these kinds of assaults, JavaScript is an essential component of dynamic web applications.

In this blog post, we will dive deep into how clickjacking attacks work, why they are so dangerous, and how you can implement clickjacking defense techniques in JavaScript. We will provide practical code examples and strategies to help secure your web applications and prevent these malicious attacks.

Understanding Clickjacking Attacks

Clickjacking is a type of attack where a malicious website embeds another website, typically by using an HTML , and overlays it with invisible or misleading elements, effectively "hijacking" the user's clicks. When the user interacts with the embedded page, they believe they are clicking a button or a link on the visible site, but they are actually interacting with the hidden embedded site.

Here’s a basic example of how an attacker might perform a clickjacking attack:

<!DOCTYPE html>
<html>
<head>
    <title>Malicious Page</title>
    <style>
        iframe {
            position: absolute;
            top: 0;
            left: 0;
            opacity: 0.01; /* Make the iframe nearly invisible */
            width: 100%;
            height: 100%;
            z-index: 999;
        }
    </style>
</head>
<body>
    <h1>Click the button to win a prize!</h1>
    <button>Claim Prize</button>
    <iframe src="https://www.vulnerablewebsite.com"></iframe> <!-- Embedded target page -->
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

In the code above, the attacker’s page appears as a normal webpage, but an invisible iframe that loads the target page is overlaid on top of it. Users think they’re interacting with the malicious page, but they’re really clicking on elements within the iframe.

Why Clickjacking is Dangerous

Clickjacking can lead to serious consequences, including:

Unintentional purchases: Users may click on hidden "Buy" buttons, resulting in unwanted transactions.

Account compromise: Attackers can trick users into changing their settings or submitting sensitive data on websites they trust.

Download of malware: Clickjacking can be used to initiate downloads of malicious files, infecting users' devices.

Loss of control over social media: Some attacks involve tricking users into liking or sharing content on social media platforms.

These attacks are particularly dangerous because users typically have no idea they've been compromised until it's too late.

Defending Against Clickjacking in JavaScript

Now that we understand how clickjacking works, let’s explore various defense techniques you can implement in JavaScript.

  1. Using X-Frame-Options Header

The X-Frame-Options HTTP header is one of the simplest and most effective ways to prevent your web pages from being embedded in iframes on other websites. This header instructs the browser whether the site can be embedded within an iframe.

There are three main options for the X-Frame-Options header:

DENY: Prevents the page from being displayed in an iframe entirely.

SAMEORIGIN: Allows the page to be embedded only if the request originates from the same domain.

ALLOW-FROM: Allows the page to be embedded only by a specific, trusted domain.

Here’s how you can set this header using JavaScript in Node.js:

const express = require('express');
const helmet = require('helmet');

const app = express();

// Use helmet to set X-Frame-Options header
app.use(helmet.frameguard({ action: 'deny' }));

app.get('/', (req, res) => {
    res.send('Clickjacking prevention with X-Frame-Options');
});

app.listen(3000, () => {
    console.log('Server running on port 3000');
});
Enter fullscreen mode Exit fullscreen mode

In this example, the helmet.frameguard() middleware ensures that the X-Frame-Options header is set to DENY for all responses, effectively preventing clickjacking by disallowing iframe embedding.

  1. Content Security Policy (CSP)

Another effective defense mechanism is using the Content-Security-Policy (CSP) header. The CSP header provides more fine-grained control over how and where your content can be embedded.

To prevent clickjacking, you can include the frame-ancestors directive in your CSP header. This directive allows you to specify which domains are allowed to embed your site.

Example CSP header:

Content-Security-Policy: frame-ancestors 'self';

This policy ensures that only the same origin ('self') can embed the page in an iframe, effectively preventing other websites from doing so.

Here’s how to implement CSP in a Node.js application:

const express = require('express');
const app = express();

app.use((req, res, next) => {
    res.setHeader("Content-Security-Policy", "frame-ancestors 'self'");
    next();
});

app.get('/', (req, res) => {
    res.send('CSP frame-ancestors directive in action!');
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});
Enter fullscreen mode Exit fullscreen mode
  1. JavaScript Frame Busting Techniques

Although relying on headers like X-Frame-Options and CSP is generally more reliable, you can also implement frame busting using JavaScript. Frame busting scripts detect when your page is being embedded in an iframe and force it to break out of the iframe.

Here’s a simple JavaScript snippet to detect and prevent iframe embedding:

if (window.top !== window.self) {
    // The page is embedded in an iframe, so redirect it
    window.top.location = window.self.location;
}
Enter fullscreen mode Exit fullscreen mode

This code checks if the current window is being loaded within an iframe (window.top !== window.self). If it is, it redirects the parent frame (window.top) to the current location of the iframe (window.self), effectively breaking out of the iframe.

This is a basic technique and can be circumvented by advanced attackers, so it should be used as a secondary defense mechanism in conjunction with headers like X-Frame-Options and CSP.

  1. Double-Checking Click Actions with JavaScript

Another defensive technique is adding confirmation dialogs for critical actions that could be exploited in a clickjacking attack. By requiring users to confirm their actions, you can reduce the risk of unauthorized clicks.

Here’s an example of adding a confirmation dialog to a button click event:

<button id="deleteButton">Delete Account</button>

<script>
document.getElementById('deleteButton').addEventListener('click', function(event) {
    if (!confirm('Are you sure you want to delete your account?')) {
        event.preventDefault(); // Cancel the action if the user clicks "Cancel"
    }
});
</script>
Enter fullscreen mode Exit fullscreen mode

In this example, when the user clicks the "Delete Account" button, a confirmation dialog appears. If the user cancels, the action is prevented.

  1. Implementing Sandbox Attributes for Embedded Content

When embedding content on your own site, you can use the sandbox attribute on iframes to restrict the functionality of the embedded content. This is useful when embedding untrusted third-party content, as it limits what the embedded content can do.

For example:

<iframe src="https://thirdpartywebsite.com" sandbox="allow-scripts allow-same-origin"></iframe>
Enter fullscreen mode Exit fullscreen mode

The sandbox attribute applies restrictions on the iframe, such as disabling forms, scripts, and preventing the iframe from navigating the parent page. You can selectively allow certain functionalities by adding values like allow-scripts or allow-same-origin.

Conclusion: Strengthening Clickjacking Defenses

Clickjacking is a serious security risk that web developers must address to protect users and data. By implementing defense techniques such as setting the X-Frame-Options and Content-Security-Policy headers, using JavaScript frame busting techniques, and adding user confirmation dialogs for critical actions, you can significantly reduce the risk of clickjacking attacks on your web applications.

It’s essential to layer these defense mechanisms to ensure comprehensive protection, as no single method is foolproof on its own. By combining multiple strategies, you can make your web applications more resilient to clickjacking and other forms of attacks.

Reference Links:

OWASP: Clickjacking Defense Cheat Sheet

MDN Web Docs: Content Security Policy (CSP)

Google Web Fundamentals: Prevent Clickjacking

By staying informed and vigilant, you can protect your users and their data from the dangers of clickjacking, ensuring a more secure browsing experience.

Top comments (0)