Clickjacking Prevention Guide

Comprehensive strategies and techniques to protect your website from clickjacking attacks

Why Clickjacking Prevention Matters

Clickjacking prevention is not just a security best practiceβ€”it's essential for protecting your users and maintaining trust in your application. A successful clickjacking attack can lead to financial loss, data breaches, and severe reputational damage.

Prevention requires a multi-layered approach combining server-side headers, client-side protections, and user education. Each layer provides defense-in-depth, ensuring that if one protection mechanism fails, others are still in place to block attacks.

πŸ›‘οΈ Defense in Depth Strategy

Effective clickjacking prevention requires implementing multiple protection mechanisms. No single solution is foolproof, but together they create a robust defense that makes attacks significantly harder to execute.

HTTP Headers: The First Line of Defense

X-Frame-Options Header

The X-Frame-Options header is the original and most widely supported method for preventing clickjacking. It tells browsers whether your site can be embedded in iframes.

X-Frame-Options Values:

DENY

Completely prevents your site from being displayed in any iframe. This is the most restrictive and secure option.

SAMEORIGIN

Allows your site to be framed only by pages from the same origin (same domain, protocol, and port). Useful for applications that need internal framing.

ALLOW-FROM uri

Allows your site to be framed only by specific origins. Note: This is deprecated in many modern browsers.

Content Security Policy (CSP) frame-ancestors

CSP is the modern, more flexible approach to controlling frame embedding. The frame-ancestors directive replaces X-Frame-Options and provides granular control.

CSP frame-ancestors Examples:

frame-ancestors 'none'

Equivalent to X-Frame-Options: DENY. Prevents all framing.

frame-ancestors 'self'

Equivalent to X-Frame-Options: SAMEORIGIN. Allows same-origin framing only.

frame-ancestors 'self' https://trusted.com

Allows framing by same origin and specific trusted domains.

Implementation Guide

Apache Server Configuration

# X-Frame-Options
Header always set X-Frame-Options "DENY"

# CSP frame-ancestors
Header always set Content-Security-Policy "frame-ancestors 'none';"

# Both headers for maximum compatibility
Header always set X-Frame-Options "DENY"
Header always set Content-Security-Policy "frame-ancestors 'none';"

Nginx Server Configuration

# X-Frame-Options
add_header X-Frame-Options "DENY" always;

# CSP frame-ancestors
add_header Content-Security-Policy "frame-ancestors 'none';" always;

# Both headers for maximum compatibility
add_header X-Frame-Options "DENY" always;
add_header Content-Security-Policy "frame-ancestors 'none';" always;

Node.js Express Implementation

const helmet = require('helmet');

// Basic protection
app.use(helmet.frameguard({ action: 'deny' }));

// CSP frame-ancestors
app.use(helmet.contentSecurityPolicy({
  directives: {
    frameAncestors: ["'none'"],
  },
}));

// Both for maximum protection
app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      frameAncestors: ["'none'"],
    },
  },
  frameguard: { action: 'deny' },
}));

PHP Implementation

<?php
// X-Frame-Options
header("X-Frame-Options: DENY");

// CSP frame-ancestors
header("Content-Security-Policy: frame-ancestors 'none';");

// Both headers
header("X-Frame-Options: DENY");
header("Content-Security-Policy: frame-ancestors 'none';");
?>

Client-Side Protection Techniques

JavaScript Frame-Busting

JavaScript frame-busting code can detect when your page is embedded in an iframe and break out of it. This provides an additional layer of protection.

Frame-Busting Techniques:

Basic Frame-Busting
if (top !== self) { top.location = self.location; }
Enhanced Frame-Busting
if (top !== self) {
  try {
    top.location = self.location;
  } catch (e) {
    // Cross-origin restrictions
    window.location = 'about:blank';
  }
}
Advanced Protection
// Prevent iframe blocking
if (self !== top) {
  // Page is in an iframe
  if (typeof window.top !== 'undefined') {
    try {
      // Test if we can access the top window
      var topLocation = window.top.location.toString();
      if (topLocation.indexOf(self.location.host) === -1) {
        // Different domain - break out
        window.top.location = self.location;
      }
    } catch (e) {
      // Cross-origin iframe detected
      window.location = 'about:blank';
    }
  }
}

