【upload-labs】文件上传漏洞原理及操作详解
什么是文件上传漏洞?
文件上传漏洞是指由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致的用户可以越过其本身权限向服务器上传可执行的动态脚本文件。这里上传的文件可以是木马、病毒、恶意脚本或者WebShell等。这种攻击方式最为直接有效的,“文件上传”本身没有问题,有问题的是文件上传后,服务器怎么处理,解释文件。如果服务器的处理逻辑做的不够安全,则会导致严重的后果。
webshell?
WebShell就是以asp、php、jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称为一种网页后门。攻击者在入侵了一个网站后,通常会将这些asp或php后门文件与网站服务器web目录下正常的网页文件混在一起,然后使用浏览器来访问这些后门,得到一个命令执行环境,以达到控制网站服务器的目的(可以上传下载或者修改文件,操作数据库,执行任意命令等)。
文件上传漏洞产生的原因
- 对于上传文件的后缀名(扩展名)没有做较为严格的限制
- 对于上传文件的MIMETYPE(content-type)没有做检查
- 在权限上,没有对文件上传的文件目录设置不可执行权限
- 服务器对于上传文件或者指定目录的行为没有做限制
在web中进行文件上传的原理是通过将表单设为multipart/from-data,同时加入文件域,而后通过HTTP协议将文件的内容发送到服务器,服务器端读取这个分段(multipart)的数据信息,并将其中的文件内容提取出来并保存的。
通常,在进行文件保存的时候,服务器端会读取文件的原始文件名,并从这个原始文件名中得出文件的扩展名,而后随机为文件起一个文件名(为了防止重复),并且加上原始文件的扩展名来保存到服务器上。
危害
- 上传web木马文件,控制web服务器文件、远程命令执行等。
- 上传系统病毒、木马文件进行挖矿、僵尸网络。
- 上传系统溢出程序进行权限提升。
- 修改web页面实现钓鱼、挂马、暗链等操作。
- 内网渗透。
- 在权限得到提升的情况下、想做什么就做什么。
常见防御姿势
- 前端JS验证
- MIME类型验证
- 黑名单/白名单
- 检查文件内容
- 禁止本地文件包含漏洞
- 使用安全的web服务(apache(a.php.xxx)、nginx(/test.png/xxx.php)、IIS解析漏洞(1.php;jpg))
绕过姿势
- 前端JS绕过
- MIME类型绕过
- 后缀名大小写绕过/php4、php5
- 00截断
- 覆盖.htaccess
- Windows文件流特性绕过
- 双写文件名绕过
- 条件竞争
【pass-01】JS检测绕过
上传一个冰蝎大马试试:
结果有弹窗提示拦截,猜测可能是前端js进行了拦截。
查看网页源码:
上传文件点击提交时,会执行checkFile()函数
这是checkFile()函数:
可以看出,该函数使用了白名单过滤只允许上传后缀为.jpg、.png、.gif的文件。
由于是前端限制,我们直接修改代码,删除checkFile()函数。
如图所示,上传成功!
如图所示,冰蝎连接成功!
【pass-02】文件类型绕过
1、测试流程
试着上传一个大马:
抓包将Content-Type字段的值改为: image/png
放包,上传成功!
2、源码分析
<?php
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR . $_FILES['upload_file']['name'];
$is_upload = true;
}
} else {
$msg = '文件类型不正确,请重新上传!';
}
} else {
$msg = $UPLOAD_ADDR.'文件夹不存在,请手工创建!';
}
}
?>
分析上述代码可知,后端先利用$_FILES['file']['type']
获取文件类型(http请求体中Content-Type内容),对该内容进行了白名单过滤(image/gif、image/jpeg、image/png)(怪不得刚才改为image/jpg无法上传),此时直接抓包修改Content-Type字段值为三个中任意一个即可绕过。
move_uploaded_file(file,newloc)
:将上传的文件移动到新的位置newloc。
【pass-03】黑名单绕过
1、测试流程
抓包将后缀改为php4 | 上传成功! |
---|---|
用浏览器去访问,结果未解析。
修改apache的配置文件
添加apache解析的后缀。
用浏览器访问该文件:
结果为空白页,说明shell.php4已被成功解析了。
但是用冰蝎连不上
上网查了资料说是php版本的问题,php5+的连不上,php7可以。最后换了php7版本,连接成功!
2、源码分析
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array('.asp','.aspx','.php','.jsp');
$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)) { //黑名单过滤
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR. '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR .'/'. $_FILES['upload_file']['name'];
$is_upload = true;
}
} else {
$msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
}
} else {
$msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
}
}
总结
常见脚本解析的后缀名:
ASP: asa/cer/cdx
ASPX: ashx/asmx/ascx
PHP: php4/php5/phtml
JSP: jspx/jspf