开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第18天,点击查看活动详情
一、简介
点击劫持是一种视觉上的欺骗手段。攻击者使用一个透明的、不可见的iframe,覆盖在一个网页上,然后诱使用户在该网页上进行操作,此时用户在不知情的情况下点击透明的iframe页面。通过调整iframe页面的位置,可以诱使用户恰好点击在iframe页面的一些功能性按钮上。
虽然受害者点击的是他所看到的网页,但其实他所点击的是被黑客精心构建的另一个置于原网页上面的透明页面
Clickjacking 是仅此于 XSS 和 CSRF 的前端漏洞,因为需要诱使用户交互,攻击成本高,所以不被重视,但危害不容小觑。
点击劫持的步骤
- 黑客创建一个网页利用 iframe 包含目标网站;
- 隐藏目标网站,使用户无法无法察觉到目标网站存在;
- 构造网页,诱变用户点击特点按钮;
- 用户在不知情的情况下点击按钮,触发执行恶意网页的命令;
二、劫持类型
2.1 Flash点击劫持
攻击者通过flash构造了点击劫持,在完成一系列复杂的动作后,最终控制了用户的摄像头。
攻击者制作了一个Flash游戏,这个游戏就是让用户去点击“CLICK”按钮,每次点击后这个按钮的位置都会发生变化。在Flash上面隐藏了一个看不见的iframe,游戏中某些点击时是有意义的,有些点击是无效的。 攻击通过诱导用户鼠标点击就能完成较复杂的动作。最终通过这一步步操作,打开了用户的摄像头。
2.2 图片覆盖攻击
点击劫持是一种视觉上的欺骗手段。那么图片覆盖也可以起到类似的作用。简称XSIO(Cross Site Image Overlaying)
原理: 利用的是图片的style,或者能够控制CSS。如果应用没有限制style的position为absolute的话,图片可以覆盖到页面上的任意位置。
<img style="position: absolute; left: 100px; top: 100px">
用户点击图片,就会链接到其他网站。
图片还可以伪装得像一个正常的链接、按钮;或者在图片中构造一些文字,覆盖在关键的位置,就有可能完全改变页面中想表达的意思。这种情况下,不需要用户点击,也能达到欺骗的目的。
由于img标签在很多系统中是对用户开放的,因此在现实生活中有非常多的站点存在在XSIO攻击的可能。在防御XSIO时,需要检查用户提交的HTML代码中,img标签的style属性是否可能导致浮出。
2.3 拖拽劫持与数据窃取
目前,许多浏览器都开始支持Drag和Drop的API。对于用户来说,拖拽使他们的操作更加简单。浏览器中的拖拽对象可以是一个链接,也可以是一段文字,还可以从一个窗口拖拽到另一个窗口,因此拖拽是不受同源策略限制的。
拖拽劫持的思路是诱使用户从隐藏不可见iframe中拖拽出攻击者希望得到的数据,然后放到攻击者能控制的另外一个页面,从而窃取数据。在JavaScript的支持下,这个攻击过程会变得非常隐蔽,因为它突破了传统ClickJacking一些先天的局限,所以这种新型的拖拽劫持能够造成更大的破坏。
国内安全研究者xisigr曾经构造了一个针对Gmail的POC,大致过程可参考POC攻击过程
2.4 ClickJacking3.0:触屏劫持
智能手机的触屏劫持攻击被斯坦福的安全研究者公布,这意味着ClickJacking的攻击方式更进一步,斯坦福安全研究者的将其称为TapJacking。
从手机角度来看,触屏实际上就是一个事件,手机捕捉这些事件,并执行相应的动作。 常见的几个事件:
touchstart: 手指触摸屏幕时发生
touchend: 手指离开屏幕时发生
touchmove: 手指滑动时发生
touchcancel: 系统可取消touch事件
将一个不可见的iframe覆盖到当前网页上,就可以劫持用户的触屏操作。
在未来,随着移动设备中浏览器功能的丰富,我们会看到更多的TapJacking
三、防御
3.1 防御ClickJacking
3.1.1 frame busting
通过可以写一段JavaScript代码,以禁止iframe的嵌套。这种方法叫作frame busting。比如
if (top.location != location) {
top.location = self.location;
}
当然,还要很多很多frame busting的写法,这里就不做赘述了。
缺点:js编写的,防御效果不好,可绕过
3.1.2 X-Frame-Options
使用HTTP头:X-Frame-Options
X-Frame-Options可以说是为了解决ClickJacking而生的,且浏览器支持较好。它有三个可选的值:
DENY 拒绝当前页面加载任何frame页面
SAMEORIGIN frame页面的地址只能为同源域名下的页面
ALLOW-FROM origin 定义允许frame加载的页面地址
例如:
- 京东:X-Frame-Options: SAMEORIGIN
- Facebook:x-frame-options: DENY
- Twitter:x-frame-options: DENY
配置 X-FRAME-OPTIONS:
-
使用 meta标签来设置
X-Frame-Options是无效的!例如<meta http-equiv="X-Frame-Options" content="deny">没有任何效果 -
配置 Apache
- 把下面这行添加到 'site' 的配置中:
Header always set X-Frame-Options "SAMEORIGIN"
-
配置nginx
- 把下面这行添加到 'http', 'server' 或者 'location',配置中
add_header X-Frame-Options SAMEORIGIN;
-
其余配置可自行百度。
除了X-Frame-Options之外,Firefox的Content Security Policy以及Firefox的NoScript扩展也能有效防御ClickJacking。这些方案为我们提供了更多的选择。
3.2 其他方式
3.2.1 阻止顶级导航
我们可以阻止因更改 beforeunload 事件处理程序中的 top.location 而引起的过渡(transition)。
顶级页面(从属于黑客)在 beforeunload 上设置了一个用于阻止的处理程序,像这样:
window.onbeforeunload = function() {
return false;
};
当 iframe 试图更改 top.location 时,访问者会收到一条消息,询问他们是否要离开页面。
在大多数情况下,访问者会做出否定的回答,因为他们并不知道还有这么一个 iframe,他们所看到的只有顶级页面,他们没有理由离开。所以 top.location 不会变化!
3.2.2 显示禁用的功能
X-Frame-Options 有一个副作用。其他的网站即使有充分的理由也无法在 iframe 中显示我们的页面。
因此,还有其他解决方案。例如,我们可以用一个样式为 height: 100%; width: 100%; 的 <div> “覆盖”页面,这样它就能拦截所有点击。如果 window == top 或者我们确定不需要保护时,再将该 <div> 移除。
<style>
#protector {
height: 100%;
width: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 99999999;
}
</style>
<div id="protector">
<a href="/" target="_blank">前往网站</a>
</div>
<script>
// 如果顶级窗口来自其他源,这里则会出现一个 error
// 但是在本例中没有问题
if (top.document.domain == document.domain) {
protector.remove();
}
</script>
四、总结
点击劫持是一种“诱骗”用户在不知情的情况下点击恶意网站的方式。如果是重要的点击操作,这是非常危险的。
黑客可以通过信息发布指向他的恶意页面的链接,或者通过某些手段引诱访问者访问他的页面。当然还有很多其他变体。
一方面 —— 这种攻击方式是“浅层”的:黑客所做的只是拦截一次点击。但另一方面,如果黑客知道在点击之后将出现另一个控件,则他们可能还会使用狡猾的消息来迫使用户也点击它们。
这种攻击相当危险,因为在设计交互界面时,我们通常不会考虑到可能会有黑客代表用户点击界面。所以,在许多意想不到的地方可能发现攻击漏洞。
- 建议在那些不希望被在 iframe 中查看的页面上(或整个网站上)使用
X-Frame-Options: SAMEORIGIN。 - 如果我们希望允许在 iframe 中显示我们的页面,那我们使用一个
<div>对整个页面进行遮盖,这样也是安全的。