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.com

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'

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.conf
  1. Add inside <VirtualHost> block:
Header always set X-Frame-Options "DENY"
Header always set Content-Security-Policy "frame-ancestors 'none'"
  1. Restart Apache:
sudo systemctl restart apache2

Nginx

  1. Edit server block:
sudo nano /etc/nginx/sites-available/default
  1. Add:
add_header X-Frame-Options "DENY";
add_header Content-Security-Policy "frame-ancestors 'none'";
  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'");

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>

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();
});

Java (Servlet)

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

PHP

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

Verification & Testing

After deploying protections:

curl -I https://yoursite.com
  • 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