点击劫持 (Clickjacking)
点击劫持是一种 Web 安全漏洞,恶意网站通过它欺骗用户点击与其感知的不同的内容,从而可能导致用户在不知情或未经许可的情况下执行非预期的操作。用户被诱导执行各种非预期操作,如输入密码、点击“删除我的账户”按钮、点击“赞”、删除帖子、在博客上评论。换句话说,普通用户在合法网站上可以执行的所有操作,都可以通过点击劫持来实现。
摘要 (Summary)
- 工具 (#tools)
- 方法论 (#methodology)
- 预防措施 (#preventive-measures)
- OnBeforeUnload 事件 (#onbeforeunload-event)
- XSS 过滤器 (#xss-filter)
- 挑战 (#challenge)
- 实验环境 (#labs)
- 参考资料 (#references)
工具 (Tools)
方法论 (Methodology)
UI 界面重绘 (UI Redressing)
UI 重绘是一种点击劫持技术,攻击者在合法网站或应用程序的顶部覆盖一个透明的 UI 元素。该透明元素包含恶意内容或操作,且对用户视觉隐藏。通过操纵元素的透明度和位置,攻击者可以诱导用户与隐藏内容互动,而用户则认为自己正在与可见的界面互动。
- UI 重绘的工作原理:
- 覆盖透明元素:攻击者创建一个覆盖合法网站整个可见区域的透明 HTML 元素(通常是
<div>)。使用opacity: 0;等 CSS 属性使其透明。 - 定位和分层:通过设置
position: absolute; top: 0; left: 0;等 CSS 属性,将透明元素定位为覆盖整个视口。由于它是透明的,用户看不到它。 - 误导用户交互:攻击者在透明容器内放置欺骗性元素,如伪造的按钮、链接或表单。这些元素在被点击时执行操作,但由于透明 UI 元素的覆盖,用户并不知晓其存在。
- 用户交互:当用户与可见界面互动时,由于透明覆盖层的存在,他们会在不知不觉中与隐藏元素互动。这种交互可能导致非预期的操作或未经授权的操作。
- 覆盖透明元素:攻击者创建一个覆盖合法网站整个可见区域的透明 HTML 元素(通常是
<div style="opacity: 0; position: absolute; top: 0; left: 0; height: 100%; width: 100%;">
<a href="malicious-link">点击我</a>
</div>
不可见框架 (Invisible Frames)
不可见框架是一种点击劫持技术,攻击者使用隐藏的 iframe 诱导用户在不知情的情况下与来自另一个网站的内容互动。通过将这些 iframe 的维度设置为零(height: 0; width: 0;)并移除边框(border: none;),可以使其不可见。这些不可见框架内的内容可能是恶意的,例如钓鱼表单、恶意软件下载或其他任何有害操作。
-
不可见框架的工作原理:
- 创建隐藏 IFrame:攻击者在网页中包含一个
<iframe>元素,将其维度设置为零并移除边框,使其对用户不可见。
- 加载恶意内容:iframe 的 src 属性指向由攻击者控制的恶意网站或资源。由于 iframe 是不可见的,这些内容在用户不知情的情况下静默加载。
- 用户交互:攻击者在不可见 iframe 之上覆盖诱人的元素,使其看起来像是用户正在与可见界面互动。例如,攻击者可能在不可见 iframe 上方放置一个透明按钮。当用户点击按钮时,他们实际上是在点击 iframe 内隐藏的内容。
- 非预期操作:由于用户对不可见 iframe 毫无察觉,他们的交互可能导致非预期的操作,如提交表单、点击恶意链接,甚至在未经许可的情况下执行金融交易。
- 创建隐藏 IFrame:攻击者在网页中包含一个
按钮/表单劫持 (Button/Form Hijacking)
按钮/表单劫持是一种点击劫持技术,攻击者诱导用户与不可见或隐藏的按钮/表单进行互动,从而在合法网站上导致非预期的操作。通过在可见的按钮或表单上方覆盖欺骗性元素,攻击者可以操纵用户的交互动作,在用户不知情的情况下执行恶意操作。
-
按钮/表单劫持的工作原理:
- 可见界面:攻击者向用户呈现一个可见的按钮或表单,鼓励他们点击或与之互动。
- 隐形覆盖层:攻击者在可见按钮或表单上方覆盖一个包含恶意操作(如提交隐藏表单)的不可见或透明元素。
<form action="malicious-site" method="POST" id="hidden-form" style="display: none;"> <!-- 隐藏的表单字段 --> </form>- 欺骗性交互:当用户点击可见按钮时,由于不可见覆盖层的存在,他们会在不经意间与隐藏表单互动。表单被提交,可能导致未经授权的操作或数据泄露。
执行方法 (Execution Methods)
- 创建隐藏表单:攻击者创建一个包含恶意输入字段的隐藏表单,目标是受害者网站上易受攻击的操作。此表单对用户保持不可见。
<form action="malicious-site" method="POST" id="hidden-form" style="display: none;">
<input type="hidden" name="username" value="attacker">
<input type="hidden" name="action" value="transfer-funds">
</form>
- 覆盖可见元素:攻击者在恶意页面上覆盖一个可见元素(按钮或表单),鼓励用户与之互动。当用户点击可见元素时,不经意间触发了隐藏表单的提交。
预防措施 (Preventive Measures)
实施 X-Frame-Options 标头
使用 DENY 或 SAMEORIGIN 指令实施 X-Frame-Options 标头,以防止您的网站在未经许可的情况下被嵌入到 iframe 中。
内容安全策略 (CSP) (Content Security Policy)
使用 CSP 控制您网站上能够加载内容的来源,包括脚本、样式和框架。定义一个完善的 CSP 策略,以防止未经授权的框架嵌套和外部资源加载。 HTML meta 标签示例:
禁用 JavaScript
- 由于此类客户端防御措施依赖于 JavaScript 的框架破坏 (frame busting) 代码,如果受害者禁用了 JavaScript,或者攻击者可以使 JavaScript 代码失效,那么该页面将没有任何防御点击劫持的机制。
-
针对框架有三种停用技术:
- Internet Explorer 的受限框架:从 IE6 开始,框架可以拥有
security属性。如果设置为restricted,则确保该框架内的 JavaScript 代码、ActiveX 控件和重定向到其他网站的操作无效。
- Sandbox 属性:HTML5 引入了一个名为
sandbox的新属性。它对加载到 iframe 中的内容启用一系列限制。目前此属性仅与 Chrome 和 Safari 兼容。
- Internet Explorer 的受限框架:从 IE6 开始,框架可以拥有
OnBeforeUnload 事件
-
onBeforeUnload事件可用于逃避框架破坏代码。当框架破坏代码想要通过在整个网页加载 URL 来销毁 iframe 时,该事件将被调用。处理函数返回一个字符串,提示用户确认是否离开页面。当此字符串显示给用户时,用户很可能会取消跳转,从而挫败目标网站的框架破坏尝试。 -
攻击者可以通过使用以下示例代码在顶层页面注册一个卸载事件:
<h1>www.fictitious.site</h1>
<script>
window.onbeforeunload = function()
{
return " 您确定要离开 fictitious.site 吗?";
}
</script>
<iframe src="http://目标网站">
- 前一种技术需要用户交互,但同样的结果可以在不提示用户的情况下实现。攻击者只需在
onBeforeUnload事件处理器中不断提交(例如每毫秒一次)一个指向返回 "HTTP/1.1 204 No Content" 标头的网页导航请求,即可自动取消即将发生的导航请求。
204 页面:
攻击者页面:
<script>
var prevent_bust = 0;
window.onbeforeunload = function() {
prevent_bust++;
};
setInterval(
function() {
if (prevent_bust > 0) {
prevent_bust -= 2;
window.top.location = "http://attacker.site/204.php";
}
}, 1);
</script>
<iframe src="http://目标网站">
XSS 过滤器 (XSS Filter)
IE8 XSS 过滤器
该过滤器监控通过浏览器的所有请求和响应参数,并将它们与一系列正则表达式进行比较,以寻找反射型 XSS 尝试。当过滤器识别出可能的 XSS 攻击时,它会禁用页面内的所有内联脚本,包括框架破坏脚本(同样的情况也可以发生在外部脚本上)。因此,攻击者通过在请求参数中插入框架破坏脚本的开头,即可诱发假阳性。
攻击者视角:
Chrome 4.0 XSSAuditor 过滤器
与 IE8 XSS 过滤器相比,它的行为略有不同。通过该过滤器,攻击者可以通过在请求参数中传递脚本代码来停用该“脚本”。这使得框架页面能够专门针对包含框架破坏代码的单一段落,而保持所有其他代码完好。
攻击者视角:
挑战 (Challenge)
检查以下代码:
<div style="position: absolute; opacity: 0;">
<iframe src="https://legitimate-site.com/login" width="500" height="500"></iframe>
</div>
<button onclick="document.getElementsByTagName('iframe')[0].contentWindow.location='malicious-site.com';">点击我</button>
确定这段代码中的点击劫持漏洞。找出隐藏的 iframe 是如何被用来在用户点击按钮时利用其行为,从而将其引向恶意网站的。