文件对话框

文件上传对话框是一直以来就存在的网页控件。

到了 HTML5 时代,增加了更多的功能,例如支持文件多选。Chrome 甚至还支持「上传文件夹」这一私有特征:

<input type="file" webkitdirectory />

在给用户方便的同时,其安全隐患也逐渐出现。用户平时在下载时,理所当然的弹出的是保存对话框,因此常常不仔细看就做出了选择。

这极有可能被攻击者所利用。一些恶意网站在用户点击下载时,故意弹出一个上传对话框。只要用户一疏忽,就把选中的文件夹给上传了!

下载对话框

上传对话框

当然,仅仅依靠默认的上传,这种攻击方式仍有较大难度。因为整个文件夹可能非常大,上传需要很久的时间。

如果用户等了半天也没看见下载进度,或许就会刷新重试,甚至放弃了。

选择即授权

然而,HTML5 带来了一个新的规范 —— File API,允许脚本访问文件。

但由于沙箱限制,脚本无法访问任何一个本地文件,除非用户主动授权。如何授权?最常见的,就是「上传对话框」了。

事实上,如今的上传对话框,早已不是从前「选择哪个文件」的功能,而是「允许脚本访问哪个文件」的权限申请!只不过界面上没有提示罢了。

例如,一个传统的文件上传控件。当用户选中文件后,即可通过 File API 读取文件内容:

<input id="dialog" type="file" />
<script>
dialog.onchange = function(e) {
var reader = new FileReader();
reader.onload = function() {
console.log(this.result);
};
reader.readAsText(this.files[0]);
};
</script>

或许你已注意到,File 位于files[]而不是file,这正是给文件夹预留的!

在 Chrome 里,上传控件只要加上 webkitdirectory 属性,就变成文件夹选择框。这时一旦用户选中某个文件夹,瞬间就赐予脚本访问整个文件夹的权限!

<input id="dialog" type="file" webkitdirectory />
<script>
dialog.onchange = function(e) {
var files = this.files;
var table = {}; for (var i = 0; i < files.length; i++) {
var f = files[i];
var dt = new Date(f.lastModified); table[i] = {
path: f.webkitRelativePath,
size: f.size,
modified: dt.toLocaleString()
};
} console.table(table);
};
</script>

演示

于是,用户本想将文件保存在桌面上,结果却将桌面上的所有资料,被攻击者的脚本拿到!

优化上传

一旦脚本可主动访问,我们可以用更灵活的方式处理这些文件,无需再用传统落后的方式上传。我们可以直接在前端分析出「有价值」的文件,例如:

  • 备注文件、脚本、批处理、电子表格等,很可能存有一些敏感信息,而且体积小价值大,优先将其上传;

  • 图片则可通过 canvas 缩放,先传较小的缩略图。当接收端发现有意义时,再传输原文件。

  • 对于一些体积较大但意义不大的文件,则可以直接忽略。

由于 HTTP 上传是没有压缩的,因此在传输文本文件时效率很低。我们可以借助 Flash 内置的LZMA压缩算法,极大提升传输效率。如果不支持 Flash,也可以使用asm.js版的 LZMA 压缩器,配合Worker线程在后台压缩和传输。

同时,将多个小文件合并后再压缩,可进一步提高压缩率。再多开几个连接,上传速度即可大幅提升。

续点上传

不过即使再优化,仍有传不完的可能。因此,我们得将没传完的内容储存起来,当用户再次回来时,继续传输。

得益于 HTML5 的 Storage API,这不难实现。

事实上,当用户授权了某个文件夹时,我们首先要做的不是发送,而是读出文件夹内容,立即备份到 Storage 里。毕竟,文件的读取需要用户主动配合,是非常珍贵的;而访问 Storage 则无需任何条件。

当备份完成后,再从 Storage 里读取、发送、删除。这样,即使中途页面刷新或关闭了,下次回来时,仍能从 Storage 中继续。

考虑到每个域的 Storage 容量有限,我们可以使用iframe嵌入多个不同域的页面,然后通过postMessage进行数据的分发和汇总,这样就不受容量限制了。

当然,能不能无限容量还得看浏览器策略,不然硬盘会被撑满

将数据存放在 Storage 里还有另一个好处,即使用户永不回来,但数据仍持久保存着。只要以后一旦进入其他的站点,只要是我们可控的,仍有机会继续上传。(例如将用户引到我们布置了 XSS 的站点上)

延长上传

在之前《延长 XSS 生命期》 中介绍过,可以使用各种黑魔法来提升脚本有效期。

利用这个原理,即使当前页面关闭,其他关联的页面也能继续上传。事实上,除了文中提到的方法,如今还有一个新的 API —— SharedWorker,它可以让 Worker 共享于多个页面,只要有一个存在,线程就不会停止。可以让续点时丢失的数据更少。

视觉欺骗

由于上传控件有着独特的界面,如何才能让用户主动去点呢?万能的方法是点击劫持(Clickjacking)。

不过本场景无需这么麻烦,只需简单的调用控件的click方法就可以了。

<a href="ed2k://|file|xxxxxxxxxx.avi" id="download">高速下载</a>
<script>
var uploader = document.createElement('input');
uploader.type = 'file';
uploader.webkitdirectory = true; download.onclick = function(e) {
uploader.click(); // 弹出授权对话框
e.preventDefault(); // 屏蔽下载对话框
};
</script>

演示

我们将屏蔽超链接的默认行为,将其传递给上传控件,即可召唤出「文件夹授权」对话框了!