Style-Based Protection

CSS can be used to make iframe embedding difficult by preventing transparency and hiding content when framed.

/* Prevent transparency when in iframe */
body {
  background-color: white !important;
  opacity: 1 !important;
}

/* Hide content when in iframe */
html:not(:root) body {
  display: none !important;
}

/* Alternative: Show warning when framed */
html:not(:root) body::before {
  content: "This page cannot be displayed in a frame.";
  display: block;
  text-align: center;
  padding: 50px;
  background: red;
  color: white;
  font-size: 24px;
}

User Interface Protection

Confirmation Dialogs

Require user confirmation for sensitive actions. This adds a layer of protection even if clickjacking bypasses other defenses.

function confirmAction(action, message) {
  if (confirm(message)) {
    // User confirmed - proceed with action
    executeAction(action);
  } else {
    // User cancelled - abort action
    return false;
  }
}

// Usage for sensitive operations
confirmAction('transfer', 
  'Are you sure you want to transfer $1,000?');

CAPTCHA Integration

Adding CAPTCHA to sensitive actions can prevent automated clickjacking attacks.

When to Use CAPTCHA:

  • β€’ Financial transactions
  • β€’ Password changes
  • β€’ Account deletion
  • β€’ Privilege modifications
  • β€’ Bulk operations

Time-Based Delays

Implement delays for critical actions to give users time to notice and cancel unintended operations.

function delayedAction(action, delay = 3000) {
  const countdown = document.getElementById('countdown');
  let timeLeft = delay / 1000;
  
  const timer = setInterval(() => {
    timeLeft--;
    countdown.textContent = timeLeft;
    
    if (timeLeft <= 0) {
      clearInterval(timer);
      executeAction(action);
    }
  }, 1000);
  
  // Cancel button
  document.getElementById('cancel-btn').onclick = () => {
    clearInterval(timer);
    showNotification('Action cancelled');
  };
}

Advanced Protection Strategies

SameSite Cookie Attributes

Set cookies with SameSite attributes to prevent CSRF attacks that often accompany clickjacking attacks.

Set-Cookie: sessionid=abc123; SameSite=Strict; Secure; HttpOnly

Content Security Policy (CSP)

Implement comprehensive CSP policies that restrict script execution and resource loading.

Content-Security-Policy: default-src 'self'; script-src 'self'; frame-ancestors 'none';

Subresource Integrity (SRI)

Use SRI to ensure external resources haven't been tampered with.

<script src="app.js" integrity="sha384-..." crossorigin="anonymous"></script>

Testing and Validation

Automated Testing Tools

Browser Developer Tools

Check security headers in browser dev tools:

  1. 1. Open DevTools (F12)
  2. 2. Go to Network tab
  3. 3. Reload page
  4. 4. Check Response Headers
  5. 5. Look for X-Frame-Options and CSP

Online Security Scanners

Use specialized tools to test clickjacking protection:

  • β€’ OWASP ZAP
  • β€’ Burp Suite
  • β€’ SecurityHeaders.com
  • β€’ Clickjacking Test Tools

Manual Testing Techniques

Create Test iframe

Test your site by embedding it in an iframe:

<!DOCTYPE html>
<html>
<head>
  <title>Clickjacking Test</title>
</head>
<body>
  <h1>Testing iframe embedding</h1>
  <iframe src="https://your-site.com" 
          width="800" 
          height="600" 
          frameborder="1">
  </iframe>
</body>
</html>

If your site doesn't load in the iframe, protection is working!

Test Your Website Protection

Use our free scanner to verify your clickjacking protection is working correctly

Maximum 60 characters

Best Practices Summary

πŸ”§ Technical Implementation

  • βœ“Always set X-Frame-Options: DENY
  • βœ“Implement CSP frame-ancestors 'none'
  • βœ“Add JavaScript frame-busting code
  • βœ“Use SameSite cookie attributes
  • βœ“Implement comprehensive CSP policies

πŸ›‘οΈ Security Practices

  • βœ“Test protection regularly
  • βœ“Require confirmation for sensitive actions
  • βœ“Monitor for unusual user behavior
  • βœ“Keep security headers updated
  • βœ“Educate users about security risks