文件对话框

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

到了 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. 【关于服务器端SQL Server 2008的设置】 使其他客户端机可通过ODBC数据源可访问

    服务器系统:Server 2003 数据库:SQL Server 2005 服务器配置:开启服务:server.workstation(这两个服务对于提供局域网共享有很大作用) 关闭防火墙 开启gue ...

  2. 如何更改UITextField 的placeholder 的字体颜色

    storyboard 中这样设置 具体步骤: 1.在User Defined Runtime Attributes中添加一个Key. 2.输入Key Path(这里我们输入_placeholderLa ...

  3. maven编译时如何忽略单元测试

    共有两种解决办法 1.通过在命令行设置:-Dmaven.test.skip=true 如:mvn clean install tomcat:run -Dmaven.test.skip=true 2.通 ...

  4. Spetember 5th 2016 Week 37th Monday

    No matter how far you may fly, never forget where you come from. 无论你能飞多远,都别忘了你来自何方. Stay true to you ...

  5. limits.h头文件

    CHAR,SHRT,INT ,LLONG加_MAX后缀表示最大,加_MIN后缀表示最小,加U前缀表示无符号 UCHAR_MIN ,UCHAR_MAX sizeof()计算数所用的空间 #include ...

  6. volatile和const

    volatile可理解为“编译器警告指示字” volatile用于告诉编译器必须每次去内存中取变量值 volatile主要修饰可能被多个线程访问的变量 volatile也可以修饰可能被未知因数更改的变 ...

  7. printf 与c的基本类型之间的关系

    型 書式 注意事項 ssize_t %zd size_t %zu intmax_t %jd uintmax_t %ju ptrdiff_t %t signed char %hhd unsigned c ...

  8. Android四种LaunchMode

    singleTop 的Activity和standard的几乎一样, 把singleTop和standard归为一类启动模式,这种模式不会引起任务栈的变更 singleTop和standard唯一的区 ...

  9. NYOJ之ASCII码排序

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAsAAAAIFCAIAAABTaNy/AAAgAElEQVR4nO3dO1LjzMIG4H8T5CyEdF

  10. Java之POJO

    转: POJO    一:什么是POJOPOJO的名称有多种,pure old java object .plain ordinary java object 等.按照Martin Fowler的解释 ...