H5危险的文件上传对话框

文件对话框

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

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

<input type="file" webkitdirectory />

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

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

下载对话框

H5危险的文件上传对话框

上传对话框

H5危险的文件上传对话框

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

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

选择即授权

然而,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>

H5危险的文件上传对话框

演示

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

优化上传

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

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

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

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

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

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

续点上传

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

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

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

H5危险的文件上传对话框

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

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

H5危险的文件上传对话框

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

将数据存放在 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>

演示

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

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

H5危险的文件上传对话框

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

后记

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

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

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

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

更多相关文章
  • EXtJS4官方示例解读--文件上传file-upload.html、file-upload.js、file-upload.php
     Tag:Ext.form.field.File.ExtJS文件上传.PHP文件上传.move_uploaded_file文件所在目录:ext-4.0.1/examples/form/相关文件:file-upload.html.file-upload.js.file-upload.php先看看界面吧 ...
  • 一个Ext2+SWFUpload做的图片上传对话框
    一个Ext2+SWFUpload做的图片上传对话框的例程我们先看看对话框的布局:布局就是在一个窗口里内嵌一个表格控件,窗口的底部工具条带一个进度条,表格的顶部工具条带几个操作按钮和一个下来选择框,底部工具条作为一个信息显示区域显示文件的总数和总的上传大小.我们来分析一下uploadDialog.js ...
  • PHP服务器文件管理器开发小结十:使用jQuery和iframe实现AJAX文件上传
    上一节讨论了文件下载,这一节继续讨论文件上传.众所周知,前端上传文件比较简单的办法就是使用文件控件<input type="file"/>.然而,如果我们需要上传过程是AJAX的,亦即上传过程不刷新页面,仅反馈需要的信息,那就需要更加精巧的设计了.首先是上传文件图片链 ...
  • 找了很多的资料,学到了不少有用的东西,最简单的实现就是使用FileUpload控件.using System;namespace UpFile { /// /// upfile 的摘要说明./// public class upfile{  private string path = null;  ...
  • 上传图片有危险代码禁止上传的问题admin/include/upfilesave.asp找到以下代码删    '======================增加检查文件内容是否合法===================================    call CheckFileContent ...
  •        如果当前用户通过验证,就可以通过SL上传附件了,因为用户上传的附件要进行实时统计,以即时更新已上传附件的总和大小,来防止用户上传过量的附件),所以我在打开文件对话框事件中加入了到已上传附件大小的统计以便进行控件:///<summary>/// 选择文件对话框事件///< ...
  • 一.开发环境搭建 创建一个FileUploadAndDownLoad项目,加入Apache的commons-fileupload文件上传组件的相关Jar包,如下图所示: 二.实现文件上传 2.1.文件上传页面和消息提示页面 upload.jsp页面的代码如下: 1<%@ page langua ...
  • springmvc学习笔记--支持文件上传和阿里云OSSAPI简介
    前言:Web开发中图片上传的功能很常见, 本篇博客来讲述下springmvc如何实现图片上传的功能. 主要讲述依赖包引入, 配置项, 本地存储和云存储方案(阿里云的OSS服务). 铺垫:文件上传是很基础的东西, 没有高深的理论背景. 因此这边不再具体阐述和"科普", ^_^.对于 ...
一周排行
  • 引入unittest框架get请求#coding: utf-8 import unittest import requests import json class TestGet(unittest.TestCase) ...
  • 大数据虚拟化实例:Tarball方式部署Hadoop发行版
    在博文<灵活管理Hadoop各发行版的运维利器>中,我们介绍了vSphere ...
  • ITU-R BT.601 建议书里面记载了五种色彩变换式,分别是:1. 模拟 RGB 讯号转为模拟 Y, (B-Y), (R-Y)2. 模拟 (B-Y), (R-Y) 转为模拟 Cb, Cr3. 模拟 YCbCr 数 ...
  • 源码与jar包下载(将rar改成jar,直接放在WEB_INF\lib目录中即可)    众所周知,Strut 2的Action类通过属性可以获得所有相关的值,如请求参数.Action配置参数.向其他Action传递 ...
  • 幸福列车 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others) Total Submission ...
  • 可以把整个网络(一个自治系统AS)看成一个王国,这个王国可以分成几个 区(area),现在我们来看看区域内的某一个人(你所在的机器root)是怎样得到一张 世界地图(routing table)的.首先,你得跟你周围 ...
  • 汶川地震.生死转换于顷刻.穷人与富人同行,少年与老人携手.恩人与仇人同去,平民与官员共趋.抹平了恩怨情仇,埋葬了利禄功名.当生命邂逅死亡,顿感生命之脆弱.情亲弥珍,更使人明白:得到别得意忘形,失去别怨天尢人:顺时要善 ...
  • AM User-bind命令完成IP.MAC地址和端口之间的绑定配置『配置环境参数』1.      PC1的IP地址为10.1.1.2/24,MAC地址为000f-1fb8-fcb82.      PC1连接到交换机 ...
  • netapp学习十三---Snapshot实验下
    上篇讲述了snapshot的知识,<netapp学习(十三)---Snapshot基 ...
  • 经过一段时间狂热的PHP编程,对WINDOWS平台下PHP的配置可算是深有感触,一开始我用的是一键安装的傻瓜包,但是考虑傻瓜包的安装版本已经落后,在真正手动配置PHP环境时遇到许多问题,在查阅了许多资料和尝试后,终于 ...