Clickjacking Attacks
Clickjacking Attacks
How Clickjacking Works
- Attacker creates fake UI over legitimate site
- User thinks they're clicking one thing
- Actually clicks on hidden element
- 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
- Classic: Hidden iframe
- Likejacking: Fake like button
- Cursorjacking: Changes cursor position
- 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
- Can be bypassed with sandboxed iframes
- Not reliable with multiple frames
- Performance impact on page load
- 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
- Use CSP frame-ancestors (preferred)
- Use X-Frame-Options (for older browsers)
- JavaScript frame busting as fallback
- Set headers server-side
- 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
- Only using JavaScript (easily bypassed)
- Using ALLOW-FROM (deprecated, limited)
- Not setting headers on all pages
- Using X-Frame-Options with CSP (redundant but safe)
- Not testing frame protection
Practice Problems
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 neededWrite 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 testsOptimize 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 analysisQuiz
1. What is clickjacking?
2. What is the best way to prevent clickjacking?
3. What is the primary purpose of Clickjacking?
4. What is a common mistake when implementing Clickjacking?
Flashcards
Question
What is clickjacking?
Click to reveal answer
Answer
A UI redress attack where users are tricked into clicking hidden elements.
Question
What does X-Frame-Options DENY do?
Click to reveal answer
Answer
Prevents the page from being embedded in any iframe.
Question
What is CSP frame-ancestors?
Click to reveal answer
Answer
A CSP directive that controls which origins can frame the page.
Question
What is frame busting?
Click to reveal answer
Answer
JavaScript code that breaks out of iframes by redirecting the top window.
Question
What is Clickjacking?
Click to reveal answer
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
- CSP frame-ancestors (preferred)
- X-Frame-Options header
- 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