????????今天来聊一聊web常见十大漏洞之一——文件上传,这个还是有点面熟的毕竟打过了几次交道,还是有我不熟悉的地方的。
=========================================================================
参考博客:
太厉害了,终于有人能把文件上传漏洞讲的明明白白了
文件上传漏洞
一句话木马
二次渲染
条件竞争
=========================================================================
目录
什么是文件上传漏洞
什么是webshell
一句话木马
入侵条件
?产生文件上传漏洞的原因
文件上传漏洞的攻击与防御方式?
1.前端限制?
2.检查扩展名
1.黑名单策略
2.白名单策略
3.检查Content-Type
4.文件头检查文件
5.限制Web Server对特定类型文件的行为
?6.文件系统00截断
7.windows NTFS文件系统特性绕过
8.二次渲染绕过
9.条件竞争
10.其它方式—绕过
靶场及工具
=========================================================================
什么是文件上传漏洞
????????文件上传漏洞是指由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致的用户可以越过其本身权限向服务器上上传可执行的动态脚本文件。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。“文件上传”本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。如果服务器的处理逻辑做的不够安全,则会导致严重的后果。
什么是webshell
????????WebShell就是以asp、php、jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称之为一种网页后门。攻击者在入侵了一个网站后,通常会将这些asp或php后门文件与网站服务器web目录下正常的网页文件混在一起,然后使用浏览器来访问这些后门,得到一个命令执行环境,以达到控制网站服务器的目的(可以上传下载或者修改文件,操作数据库,执行任意命令等)。 WebShell后门隐蔽较性高,可以轻松穿越防火墙,访问WebShell时不会留下系统日志,只会在网站的web日志中留下一些数据提交记录
一句话木马
常用的webshell就是一句话木马,结合中国菜刀或者蚁剑等工具可以很高效快捷的获得网站shell。
php的一句话木马: <?php @eval($_POST['pass']);?>
asp的一句话是: <%eval request ("pass")%>
aspx的一句话是: <%@ Page Language="Jscript"%> <%eval(Request.Item["pass"],"unsafe");%>
入侵条件
其中,只要攻击者满足三个条件,就能实现成功入侵:
- 木马上传成功,未被杀
- 知道木马的路径在哪?
- 上传的木马能正常运行
?产生文件上传漏洞的原因
原因:
- 对于上传文件的后缀名(扩展名)没有做较为严格的限制
- 对于上传文件的MIMETYPE(用于描述文件的类型的一种表述方法) 没有做检查
- 权限上没有对于上传的文件目录设置不可执行权限,(尤其是对于shebang类型的文件)
- 对于web server对于上传文件或者指定目录的行为没有做限制
文件上传漏洞的攻击与防御方式?
1.前端限制?
<li id="show_code">
<h3>代码</h3>
<pre>
<code class="line-numbers language-javascript">function checkFile() {
var file = document.getElementsByName('upload_file')[0].value;
if (file == null || file == "") {
alert("请选择要上传的文件!");
return false;
}
//定义允许上传的文件类型
var allow_ext = ".jpg|.png|.gif";
//提取上传文件的类型
var ext_name = file.substring(file.lastIndexOf("."));
//判断上传文件类型是否允许上传
if (allow_ext.indexOf(ext_name + "|") == -1) {
var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
alert(errMsg);
return false;
}
}
</code>
</pre>
</li>
原理?
=========================================================================
在表单中使用onsumbit=checkFile()调用js函数来检查上传文件的扩展名。当用户在客户端选择文件点击上传的时候,客户端还没有向服务器发送任何消息,就对本地文件进行检测来判断是否是可以上传的类型,这种方式称为前台脚本检测扩展名。
?绕过方法
=========================================================================
这种限制很简单,通过浏览器F12很简单的修改文件后缀名就可以完成绕过检查,或者是讲木马修改后缀名后上传,通过改包工具修改上传。如果是JS脚本检测,在本地浏览器客户端禁用JS即可。可使用火狐浏览器的NoScript插件、IE中禁用掉JS等方式实现绕过。
2.检查扩展名
就是在文件被上传到服务端的时候,对于文件名的扩展名进行检查,如果不合法,则拒绝这次上传 在检查扩展名是否合法的时候,有两种策略:
1.黑名单策略
文件扩展名在黑名单中的为不合法
2.白名单策略
文件扩展名不在白名单中的均为不合法
原理 当浏览器将文件提交到服务器端的时候,服务器端会根据设定的黑白名单对浏览器提交上来的文件扩展名进行检测,如果上传的文件扩展名不符合黑白名单的限制,则不予上传,否则上传成功。
3.检查Content-Type
原理
HTTP协议规定了上传资源的时候在Header中加上一项文件的MIMETYPE,来识别文件类型,这个动作是由浏览器完成的,服务端可以检查此类型不过这仍然是不安全的,因为HTTP header可以被发出者或者中间人任意的修改。
??绕过方法 使用各种各样的工具(如burpsuite)强行篡改Header就可以,将Content-Type: application/php改为其他web程序允许的类型。
4.文件头检查文件
原理
利用的是每一个特定类型的文件都会有不太一样的开头或者标志位。
绕过方法
给上传脚本加上相应的幻数头字节就可以,php引擎会将 <?之前的内容当作html文本,不解释而跳过之,后面的代码仍然能够得到执行比如下面: (一般不限制图片文件格式的时候使用GIF的头比较方便,因为全都是文本可打印字符。)
5.限制Web Server对特定类型文件的行为
原理
导致文件上传漏洞的根本原因在于服务把用户上传的本应是数据的内容当作了代码,一般而言:用户上传的内容都会被存储到特定的一个文件夹下,比如我们很多人习惯于放在 ./upload/ 下面要防止数据被当作代码执行,我们可以限制web server对于特定文件夹的行为。
大多数服务端软件都可以支持用户对于特定类型文件的行为的自定义,以Apache为例:
?在默认情况下,对与 .php文件Apache会当作代码来执行,对于 html,css,js文件,则会直接由HTTP Response交给客户端程序对于一些资源文件,比如txt,doc,rar等等,则也会以文件下载的方式传送的客户端。我们希望用户上传的东西仅仅当作资源和数据而不能当作代码。因此Apache使用服务器程序的接口来进行限制利用 .htaccess 文件机制来对web server行为进行限制。
前提条件:
- ?配置上允许.htaccess生效
- Apache开启rewrite模块
- .apache配置文件为AllowOverride All(默认为None)
禁止脚本执行有多种方式可以实现,而且分别有不同的效果:
- 指定特定扩展名的文件的处理方式,原理是指定Response的Content-Type可以加上如下几行
AddType text/plain .pl .py .php
这种情况下,以上几种脚本文件会被当作纯文本来显示出来,你也可以换成其他的Content-Type -
如果要完全禁止特定扩展名的文件被访问,用下面的几行 Options -ExecCGI
AddHandler cgi-script .php .pl .py .jsp .asp .htm .shtml .sh .cgi识别
在这种情况下,以上几种类型的文件被访问的时候,会返回403 Forbidden的错误 -
强制web服务器对于特定文件类型的处理,与第一条不同的是, 下面的方法直接强行让apache将文件识别为你指定的类型,而第一种是让浏览器符合上面正则的全部被认为是纯文本,也可以继续往里面加入其他类型。 <FilesMatch "\.(php|pl|py|jsp|asp|htm|shtml|sh|cgi)$">
ForceType text/plain
</FilesMatch>
- 只允许访问特定类型的文件.使得该文件夹里面只有图片扩展名的文件才可以被访问,其他类型都是拒绝访问(白名单策略)。
<Files ^(*.jpeg|*.jpg|*.png|*.gif)>
order deny,allow
deny from all
</Files>
绕过方法
可以通过 move_uploaded_file 函数把自己写的.htaccess 文件上传,覆盖掉服务器上的文件,来定义文件类型和执行权限如果做到了这一点,将获得相当大的权限。
补充知识htaccess:
.htaccess文件(或者"分布式配置文件"),全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。概述来说,htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
?6.文件系统00截断
这个还没有见过详细的题目,现在了解一下,写一下其他大佬的看法
7.windows NTFS文件系统特性绕过
这个是真的难懂,等我什么时候明白了在进行补充😑?
8.二次渲染绕过
原理?
?在我们上传文件后,网站会对图片进行二次处理(格式、尺寸要求等),服务器会把里面的内容进行替换更新,处理完成后,根据我们原有的图片生成一个新的图片并放到网站对应的标签进行显示。?我们上传的文件名称会被修改,并且文件末尾段一些冗余的信息(一句话木马)会被删除。
绕过:?
- 很明显,我们只需要将我们需要写入的东西塞在图片中间(虽然会使图片损坏,但是我们又不需要图片。。),用winhex或者是010editor等在文件内进行修改即可。
- 可以配合条件竞争:??这里二次渲染的逻辑存在漏洞,先将文件上传,之后再判断,符合就保存,不符合删除,可利用条件竞争来进行爆破上传
9.条件竞争
原理?
条件竞争漏洞是一种服务器端的漏洞,由于服务器端在处理不同用户的请求时是并发进行的,因此,如果并发处理不当或相关操作逻辑顺序设计的不合理时,将会导致此类问题的发生。
??上传文件源代码里没有校验上传的文件,文件直接上传,上传成功后才进行判断:如果文件格式符合要求,则重命名,如果文件格式不符合要求,将文件删除。 ??由于服务器并发处理(同时)多个请求,假如a用户上传了木马文件,由于代码执行需要时间,在此过程中b用户访问了a用户上传的文件,会有以下三种情况: ??1.访问时间点在上传成功之前,没有此文件。 ??2.访问时间点在刚上传成功但还没有进行判断,该文件存在。 ??3.访问时间点在判断之后,文件被删除,没有此文件。
?示例:
$is_upload = false;
$msg = null; //判断文件上传操作
if(isset($_POST['submit'])){ //判断是否接收到这个文件
$ext_arr = array('jpg','png','gif'); //声明一个数组,数组里面有3条数据,为:'jpg','png','gif'
$file_name = $_FILES['upload_file']['name']; //获取图片的名字
$temp_file = $_FILES['upload_file']['tmp_name']; //获取图片的临时存储路径
$file_ext = substr($file_name,strrpos($file_name,".")+1); //通过文件名截取图片后缀
$upload_file = UPLOAD_PATH . '/' . $file_name; //构造图片的上传路径,这里暂时重构图片后缀名。
if(move_uploaded_file($temp_file, $upload_file)){ //这里对文件进行了转存
if(in_array($file_ext,$ext_arr)){ //这里使用截取到的后缀名和数组里面的后缀名进行对比
$img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext; //如果存在,就对文件名进行重构
rename($upload_file, $img_path); //把上面的文件名进行重命名
$is_upload = true;
}else{
$msg = "只允许上传.jpg|.png|.gif类型文件!"; //否则返回"只允许上传.jpg|.png|.gif类型文件!"数据。
unlink($upload_file);// 并删除这个文件
}
}else{
$msg = '上传出错!';
}
}
?代码处理流程:声明一个数组,保存着允许上传的文件类型-->获取文件名和文件临时存储路径-->截取文件名-->构造文件上传后的存储路径-->对文件进行转存-->比对白名单,如果存在就对文件进行重命名-->否则就删除文件。 通过上面代码我们发现: ??服务器先通过move_uploaded_file函数把文件保存了,然后再去判断后缀名是否合法,合法就重命名,如果不合法再删除。重点在于,在多线程情况下,就有可能出现还没处理完,我们就访问了原文件,这样就会导致防护被绕过。 ??我们上传一个文件上去,后端会检验上传文件是否和要求的文件是否一致。如果不能达到要求就会删除文件,如果达成要求就会保留,那么当我们上传文件上去的时候,检测是否到达要求需要一定的时间,这个时间可长可短,但是我们确确实实在某一刻文件已经上传到了指定地址,并且访问到这个文件。这时候就会造成条件竞争。 一个可以一直发requests的py文件
import requests
url="http://119.23.73.3:5006/web2/uploads/b106f91010a3789acab1f27a00d67570052a7921/1.php"//网页链接
while 1:
print (requests.get(url).text)
10.其它方式—绕过
原理
部分程序员的思维不严谨,并使用逻辑不完善的上传文件合法性检测手段,导致可以找到方式绕过其检测方式。
绕过方法
- 后缀名大小写绕过 用于只将小写的脚本后缀名(如php)过滤掉的场合; 例如:将Burpsuite截获的数据包中的文件名【evil.php】改为【evil.Php】
- 双写后缀名绕过 用于只将文件后缀名过滤掉的场合,例如"php"字符串过滤的; 例如:上传时将Burpsuite截获的数据包中文件名【evil.php】改为【evil.pphphp】,那么过滤了第一个"php"字符串"后,开头的’p’和结尾的’hp’就组合又形成了【php】。
- 特殊后缀名绕过 用于检测文件合法性的脚本有问题的场合; 例如:将Burpsuite截获的数据包中【evil.php】名字改为【evil.php6】,或加个空格改为【evil.php 】等。
?
靶场及工具
upload-labs和sql-labs环境搭建?其中upload-labs是文件上传的靶场
BUUCTF和攻防世界这里面也有关于文件上传的题目
工具主要就是burp,中国蚁剑或菜刀,还有就是浏览器最好是火狐,最后最好的工具是是你那充满智慧的大脑😎
|