在网络上进行分享的时候有一个操作肯定是无法避免的,那就是“文件上传”。我们经常发微博、发微信朋友圈等等,发送过程就用到了文件上传中的图片上传功能。将本地图片、视频、音频等文件上传到程序服务器上,再供其他用户浏览或下载。这就造成网站每天都会有大量数据的流入,海量数据带来用户的同时,也带来了一些安全问题。
而网站的开发者在网站存储空间中,经常会发现各类 xml、html、apk 等垃圾文件,这些文件或是注入广告,或者散播涉黄视频等资源,严重影响网站业务的运营。这些垃圾文件都是通过文件上传功能上传到网站存储空间的。如果网站上传程序没有对用户提交的数据进行检验或严格过滤,服务器就很容易被上传修改过的数据。
文件上传是数据安全中最容易被利用的一个环节,要减少恶意文件上传打扰,我们首先需要弄清楚它的原理。
文件类型和文件扩展名的作用
计算机的数据内容一般存放在例如硬盘等等这类存储硬件上。由于硬盘本身空间巨大,就像一个大仓库,为了方便数据存储以及管理,我们创造了文件的概念,也就是操作系统用文件的格式来封装存储于空间中的一段数据。
然而随着互联网的发展,从最开始的纯文本文件,发展到今天各个类型的多媒体文件,如图像、音频、视频等等,我们存储的文件越来越多,种类也越来越丰富,文件体积也越来越大,如果不对这些文件进行区分,查找起来极为麻烦。所以文件格式(或文件类型)也就应运而生。每一类文件,都能以一种或多种文件格式保存在电脑存储中。每一种文件格式通常会有一种或多种扩展名可以用来识别,扩展名可以帮助用户和应用程序识别的文件格式。
例如,有一个文件被命名为 README.txt ,.txt 就是这个文件的扩展名,而 txt 适用于纯文本文件。这类文件可能是一份文件内容为纯文本的说明文档。
除此之外,扩展名还可以帮助操作系统判断以何种方式读取文件。例如 score.doc 这个文件,doc 文件可以用 Word 打开,那么 Windows 用户在双击一个 .doc 文件后, Windows 系统会根据文件扩展名“doc”,在自维护数据库表中查找“可以打开这个扩展名文件的程序”,如 Word 程序,之后系统会自动启动 Word 程序,并通知 Word 去加载这个文件。
从这里可以看出,Windows 系统在打开一个文件的时候,只需要文件名中的扩展名就可以找到对应的程序。所以,改变一个文件的扩展名,也会更改这个文件在系统中的默认打开方式。而且如果文件本身内容不符合程序对文件内容格式的预期,则打开会出错,或者出现意料之外的结果。
浏览器如何识别打开文件
因为互联网工具功能的逐渐完善,相比在本地打开文件,使用浏览器打开文件的几率也逐渐增多了。那么,浏览器是如何确认访问的资源是什么文件类型的呢?其实是通过响应头来判断的。
当用户输入 URL 后,资源所在服务器会进行响应,并给出 Content-Type 响应头,其值就是文件对应的类型(MIME 类型)。如果浏览器支持该格式,则浏览器会尝试渲染显示对应文件。
与 Windows 系统中相比,浏览器通常使用 MIME 类型,而不是文件扩展名来处理 URL。因此在响应头中添加正确的 MIME 类型就显得非常重要,如果配置不正确,浏览器可能会曲解文件内容,下载的文件也会被错误处理,进而影响网站的正常运作。
恶意文件是如何上传的
最开始我们提到一些恶意资源会通过上传文件的方式上传,这些恶意资源的文件格式明明是正常格式,但是打开后却会出现跳转网页等特殊访问效果。这是怎么做到的呢?
其实原理很简单,就是通过修改 MIME 类型作出的操作。比如上图的 test.jpg 图片。虽然 URL 链接的资源后缀是 jpg,但是真实的资源的文件类型是 text/html ,也就是网页类型。
而这种网页类型的文件支持 JS 代码地嵌入,并可以通过这些代码让打开文件的用户跳转到指定网站。尽管这个现象看起来和 DNS 劫持有些相似,但是其实是不同的。关于 DNS 劫持的问题,大家可以查看【白话科普】聊聊 DNS 的那些小知识》了解更多。
如此看来这类恶意文件是通过修改文件 MIME 来达到效果的,那么我们是否可以通过限制 MIME 等方式来减少此类恶意文件的上传与访问呢?有的,方法还有很多种,我们接下来以又拍云存储为例一一讲解。
防止恶意文件上传手段
身份溯源 - TOKEN 上传
使用 TOKEN 上传时 TOKEN 鉴权会使用终端上传文件的标识信息来计算 TOKEN,控制上传有效期,固定上传目录或者上传后缀。与一般的所有用户使用服务器上一个操作员信息进行鉴权上传的方式不同,云存储提供的 TOKEN 鉴权可以实现更加细粒度的权限控制。
开启 TOKEN 功能后我们可以为每个用户分配一个独立标识,这样用户上传的文件会按照标识单独建立目录进行存储。
X-Upyun-Uri-Prefix = /服务名/client_37ascii // 用户标识前缀,对应存储上的一个目录,如 /client_37ascii/
X-Upyun-Uri-Postfix = .jpg // 限定上传文件后缀
通过这种方式上传的文件,可以通过标识来快速进行身份回溯,找到是谁上传了大量恶意文件,并进行处理。
文件证明 - Content-Type
第二种方式是从文件保存名方面进行限制。我们可以对上传文件的 MIME 类型进行限制,例如限制上传的图片类为型 Content-Type 类型,这样即便上传了恶意文件,当浏览器访问的时候,浏览器会强制按照图片格式进行解析,非图片资源则会解析失败,从而限制恶意文件的访问。
云存储的 REST API 与 FORM API 都支持强制设置 Content-Type 类型。其中 FORM API 更是支持多种限制方法:
具体的使用方法我们以 Java SDK Form API 上传为示例:
//初始化uploader
FormUploader uploader = new FormUploader(BUCKET_NAME, OPERATOR_NAME, OPERATOR_PWD);
//初始化 policy 参数组 Map
final Map<String, Object> paramsMap = new HashMap<String, Object>();
//添加 SAVE_KEY 参数
paramsMap.put(Params.SAVE_KEY, savePath);
//添加文件上传限制
paramsMap.put(Params.CONTENT_TYPE, "image/jpg"); //强制文件MIME类型
paramsMap.put(Params.ALLOW_FILE_TYPE, "jpg,jpeg,png"); //强制文件扩展名
paramsMap.put(Params.CONTENT_LENGTH_RANGE, "102400,1024000"); //强制文件大小,单位字节
//执行上传
uploader.upload(paramsMap, file);
只要在上传设置中设置了以上的任意参数,如果有上传请求,云存储就会侦测上传文件内容,再用判断值跟上传指定值进行匹配,匹配成功则允许上传,匹配失败则返回 403 状态码。
拒绝访问 - 边缘规则
上面说到的两个方法都是在上传的时候排除恶意文件,那已经上传了的文件要怎么办呢?
针对已经上传的伪装成图片的恶意资源,我们可以边缘规则来识别。通过为每一条图片链接增加一个隐式的云处理图片参数让恶意文件无法正常显示,出现 405 错误反馈。
除去图片限制外,如果在图片空间内发现了大量恶意 APK,我们也可以通过边缘规则来快速禁止对它们的访问。
热门链接 - 统计分析
如果有很多文件,而且文件类型本身很多,排查的时间很长,需要马上检查出问题。也可以看一下又拍云的日志分析功能。这个功能每天都会统计每个服务下的访问域名访问情况,可以根据热门文件、热门客户端、热门引用文件、资源状态码、文件大小、热门 IP 等维度来统计 TOP 1000 的分析数据。
统计分析可以帮助您综合盘点服务情况。如果发现某一条资源、某一个 IP 有异常高频率的访问,可以及时定位进行排查。
信息安全 - 内容识别
如果您的网站流量很大,而通过上面的方式进行限制不太合适的话。您还可以看一下又拍云联合梵为公司的天清和天测两款内容识别工具。
这两款工具以 AI 智能安全检测为核心,通过机器学习的分类器算法,“智能”地对图片、视频等信息做审核,逐渐将“鉴黄师”从职业变成一种“算法”和“模型”。解放人力,并且大大提升处理效率,帮助企业减少投入成本。为客户提供内容安全预警、 内容安全数据以及内容安全⻛评等服务,提供完善的网络信息内容安全解决方案,
目前已经为数家互联网企业以及政府部门提供了低延迟、高精度、可视化的整套从引擎识别到人工审核一站式内容安全服务。