Clickjacking remains a stealthy but potent web security threat. This guide provides robust techniques and configuration examples to help sysadmins harden their systems against UI redress attacks.

Clickjacking (User Interface redress attack) tricks users into clicking invisible or misleading elements embedded via iframes on a malicious site. In enterprise environments, it can lead to unauthorized operations, credential leaks, or administrative actions being hijacked.

How to Check if Your Site is Vulnerable

A site is vulnerable if it allows itself to be embedded via <iframe> by external domains. To check, use:

curl -I https://yourdomain.comCode language: JavaScript (javascript)

If no X-Frame-Options or Content-Security-Policy: frame-ancestors header appears, the site is potentially at risk.

👉 Visit clickjacker.io to test if your site is vulnerable.


Key Defense Strategies

1. Set Protective HTTP Headers

a) X-Frame-Options (Legacy but still useful)

  • DENY: Blocks all iframe embedding.
  • SAMEORIGIN: Allows embedding only from the same origin.
  • ALLOW-FROM uri: Deprecated and unsupported by modern browsers.

b) Content-Security-Policy (CSP) — frame-ancestors

A more modern, flexible and widely supported solution:

Content-Security-Policy: frame-ancestors 'none'Code language: JavaScript (javascript)

Options:

  • 'none': No framing allowed at all.
  • 'self': Only same-origin embedding allowed.
  • https://example.com: Allows embedding only from a specific domain.

Server Config Examples

Apache

  1. Enable headers module:
sudo a2enmod headers && sudo systemctl restart apache2
  1. Edit VirtualHost config:
sudo nano /etc/apache2/sites-available/000-default.confCode language: JavaScript (javascript)
  1. Add inside <VirtualHost> block:
Header always set X-Frame-Options "DENY"
Header always set Content-Security-Policy "frame-ancestors 'none'"Code language: JavaScript (javascript)
  1. Restart Apache:
sudo systemctl restart apache2

Nginx

  1. Edit server block:
sudo nano /etc/nginx/sites-available/defaultCode language: JavaScript (javascript)
  1. Add:
add_header X-Frame-Options "DENY";
add_header Content-Security-Policy "frame-ancestors 'none'";Code language: JavaScript (javascript)
  1. Reload Nginx:
sudo systemctl reload nginx

WordPress

Edit wp-config.php and append:

header('X-Frame-Options: SAMEORIGIN');
header("Content-Security-Policy: frame-ancestors 'none'");Code language: JavaScript (javascript)

Note: Some themes/plugins may override these headers. Validate with browser dev tools or CLI tools.


2. JavaScript Frame-Busting (Optional Layer)

Not as reliable as HTTP headers but useful as a fallback:

<style>html { display: none; }</style>
<script>
  if (self === top) {
    document.documentElement.style.display = 'block';
  } else {
    top.location = self.location;
  }
</script>Code language: HTML, XML (xml)

Backend Language Examples

Node.js / Express.js

app.use((req, res, next) => {
  res.setHeader("X-Frame-Options", "DENY");
  res.setHeader("Content-Security-Policy", "frame-ancestors 'none'");
  next();
});Code language: JavaScript (javascript)

Java (Servlet)

response.setHeader("X-Frame-Options", "DENY");
response.setHeader("Content-Security-Policy", "frame-ancestors 'none'");Code language: JavaScript (javascript)

PHP

header('X-Frame-Options: DENY');
header("Content-Security-Policy: frame-ancestors 'none'");Code language: JavaScript (javascript)

Verification & Testing

After deploying protections:

curl -I https://yoursite.comCode language: JavaScript (javascript)
  • Use OWASP ZAP or Burp Suite to simulate iframe attacks.

Final Thoughts

Clickjacking is easy to overlook but potentially devastating. In the era of SSO, cloud dashboards, and web-based admin panels, properly configured headers like Content-Security-Policy and X-Frame-Options are essential.

For defense-in-depth:

  • Use CSP with frame-ancestors.
  • Optionally add JavaScript frame-busting.
  • Monitor headers regularly as part of your security audits.

👉 Visit clickjacker.io to test if your site is vulnerable.

Scroll to Top