一、文件上传
概念:文件上传攻击是指攻击者利用Web应用对上传文件过滤不严的漏洞,将应用程序定义类型范围之外的文件上传到Web服务器,并且此类文件通常为木马,在上传成功后攻击者即可获得当前文件的webshell。
攻击者的目标是取得当前Web服务器的权限,如果通过Web层面展开攻击,那必须将攻击者的木马插入到Web系统中,并在服务器端执行,这个过程就是对Web服务器进行文件注入攻击。
1、上传攻击的原理
假设目标服务器为用PHP语言构建的Web系统,那么针对上传点就要利用PHP木马,并且要求在木马服务器以后缀名为.php进行保存,因此上传木马的过程就是在Web系统中新增一个页面,当木马上传成功后,攻击者就可以远程访问这个木马文件,也就相当于浏览一个页面,只不过这个页面就是木马,具备读取、修改文件内容、连接数据库等功能。 上传漏洞存在的前提是:存在上传点且上传点用户可以独立控制上传内容,同时上传文件可被顺利解析。
2、上传的标准业务流程
整个过程可分为三大步骤:
- 客户端上传功能
- 中间文件上传功能
接收客户端提交的HTML表单 将表单内容存储为临时文件 根据安全规范,将临时文件保存为正式文件 - 服务器存储及调用
客户端上传表单基本通过HTML格式中的 < from > 实现 from action定义了表单上传目标界面为upload_file.php,采用提交的方式由method定义,值为post,定义提交的lexicon为multipart/from-data(如果不指定由浏览器自行判断)
<form action="upload_file.php" method="post" enctype="multipart/form-data">
3、上传攻击的条件
攻击者利用上传功能的目的是将Web木马上传至服务器并能成功执行,也难辞,攻击者成功实施文件上传攻击并获得服务器Webshell的前提条件如下所示:
- 目标网站具有上传功能
- 上传的目标文件能够被Web服务器解析执行
- 知道文件上传到服务器后的存放路径和文件名称
- 目标文件可被用户访问
二、上传检测绕过技术
1、客户端JavaScript检测及绕过
1.1 防护思路
如果用户上传文件名非法,则不允许通过,如果合法则正常执行上传流程。简称JS防护。 在网站部署JavaScript脚本,Js脚本会对用户表单提交的数据进行检查,如果发现非法后缀,如.php,.jsp等,则直接终止上传。
1.2 绕过方式
- 浏览器可以通过禁用JS方式,禁止防护脚本执行,导致防护功能直接失效。
- 如果这种防护手段在HTTP数据包发出之前执行完毕,那攻击者可使用Web代理类攻击,抓取含有上传表单的HTTP数据包,并在包中修改为预想的后缀,如.php。
- 直接删除代码里onsubmit事件中关于上传时验证文件的相关代码。
onsubmit事件:将用户上传的后缀名提交到lastname函数中进行后缀名匹配测试。 - 伪造后缀绕过JS检查
采用JS进行过滤的防护方式的初衷时减少服务器的性能消耗,同时实现防护功能。 缺陷是:服务器要相信用户浏览器提价到西悉尼正确,由于检测是在客户端进行的,所以会存在很大的安全隐患,如用户随意修改本地信息及配置,当值防护手段失效,且绕过手段较为成熟。
2、服务器端MIME检测及绕过
2.1 防护思路
在HTTP协议中,会利用Content-Type表示本次上传的内容类型,如图片格式文件Content-Type的值为image/jpg、image/gif、image/png。服务器接收到HTTP包后,会先判断Content-Type是否合法,默认情况下,Content-Type由浏览器自动生成,并且在HTTP包的文件头进行传输。
2.2 绕过方式
HTTP 抓包后修改Content-type的值,可利用BurpSuite进行抓包。
总体来说MIME在服务器端检测,比JS在客户端检测效果略好一点,但由于Content-Tpye类型依然由客户端浏览器生成,因此实际上MIME还是处于用户可控状态(修改文件头,修改Content-Type等均可),因此MIME的防护效果依然较差。
3、服务端文件扩展名检测及绕过
根据以上描述,只能在服务器端进行全面检查,且不能信赖由服务器浏览器生成并提交的数据,有效的防护思路为:
- 当服务器接收到上传信息后,校验文件名是否合法。
- 完全不信来用户所上次文件的后缀名,在用户上传文件之后,重新给文件添加用户名。
3.1 防护思路
主要通过文件后缀名黑/白名单过滤,服务器采用针对文件名的黑/白名单检测机制。 上传时,在转存过程中利用预先设定的会缀名保存文件来避免非法后缀名的问题。 但从防护效果来看,白名单效果好于黑名单,但在实际应用中,白名单由于防护过严,常常无法满足实际业务需要。
总结,推荐以下几种手段:
- 文件后缀名重命名
- 白名单过滤
- 黑名单过滤
$deny_ext=array('.php');
$file_ext=strrchr($_FILES['upfile']['name'],'.');
if(!in_array($file_ext,$deny_ext)){
......
}
3.2 绕过方式
尝试未被过滤的文件名,利用截断漏洞等实现木马上传。 绕过思路为:构造非限制条件,以欺骗服务器,从而达到绕过的行为。
针对黑名单:
- 多重测试过滤文件名
如:直接上传php文件,会报类型错误,尝试用php5后缀。 - 判断是否存在大小写绕过
中间件会区分文件大小写,但操作系统并不会区分后缀名大小写。 - 特殊文件名构造(Windows下)
可用Burpsuite代理劫持HTTP包,并手动在相关字段出添加“_”下划线,由于Windows不识别上述后缀机制,会自动去掉“ _ ”、“ . ”等符号,从而使攻击者可绕过黑名单防护规则。 - %00截断
当C语言在执行过程中遇到%00,会被当做终止符,因此程序会自动截断后续信息。如:shell.php .jpg(注意.jpg前有空格)。
针对白名单:
- 特殊文件构造(参考黑名单防护)
- 0x00截断(参考黑名单防护)
4、服务器端文件内容检测及绕过
4.1 防护思路
- 通过检测上传文件的文件头判断当前文件格式
读取文件开题部分的数个字节,判断文件头与文件类型是否匹配,通常情况下,通过判断前10个字节基本上就能判断出一个文件的真实类型。 - 调用API或函数对文件进行加载测试,常见的使图像二次渲染
关键函数imagrcreatefromjpeg从jpeg生成新的图片,这也就导致在二次渲染的过程中,插入的木马无法被渲染成像素,在渲染过程中被丢弃,导致木马执行失效,针对图像二次渲染会给服务器带来额外的性能开销。 - 检测上传文件是否为图像文件内容
可利用php中的getimagesize()函数实现,获取目标图片的高度宽度像素值,再与本地获取到的图片信息进行比对,如果相同则保存。
4.2 绕过方式
- 文件头检测
修改文件头,对前二十字节进行替换,后面再插入一句话木马,即可实现对文件内容检测的绕过。 - 文件二次渲染(极难)
基于数据二义性,即让数据即是图像数据也包含一句话木马 对文件加载器进行溢出攻击
三、上传流程安全防护总结
攻击者利用上传漏洞的主要目标是:
- 上传木马
- 让木马按照Web格式进行解析
在防护手段可用的思路有:
- 限制高位扩展名上传
利用黑名单确定后缀名是否合法 根据应用特点重新对上传文件进行后缀名重命名 - 显示高危文件内容出现
利用内容检索来检测是否存在非正常内容 确认图片格式与上传文件内容是否对应 在图像加载时重新渲染,避免非图像内容出现
|