同学们,早上好!我是老码农,今天咱们来聊聊一个听起来有点像好莱坞大片的网络安全问题——Clickjacking,中文名叫“点击劫持”。
啥是点击劫持?简单来说,就是坏人把你带到一个看起来无害的网站上,然后在你不知不觉中,让你点击了另一个网站上的按钮,做了你原本不想做的事情。是不是有点像电影里的催眠术?
一、点击劫持的“障眼法”
想象一下,你在网上开开心心地浏览猫片,突然出现一个弹窗,说“恭喜你获得免费iPhone!点击领取!” 你心想,天上掉馅饼了?赶紧点一下。
但实际上,这个“免费iPhone”的弹窗背后,可能隐藏着一个你正在登录的银行网站的“转账”按钮。坏人通过一些技术手段,把银行网站的转账按钮透明地覆盖在了“领取iPhone”的按钮上。你以为点击了“领取iPhone”,实际上却点击了“转账”,把钱转到了坏人的账户里。
这就是点击劫持的精髓:欺骗用户点击隐藏的元素,执行恶意操作。
它主要利用了 HTML 中的 <iframe>
标签。 <iframe>
允许在一个网页中嵌入另一个网页。坏人就可以把目标网站嵌入到自己的网站里,然后通过 CSS 样式,把目标网站隐藏起来或者透明化。
举个例子:
<!DOCTYPE html>
<html>
<head>
<title>Clickjacking Example</title>
<style>
#evilFrame {
position: relative;
width: 300px;
height: 200px;
opacity: 0.0001; /* 几乎完全透明 */
z-index: 2; /* 放在猫片上面 */
}
#catPicture {
position: relative;
width: 300px;
height: 200px;
z-index: 1; /* 放在 evilFrame 下面 */
}
</style>
</head>
<body>
<img id="catPicture" src="cat.jpg" alt="可爱的猫咪" />
<iframe id="evilFrame" src="https://your-bank.com/transfer.html"></iframe>
<p>看起来没什么问题,对吧?</p>
</body>
</html>
在这个例子中:
cat.jpg
是一张猫片,用来吸引你的注意力。https://your-bank.com/transfer.html
是你的银行网站的转账页面(假设存在)。evilFrame
这个<iframe>
元素,用 CSS 设置了opacity: 0.0001;
,几乎完全透明,并且用z-index
属性把它放在了猫片上面。
当你点击猫片的时候,实际上点击的是 evilFrame
里的转账按钮!
二、点击劫持的常见套路
点击劫持的套路五花八门,但万变不离其宗,都是利用 <iframe>
标签和 CSS 样式来欺骗用户。常见的套路包括:
- Like劫持: 伪装成社交网站的“喜欢”按钮,诱导用户点击,实际上是让用户关注了某个恶意账号或者发布了恶意内容。
- Flash劫持: 利用 Flash 的透明窗口,覆盖在目标网站上,诱导用户点击 Flash 窗口,实际上是点击了目标网站上的按钮。
- Cursor劫持: 改变鼠标指针的位置,让用户以为点击的是某个按钮,实际上点击的是另一个按钮。
三、防御点击劫持的“金钟罩”
要防御点击劫持,就像练武功一样,需要内外兼修。
1. X-Frame-Options:简单粗暴但有效
X-Frame-Options
是一个 HTTP 响应头,用来告诉浏览器是否允许当前页面被嵌入到 <iframe>
中。它有三个可选值:
- DENY: 完全禁止当前页面被嵌入到
<iframe>
中。 - SAMEORIGIN: 只允许同源域名下的页面嵌入当前页面。
- ALLOW-FROM uri: 允许指定域名下的页面嵌入当前页面(不推荐使用,浏览器支持不一致)。
举个例子,如果你的银行网站设置了 X-Frame-Options: DENY
,那么坏人就无法把你的银行网站嵌入到他的恶意网站里了。
如何设置 X-Frame-Options?
- Apache: 在
.htaccess
文件中添加:Header always set X-Frame-Options "DENY"
- Nginx: 在
nginx.conf
文件中添加:add_header X-Frame-Options "DENY";
- Java (Servlet):
response.setHeader("X-Frame-Options", "DENY");
- PHP:
header('X-Frame-Options: DENY');
- Node.js (Express):
app.use(function(req, res, next) { res.setHeader('X-Frame-Options', 'DENY'); next(); });
X-Frame-Options
的优点是简单易用,兼容性好。但缺点也很明显:只能设置一个域名,无法灵活地控制哪些域名可以嵌入当前页面。
2. Content-Security-Policy (CSP):更强大的“护身符”
Content-Security-Policy (CSP)
是一个更强大的 HTTP 响应头,可以控制浏览器可以加载哪些资源,包括是否允许嵌入到 <iframe>
中。
CSP 使用 frame-ancestors
指令来控制哪些域名可以嵌入当前页面。
举个例子:
Content-Security-Policy: frame-ancestors 'self' https://example.com;
这个 CSP 策略表示:
'self'
:允许同源域名下的页面嵌入当前页面。https://example.com
:允许https://example.com
域名下的页面嵌入当前页面。
如何设置 CSP?
- Apache: 在
.htaccess
文件中添加:Header always set Content-Security-Policy "frame-ancestors 'self' https://example.com;"
- Nginx: 在
nginx.conf
文件中添加:add_header Content-Security-Policy "frame-ancestors 'self' https://example.com;";
- Java (Servlet):
response.setHeader("Content-Security-Policy", "frame-ancestors 'self' https://example.com");
- PHP:
header("Content-Security-Policy: frame-ancestors 'self' https://example.com");
- Node.js (Express):
app.use(function(req, res, next) { res.setHeader('Content-Security-Policy', "frame-ancestors 'self' https://example.com"); next(); });
CSP 的优点是功能强大,可以灵活地控制哪些域名可以嵌入当前页面,还可以控制其他资源的加载。缺点是配置复杂,兼容性不如 X-Frame-Options
。
CSP 的更多用法
除了 frame-ancestors
指令,CSP 还有很多其他的指令,可以用来控制各种资源的加载:
指令 | 描述 |
---|---|
default-src |
定义了其他指令未定义时默认的资源加载策略。 |
script-src |
定义了允许加载的 JavaScript 资源的来源。 |
style-src |
定义了允许加载的 CSS 资源的来源。 |
img-src |
定义了允许加载的图片资源的来源。 |
connect-src |
定义了允许建立的 HTTP 连接的来源(例如,AJAX 请求、WebSocket)。 |
font-src |
定义了允许加载的字体资源的来源。 |
media-src |
定义了允许加载的媒体资源的来源(例如,视频、音频)。 |
object-src |
定义了允许加载的插件资源的来源(例如,Flash)。 |
frame-src |
已经过时,请使用 frame-ancestors 。 |
child-src |
定义了允许加载的 Web Worker 和嵌套的浏览上下文(例如,<iframe> )的来源。 |
form-action |
定义了允许提交表单的 URL。 |
upgrade-insecure-requests |
指示浏览器将所有 HTTP URL 视为 HTTPS,并将所有不安全的请求转换为安全请求。这有助于防止混合内容错误,并提高网站的安全性。 |
block-all-mixed-content |
确保浏览器不会加载任何使用 HTTP 的资源。这有助于避免中间人攻击,并确保网站的所有资源都通过加密连接加载。 |
例如,你可以使用以下 CSP 策略来限制 JavaScript 只能从同源域名加载:
Content-Security-Policy: script-src 'self';
3. JavaScript 防御:最后的“防线”
即使设置了 X-Frame-Options
或 CSP,仍然有一些特殊情况可能导致点击劫持攻击成功。例如,某些老旧浏览器可能不支持这些 HTTP 响应头。
因此,我们可以在客户端使用 JavaScript 来进行额外的防御。
JavaScript 防御的原理:
通过 JavaScript 代码,检测当前页面是否被嵌入到 <iframe>
中。如果被嵌入,就采取一些措施,例如:
- 隐藏页面: 直接把页面隐藏起来,让用户无法看到。
- 重定向页面: 把页面重定向到当前域名的顶级页面,防止被恶意网站利用。
JavaScript 防御的代码示例:
if (window.top !== window.self) {
// 页面被嵌入到 <iframe> 中
window.top.location.href = window.self.location.href; // 重定向到顶级页面
// 或者
document.body.style.display = 'none'; // 隐藏页面
}
这段代码的原理很简单:
window.top
指的是最顶层的窗口对象。window.self
指的是当前窗口对象。
如果当前页面没有被嵌入到 <iframe>
中,那么 window.top
和 window.self
指向的是同一个对象。如果当前页面被嵌入到 <iframe>
中,那么 window.top
指的是包含 <iframe>
的页面的窗口对象,而 window.self
指的是 <iframe>
内部的页面的窗口对象。
JavaScript 防御的注意事项:
- 兼容性: 确保 JavaScript 代码在各种浏览器上都能正常运行。
- 性能: 尽量避免使用过于复杂的 JavaScript 代码,以免影响页面性能。
- 误判: 有些正常情况下也可能出现
window.top !== window.self
的情况,例如,页面被嵌入到 Chrome 扩展程序的<iframe>
中。因此,需要谨慎判断,避免误判。
四、总结:内外兼修,防患于未然
防御点击劫持,需要从服务器端和客户端两方面入手,内外兼修。
| 防御措施 | 优点 | 缺点 | 适用场景 |
| ——————- | ——————————————————————- | ————————————————————————————————– | ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————</
X-Frame-
X-Frame-Options:
3.
|
|作用: X-Frame-Options
HTTP 响应标头允许网站指示浏览器是否允许页面呈现在 <frame>
、<iframe>
或其他外部框架中。使用它可以防止点击劫持式攻击,攻击者会将您的页面嵌入到他们自己的网站中,以诱骗用户执行某些操作。 | 简单,易配置,对代码无侵入性。 | 不够灵活,只能粗粒度设置,无法满足复杂场景需求。 | 站点需要防止所有或者来自特定站点嵌入的场景. |
|配置:在服务器配置文件中添加,例如 nginx.conf
或 .htaccess
。|
|常见配置值: DENY
: 完全禁止任何站点嵌入。 SAMEORIGIN
: 只允许同源站点嵌入。 ALLOW-FROM uri
: 允许指定站点嵌入(不推荐,存在兼容性问题)。 |
1. Content-Security-Policy (CSP):
作用: CSP 是一种更全面的安全策略,可以控制浏览器允许加载的资源来源。通过 frame-ancestors
指令,可以精确控制哪些站点可以嵌入当前页面。
优点: 功能强大,灵活性高,可以进行细粒度的权限控制。
缺点: 配置复杂,学习成本高。
适用场景: 站点需要更精细的权限控制,例如允许特定站点嵌入,或者需要控制其他资源加载策略。
配置: 在服务器配置文件中添加,例如 nginx.conf
或 .htaccess
。
常见配置值: frame-ancestors 'self' https://example.com;
允许同源站点和 https://example.com
嵌入。
2. JavaScript 防御:
作用: 在客户端使用 JavaScript 代码检测页面是否被嵌入到 iframe 中,如果被嵌入,则采取措施阻止攻击。
优点: 可以作为额外的安全保障,防止 X-Frame-Options 或 CSP 配置错误或失效。
缺点: 依赖客户端 JavaScript 代码执行,可能被绕过,且可能存在兼容性问题。
适用场景: 作为额外的防御手段,增强站点的安全性。
配置: 在页面中添加 JavaScript 代码,例如:
if (window.top !== window.self) {
window.top.location.href = window.self.location.href;
}
最佳实践:
- 优先使用 CSP: CSP 提供了更强大和灵活的防御能力,是首选的防御手段。
- 配置 X-Frame-Options 作为备选: 对于不支持 CSP 的浏览器,X-Frame-Options 可以提供基本的防御。
- 使用 JavaScript 代码作为额外的保障: 在客户端使用 JavaScript 代码检测和阻止点击劫持攻击,提高站点的安全性。
记住,没有绝对安全的系统,只有不断加强防御,才能有效地保护我们的网站和用户免受点击劫持的威胁。
好了,今天的讲座就到这里。大家有什么问题可以提问。希望大家以后也能像保护自己的眼睛一样,保护好自己的网络安全!谢谢大家!