点击劫持(Clickjacking)是一种恶意攻击技术,攻击者通过透明或不透明的层覆盖在看似无害的网页元素上,诱使用户在不知情的情况下点击隐藏的恶意内容。本文将介绍几种使用JavaScript防御点击劫持的有效方案。
1. X-Frame-Options 头
虽然不是纯JavaScript解决方案,但X-Frame-Options是最基础的防御措施,可以与JavaScript配合使用:
javascript
// 在服务器端设置(Node.js示例)
app.use((req, res, next) => {
res.setHeader('X-Frame-Options', 'SAMEORIGIN');
next();
});
2. Frame Busting 脚本
传统的框架破坏技术可以防止页面被嵌入到iframe中:
javascript
if (top != self) {
top.location = self.location;
}
然而,这种方法存在被绕过的情况(如使用sandbox属性),需要配合其他技术使用。
3. 现代防御:Content Security Policy (CSP)
CSP提供更强大的防护,可以通过HTTP头或meta标签设置:
javascript
// 服务器端设置(Node.js示例)
app.use((req, res, next) => {
res.setHeader("Content-Security-Policy", "frame-ancestors 'self'");
next();
});
4. 视觉混淆防御
对于敏感操作,可以添加确认步骤或视觉干扰:
javascript
document.getElementById('sensitive-button').addEventListener('click', function(e) {
const randomX = Math.floor(Math.random() * 10) - 5;
const randomY = Math.floor(Math.random() * 10) - 5;
// 轻微移动按钮位置,破坏攻击者的覆盖层对齐
this.style.position = 'relative';
this.style.left = `${randomX}px`;
this.style.top = `${randomY}px`;
// 添加二次确认
if (!confirm('确定要执行此操作吗?')) {
e.preventDefault();
}
});
5. 鼠标移动检测
检测鼠标移动轨迹是否可疑:
javascript
let lastX, lastY;
document.addEventListener('mousemove', function(e) {
if (lastX !== undefined && lastY !== undefined) {
const distance = Math.sqrt(
Math.pow(e.clientX - lastX, 2) +
Math.pow(e.clientY - lastY, 2)
);
// 如果鼠标直接从页面外移动到按钮上,可能是点击劫持
if (distance > 100) {
alert('检测到可疑操作,请刷新页面后重试');
window.location.reload();
}
}
lastX = e.clientX;
lastY = e.clientY;
});
6. 组合防御策略
最有效的防御是组合多种技术:
javascript
// 检查是否在iframe中
if (window !== window.top) {
// 尝试框架破坏
window.top.location = window.location;
// 如果框架破坏失败,隐藏敏感内容
document.body.innerHTML = '<h1>此页面不能嵌入到iframe中</h1>';
// 同时可以发送安全警报
fetch('/security-log', {
method: 'POST',
body: JSON.stringify({type: 'clickjacking_attempt'})
});
}
// 为敏感按钮添加保护
document.querySelectorAll('.protected-btn').forEach(btn => {
btn.addEventListener('mouseover', function() {
this.style.transform = `translate(${Math.random()*5-2.5}px, ${Math.random()*5-2.5}px)`;
});
btn.addEventListener('click', function(e) {
if (!confirm('确认操作?')) {
e.preventDefault();
e.stopPropagation();
}
});
});
最佳实践建议
- 优先使用服务器端防御:X-Frame-Options和CSP等HTTP头是最可靠的防御手段
- JavaScript作为补充:在客户端添加额外的保护层
- 敏感操作多重验证:关键操作应要求重新认证或二次确认
- 持续监控:记录可疑行为并报警
- 定期更新防御策略:随着攻击技术演变,防御措施也需要更新
点击劫持防御需要多层次的安全措施,结合服务器端和客户端技术,才能提供全面的保护。