Skip to content
intermediatePhase 41 · Frontend Security

Clickjacking

Protect against clickjacking with X-Frame-Options and CSP.

30m
0 problems
Topic Progress0%

Clickjacking Attacks

Clickjacking Attacks

How Clickjacking Works

  1. Attacker creates fake UI over legitimate site
  2. User thinks they're clicking one thing
  3. Actually clicks on hidden element
  4. Performs unintended action

Example Attack

<!-- Attacker's site -->
<style>
  .target-site {
    position: relative;
    width: 300px;
    height: 150px;
    opacity: 0.0001;
    z-index: 2;
  }
  .decoy {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
  }
</style>

<div class="decoy">
  <h1>Click here to win a prize!</h1>
</div>

<iframe src="https://bank.com/transfer" class="target-site"></iframe>

Vulnerable Actions

  • Financial transactions
  • Changing user settings
  • Deleting accounts
  • Granting permissions
  • Liking/sharing content

Types of Clickjacking

  1. Classic: Hidden iframe
  2. Likejacking: Fake like button
  3. Cursorjacking: Changes cursor position
  4. Filejacking: Hidden file upload

X-Frame-Options

X-Frame-Options

Header Options

// DENY: Cannot be framed at all
app.use((req, res, next) => {
  res.setHeader('X-Frame-Options', 'DENY');
  next();
});

// SAMEORIGIN: Can be framed by same origin
app.use((req, res, next) => {
  res.setHeader('X-Frame-Options', 'SAMEORIGIN');
  next();
});

// ALLOW-FROM: Can be framed by specific origin (deprecated)
app.use((req, res, next) => {
  res.setHeader('X-Frame-Options', 'ALLOW-FROM https://example.com');
  next();
});

Content-Security-Policy

// Modern approach using CSP
app.use((req, res, next) => {
  res.setHeader(
    'Content-Security-Policy',
    "frame-ancestors 'none'" // Same as DENY
  );
  next();
});

// Allow framing from same origin
app.use((req, res, next) => {
  res.setHeader(
    'Content-Security-Policy',
    "frame-ancestors 'self'" // Same as SAMEORIGIN
  );
  next();
});

// Allow specific origins
app.use((req, res, next) => {
  res.setHeader(
    'Content-Security-Policy',
    "frame-ancestors 'self' https://trusted.com"
  );
  next();
});

Nginx Configuration

# Add to server block
add_header X-Frame-Options "DENY";
add_header Content-Security-Policy "frame-ancestors 'none'";

# Or for same origin only
add_header X-Frame-Options "SAMEORIGIN";
add_header Content-Security-Policy "frame-ancestors 'self'";

Apache Configuration

# Add to .htaccess or config
Header always set X-Frame-Options "DENY"
Header always set Content-Security-Policy "frame-ancestors 'none'"

When to Use Each

  • DENY: Most secure, prevents all framing
  • SAMEORIGIN: Allows framing by own pages
  • ALLOW-FROM: Deprecated, use CSP instead

CSP frame-ancestors vs X-Frame-Options

Feature X-Frame-Options CSP frame-ancestors
Multiple origins No Yes
Wildcards No Yes
Browser support Older browsers Modern browsers
Flexibility Limited More flexible

JavaScript Frame Busting

JavaScript Frame Busting

Basic Frame Buster

// Prevent framing
if (window.top !== window.self) {
  window.top.location = window.self.location;
}

Advanced Frame Buster

// More robust frame busting
(function() {
  'use strict';
  
  if (window.top !== window.self) {
    // Try multiple methods
    try {
      window.top.location = window.self.location;
    } catch (e) {
      // If cross-origin, use alternative
      if (window.top && window.top.location) {
        window.top.location.href = window.self.location.href;
      }
    }
  }
})();

Frame Busting Limitations

  1. Can be bypassed with sandboxed iframes
  2. Not reliable with multiple frames
  3. Performance impact on page load
  4. Better to use headers (CSP, X-Frame-Options)

Server-side Protection (Recommended)

// Always use server-side headers
app.use((req, res, next) => {
  res.setHeader('X-Frame-Options', 'DENY');
  res.setHeader(
    'Content-Security-Policy',
    "frame-ancestors 'none'"
  );
  next();
});

// Frame busting as additional defense
app.get('/', (req, res) => {
  res.send(`
    <!DOCTYPE html>
    <html>
    <head>
      <script>
        if (window.top !== window.self) {
          window.top.location = window.self.location;
        }
      </script>
    </head>
    <body>...</body>
    </html>
  `);
});

Best Practices

  1. Use CSP frame-ancestors (preferred)
  2. Use X-Frame-Options (for older browsers)
  3. JavaScript frame busting as fallback
  4. Set headers server-side
  5. Test with iframe

Testing Clickjacking Protection

// Test that page cannot be framed
describe('Clickjacking Protection', () => {
  it('should set X-Frame-Options header', async () => {
    const response = await request(app).get('/');
    expect(response.headers['x-frame-options']).toBe('DENY');
  });

  it('should set CSP frame-ancestors', async () => {
    const response = await request(app).get('/');
    expect(response.headers['content-security-policy'])
      .toContain("frame-ancestors 'none'");
  });
});

Common Mistakes

  1. Only using JavaScript (easily bypassed)
  2. Using ALLOW-FROM (deprecated, limited)
  3. Not setting headers on all pages
  4. Using X-Frame-Options with CSP (redundant but safe)
  5. Not testing frame protection

Practice Problems

0/3solved
Build Clickjacking Component

Create a reusable React component implementing Clickjacking. Include proper state management and accessibility.

Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where needed
Clickjacking Testing

Write unit and integration tests for Clickjacking using React Testing Library.

Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility tests
Clickjacking Performance

Optimize Clickjacking for performance. Consider memoization, code splitting, and bundle size.

Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysis

Quiz

1. What is clickjacking?

Question 1 options

2. What is the best way to prevent clickjacking?

Question 2 options

3. What is the primary purpose of Clickjacking?

Question 3 options

4. What is a common mistake when implementing Clickjacking?

Question 4 options

Flashcards

Question

What is clickjacking?

Answer

A UI redress attack where users are tricked into clicking hidden elements.

Question

What does X-Frame-Options DENY do?

Answer

Prevents the page from being embedded in any iframe.

Question

What is CSP frame-ancestors?

Answer

A CSP directive that controls which origins can frame the page.

Question

What is frame busting?

Answer

JavaScript code that breaks out of iframes by redirecting the top window.

Question

What is Clickjacking?

Answer

Clickjacking is a key concept in frontend development.

Revision Notes

Key Takeaways

  • 1.Clickjacking tricks users into clicking hidden elements
  • 2.CSP frame-ancestors is the preferred protection method
  • 3.X-Frame-Options is a simpler alternative for older browsers
  • 4.JavaScript frame busting is unreliable and can be bypassed
  • 5.Set headers server-side for all pages

Interview Tips

  • Explain how clickjacking attacks work
  • Discuss X-Frame-Options vs CSP frame-ancestors
  • Know why JavaScript frame busting is unreliable

Cheat Sheet

Clickjacking Prevention Cheat Sheet

Attack

  • Hidden iframe over legitimate site
  • User clicks thinking it's safe
  • Actually performs unintended action

Prevention

  1. CSP frame-ancestors (preferred)
  2. X-Frame-Options header
  3. JavaScript frame busting (fallback)

Headers

X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'none'

Values

  • DENY: No framing
  • SAMEORIGIN: Same origin only
  • frame-ancestors 'none': No framing
  • frame-ancestors 'self': Same origin only