Skip to main content
Offensive360
Home / Knowledge Base / Clickjacking / UI Redress Attack
Medium CWE-1021 A05:2021 Security Misconfiguration

Clickjacking / UI Redress Attack

Clickjacking tricks users into clicking invisible iframe overlays to perform unintended actions. Learn how X-Frame-Options, Content Security Policy, and frame-busting prevent these attacks.

Affects: JavaScriptC#JavaPHPPython

What is Clickjacking?

Clickjacking (UI Redress Attack) is a technique where an attacker embeds a target website in a transparent or invisible <iframe> overlaid on a decoy page. The victim sees the attacker’s page and clicks on what appears to be a harmless button, but their click is actually registered by the hidden target frame below — performing an action on the target site using their authenticated session.

Common clickjacking attacks include: tricking users into clicking “Allow” on camera/microphone permission prompts, submitting forms (account deletion, fund transfers, social media likes), enabling attacker-controlled settings, or approving OAuth permissions.

How exploitation works

<!-- Attacker's decoy page -->
<html>
<body>
  <style>
    iframe {
      position: absolute; top: 0; left: 0;
      width: 100%; height: 100%;
      opacity: 0.0;  /* Invisible overlay */
      z-index: 999;
    }
    #decoy-button {
      position: absolute; top: 300px; left: 200px;
      z-index: 1;
    }
  </style>
  <!-- Target site loaded invisibly on top -->
  <iframe src="https://target.com/settings/delete-account"></iframe>
  <!-- Decoy button positioned under the real "Confirm" button -->
  <button id="decoy-button">Click here to claim your prize!</button>
</body>
</html>

The victim clicks the decoy button; the click falls through to the invisible iframe, hitting the “Delete Account” button on the target site.

Vulnerable code examples

ASP.NET Core — no frame options set

// VULNERABLE: No X-Frame-Options or CSP frame-ancestors configured
// Default ASP.NET Core configuration does not include framing protection
app.UseRouting();
app.UseAuthorization();
// Missing: response headers that prevent iframe embedding

Express / Node.js — no helmet configuration

// VULNERABLE: No framing protection
const app = express();
// Missing: helmet with frameguard, or explicit X-Frame-Options header
app.use(express.json());

Secure code examples

ASP.NET Core — security headers middleware

// SECURE: Set X-Frame-Options and CSP frame-ancestors
app.Use(async (context, next) => {
    context.Response.Headers.Add("X-Frame-Options", "DENY");
    context.Response.Headers.Add("Content-Security-Policy",
        "frame-ancestors 'none'"); // Modern equivalent — takes precedence
    await next();
});

Express / Node.js — helmet

// SECURE: helmet's frameguard sets X-Frame-Options automatically
const helmet = require('helmet');

app.use(helmet({
    frameguard: { action: 'deny' },
    contentSecurityPolicy: {
        directives: {
            frameAncestors: ["'none'"],  // Disallow all framing
        }
    }
}));

Python / Django

# SECURE: Enable clickjacking middleware (enabled by default in Django)
# settings.py
MIDDLEWARE = [
    'django.middleware.clickjacking.XFrameOptionsMiddleware',  # Adds X-Frame-Options: DENY
    ...
]
X_FRAME_OPTIONS = 'DENY'  # or 'SAMEORIGIN' if you need same-domain iframes

What Offensive360 detects

  • Missing X-Frame-Options header — HTTP responses without X-Frame-Options: DENY or SAMEORIGIN
  • Missing CSP frame-ancestors directive — Absence of the modern Content-Security-Policy: frame-ancestors restriction
  • Permissive SAMEORIGIN without need — Applications that allow same-origin framing when there is no legitimate use case
  • Disabled Django XFrame middlewareXFrameOptionsMiddleware removed from the middleware stack

Remediation guidance

  1. Set Content-Security-Policy: frame-ancestors 'none' — This is the modern standard and takes precedence over X-Frame-Options in browsers that support CSP Level 2+.

  2. Also set X-Frame-Options: DENY — For backward compatibility with older browsers that do not support CSP.

  3. Use SAMEORIGIN only when required — Only allow same-origin framing if your application deliberately uses iframes for own-domain content.

  4. Apply headers globally — Configure framing headers as middleware that applies to all responses, not per-endpoint.

  5. Avoid JavaScript frame-busting — JavaScript-based frame-busting (if (top !== self) top.location = self.location) can be bypassed with sandbox iframe attributes. Use HTTP headers instead.

References

By Offensive360 Security Research Reviewed: March 2026

Detect Clickjacking / UI Redress Attack automatically

Run Offensive360 SAST on your codebase to find this and 100+ other vulnerabilities.