同时,为了不让眼亮的人发现对话框上的破绽,我们使用一些第三方的下载方式,例如电驴、迅雷等等,让人们误以为就是这样的。

当然,这只是一个小例子。只要页面做的真实,下载内容引人入胜,用户自然就会中招。

后记

本以为 webkitdirectory 的这个私有属性很快就会放弃,至少是更强的安全提示。不过至少现在也没更新,因此上网时还是要多加留心,看清楚了再做决定。

当然,这篇只是最早的「交互欺骗」探索。事实上,深入挖掘会发现可利用点远不仅此。

如今的浏览器在视觉、音频上的体验已经非常完善,攻击者甚至可以在网页里,高度模拟一个本地应用的交互效果。让用户误以为是浏览器之外的程序弹出的界面,从而进行钓鱼。

参考:http://www.cnblogs.com/index-html/p/dialog-phishing.html

H5危险的文件上传对话框的更多相关文章

  1. H5+JAVA的文件上传,断点续传

    这里只写后端的代码,基本的思想就是,前端将文件分片,然后每次访问上传接口的时候,向后端传入参数:当前为第几块文件,和分片总数 下面直接贴代码吧,一些难懂的我大部分都加上注释了: 上传文件实体类: 看得 ...

  2. nodemailer + express + h5 拖拽文件上传 实现发送邮件

    一.部署 1.部署Express 2.准备一个邮箱并开始SMTP服务 二.服务器端 三.客户端 四.效果:

  3. selenium之 文件上传所有方法整理总结【转】

    本文转自:https://blog.csdn.net/huilan_same/article/details/52439546 文件上传是所有UI自动化测试都要面对的一个头疼问题,今天博主在这里给大家 ...

  4. selenium之 文件上传方法

    文件上传是所有UI自动化测试都要面对的一个头疼问题 首先,我们要区分出上传按钮的种类,大体上可以分为两种,一种是input框,另外一种就比较复杂,通过js.flash等实现,标签非input 我们分别 ...

  5. 富文本编辑器 KindEditor 的基本使用 文件上传 图片上传

    富文本编辑器 KindEditor 富文本编辑器,Rich Text Editor , 简称 RTE , 它提供类似于 Microsoft Word 的编辑功能. 常用的富文本编辑器: KindEdi ...

  6. selenium之 文件上传所有方法整理总结

    本文转载“灰蓝”的原创博客.http://blog.csdn.net/huilan_same/article/details/52439546 文件上传是所有UI自动化测试都要面对的一个头疼问题,今天 ...

  7. web自动化之selenium(三)文件上传

    1.上传标签为input #若上传文件的标签为<input>可以直接定位标签,然后send_keys(文件路径)可以直接上传 2.利用第三方软件Autoit上传 1.下载Autoit:ht ...

  8. Atitit .h5文件上传 v3

    Atitit .h5文件上传 v3 1. 上传原理1 2. V3版新特性1 3. Html1 4. Js2 5. uploadV2.js2 6. upServlet & FileUploadS ...

  9. Atitit .h5文件上传

    Atitit .h5文件上传 1. 上传原理1 2. Html1 3. Js2 4. uploadV2.js2 5. upServlet & FileUploadService {3 6. 注 ...

随机推荐

  1. Effective C++ -----条款40:明智而审慎地使用多重继承

    多重继承比单一继承复杂.它可能导致新的歧义性,以及对virtual继承的需要. virtual继承会增加大小.速度.初始化(及赋值)复杂度等等成本.如果virtual base classes不带任何 ...

  2. Effective C++ -----条款16:成对使用new和delete时要采取相同形式

    如果你在new表达式中使用[],必须在相应的delete表达式中也使用[].如果你在new表达式中不使用[],一定不要在相应的delete表达式中使用[].

  3. 关于C语言中的转义字符

    1.转义字符的分类 1. 1一般转义字符 这种转义字符,虽然在形式上由两个字符组成,但只代表一个字符.常用的一般转义字符为: \a     \n     \t     \v     \b     \r ...

  4. JS点击灯泡变亮(学自W3school)

    JS学习笔记1(学自W3school)        function changeImage()  {  element = document.getElementByIdx_x('myimage' ...

  5. object实现小老鼠交互

    直接使用 <p style="text-align: center; "> <object type="application/x-shockwave- ...

  6. iOS 十六进制和字符串转换

    NSString *dictString = [dict JSONFragment];//组合成的. dictString==={"content":"Sadgfdfg& ...

  7. TCP/IP五层模型

    (2)TCP/IP五层模型的协议   应用层 传输层 网络层 数据链路层 物理层   物理层:中继器.集线器.还有我们通常说的双绞线也工作在物理层 数据链路层:网桥(现已很少使用).以太网交换机(二层 ...

  8. 二、JavaScript语言--JS实践--信息滚动效果制作

    运用JavaScript技术,掌握无缝滚动和歇间性滚动的制作方法. 一.marquee标签实现信息滚动 1 behavior滚动的方式 alternate:表示在两端之间来回滚动 scroll:表示由 ...

  9. .net学习笔记----WebConfig常用配置节点介绍

    一.配置文件入门 .Net提供了一种保存项目配置信息的办法,就是利用配置文件,配置文件的后缀一般是.config.在WinForm程序中配置文件一般是App.config.在Asp.net中一般默认是 ...

  10. 【转载】 Pyqt QStackedWidget堆栈窗体

    转载地址: http://blog.csdn.net/a649518776/article/details/6636578 下面用代码实现上面窗口的设计 # -*- coding: utf-8 -*- ...