PHP文件上传漏洞的浅析。
文件上传简介
在一个正常的网站中,通常都会存在一些允许用户上传文件的地方。但是有一些上传功能的地方没有对用户上传的内容进行过滤,导致会上传木马到服务器并执行命令,甚至控制服务器的权限。
文件上传实现
前端代码。
File uploads请选择上传的文件:
服务器端代码。<?php
// 通过$_FILES文件上传变量接收上传文件信息
header('content-type:text/html;charset=utf-8');
$fileinfo = $_FILES['myfile'];
$filename = $fileinfo['name'];
$type = $fileinfo['type'];
$tmp_name = $fileinfo['tmp_name'];
$size = $fileinfo['size'];
$error = $fileinfo['error'];
//判断错误号
if($error==UPLOAD_ERR_OK){
if(move_uploaded_file($tmp_name,"uploads/".$filename)){
echo '文件'.$filename.'上传成功';
}else{
echo '文件'.$filename.'上传失败';
}
}
上面是实现文件上传的测试代码,对上传文件没有进行任何的限制,可以进行任意文件的上传,比如以下上传一个php文件。
上传一个php文件,会显示文件test.php上传成功。然后访问该文件。
上面是只是一个理想的测试环境,来实现一下由于文件上传存在的一些漏洞。可能在实际环境中有多种的限制,比如对上传文件黑/白名单的限制、上传后文件名的重命名、可写目录没有执行权限等。
接下来复现phpCollab 2.5.1任意文件上传的漏洞,学习一下其中的原理。
phpCollab 2.5.1 - Arbitrary File Upload
下载对应的版本,安装。登录后台里面。在客户–>客户组织–>标志处,上传文件的地方存在任意文件上传漏洞。
在标志处可以进行任意文件上传,我们上传一个php后缀的文件,然后通过前端调试分析,可知上传后的文件路径以及名字。
最后,可以访问到上传后的文件。
其中漏洞点在/clients/editclient.php文件的第63~70行。$extension = strtolower( substr( strrchr($_FILES['upload']['name'], ".") ,1) ); // 后缀名字 substr(string,start,length)
if(@move_uploaded_file($_FILES['upload']['tmp_name'], "../logos_clients/".$id.".$extension"))
//move_uploaded_file() 函数将上传的文件移动到新位置。
{
chmod("../logos_clients/".$id.".$extension",0666);
$tmpquery = "UPDATE ".$tableCollab["organizations"]." SET extension_logo='$extension' WHERE id='$id'";
connectSql("$tmpquery");
}
从代码中可以看到没有对上传的文件进行任何的验证,直接通过move_uploaded_file来完成上传操作,并保存在logos_clients文件夹下。
接下来翻译一篇关于文件上传安全测试的文章,来具体学习一下如何来进行测试。
Web应用程序中的允许用户上传文件的函数处,有时候没有对上传内容其进行严格的过滤和验证,可能会导致攻击者利用此漏洞进行攻击。本文进行概述利用文件上传的功能进行渗透测试,将会介绍一些小技巧来绕过黑名单的过滤和一些实用的检测方法。
寻找上传点
文件上传功能非常容易验证和利用,一般在个人信息图片、文件上传和文件导入处。当你测试的时候,Burp被动扫描也会去验证存在上传功能的入口。
测试文件上传类型
一般的Web应用程序都会设置一个黑名单来过滤和验证用户上传的内容,但是有时候百密一疏,一些其他的后缀名会绕过黑名单。另外一种是白名单,只允许用户上传特定的文件。
这个时候需要测试一下允许上传的文件后缀名。使用Burp 测试文件上传类型手工测试一个请求,该请求会收到拒绝上传此类型之类等错误响应。发送这个请求到Burp intruder模块清除其中默认的选项
选择文件上传类型的点
选择不同的文件名,比如php.jpg,asp.jpg等
在选项中,配置grep匹配在第一步中响应出现的字符串。
开始进行测试,那些没有匹配到错误响应字符串的后缀,需要进一步的验证和测试,是否可以上传成功。关键点
使用Burp Intruder测试所有的后缀,使用Grep功能处理结果
一些不常见的后缀名可能会绕过黑名单,比如.php,.php5,.phtml
使用Burp测试文件上传的Content-Type
识别那些文件上传的Content-Type能被应用程序接受
和测试上传文件后后缀一样,同样是使用Burp Intruder进行爆破。这次修改的是Content-Type字段。参考上面的7个步骤即可。关键点
使用Burp Intruder测试所有的Content-Type,使用Grep功能处理结果
尝试将Content-Type更改为支持的文件类型,但是其中包含Web服务器/Web应用程序要处理的后缀名
一些不常见Content-Type可能会绕过黑名单
文件名和扩展模糊测试
文件名和扩展应该在输入验证时测试,当文件的名字为XSS,SQLi,LDAP或者一个命令注入载荷的时候会发生什么。
还是使用Burp Intruder进行测试,原理和测试文件上传类型类似,可以参考上面的七个步骤。
文件上传黑名单绕过
Windows IIS 文件上传黑名单绕过1:配合服务器解析漏洞,在黑名单加一个分号以及正常的文件名,例如shell.asp;.jpg
2:目录解析。folder.aspfile.txt,其中asp文件夹里面的任何扩展名文件都被IIS当作asp文件来执行。
3:环境是IIS,PHP时,< > 和 . 可以转换为 ? * .
4:使用可以替换文件的字符。比如>>可以替换 web.config
5:尝试在文件名后面使用空格或点。比如 foo.asp…. .. . . . .
6:file.asax:.jpg
7:尝试在文件名中加入禁止的字符,| %< * ? “,来得到错误信息。
Windows Apache 环境黑名单绕过1:Windows8.3 一个特征允许短文件名替换已经存在的文件。比如web.config可以被web~config.con替代,或者.htaccess可以被HTACESS~1替代。
2:尝试上传a.file,如果上传函数的根目录在www/uploads,将会创建一个uploads文件在上述目录。
其他绕过技术1:确定那些字符被过滤了。使用Burp在特定位置插入元字符表。
2:确保你的列表中包括一些不常见的扩展名,比如.php5,.php3,.phtml
3:测试防御机制。如果是过滤一些文件名,可能会被绕过。比如shell.ph.phpp,如果是过滤了php,之后名字后缀可能会变成.php
4:使用%00截断。比如shell.php%00.jpg, shell.php%0delete0.jpg。
5:双扩展名:如果应用程序过滤或者重命名扩展名。如果给它两个扩展名会发生什么?比如shell.php.php或者shell.txt.jog.png.asp。
6:尝试上传一个超长文件名,比如supermassivelongfileeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeename.php
7:尝试上传test.asp,test.asp.。
8:上传flash XSS攻击载荷,然后命名a.jpg
9:尝试以前的技术,但使用PDF或Silverlight代替
10:同样,尝试滥用crossdomain.xml或clientaccesspolicy.xml文件。
11:尝试使用编码绕过。比如URL,HTML,Unicode或者双重编码
12:结合以上所有的绕过技术。
13:尝试替换HTTP请求方法。使用POST替换PUT或者GET(反之亦然)。
14:确保所有的输入点进行模糊测试。
绕过文件上传白名单1:枚举出白名单并测试允许的扩展名来利用
2:测试文件内容正在验证中
3:测试扩展重命名技术,如shell.php.png
绕过文件大小上传机制
恶意文件内容
测试上传任何文件上传的内容是否被应用程序处理。比如你可以将XSS载荷写入到Excel,CSV,txt文件中,稍后看是否会由应用程序呈现。使用Burp repwater和intruder尝试在文件导入和上传功能函数中注入各种的载荷,测试应用程序的响应。
图像数据
可以在图像EXIF数据内注入反向shell吗?
在Kali安装apt-get install exiftool
在图像文件中注入代码后,只需上传文件,并使用校验和验证文件是否相同(以下是详细步骤)
用Burp注入请求
这是与上述EXIF方法类似的技术,但是你要将代码直接粘贴到打包请求中。1:使用burp上传一个合法的图片,且验证上传成功
2:发送之前的请求到repeater模块
3:在请求中的合法图像数据之后,尝试注入有效载荷(注入有效载荷或反向shell)
4:提交这个请求
5:从目标服务器上下载上传的我呢件,验证它是否包含有效的载荷。是否在目标服务器上能成功执行。
验证上传文件
不管你在上一步使用什么方法(EXIF或修改Burp请求),校验一个本地上传的和上传到目标服务器的文件,是否匹配。
服务器端命令执行技术
如果能成功上传一个shell到目标的web服务器上,你可以尝试以下技术来执行上传的shell。1:Apache MIME Types: 尝试上传重命名文件,比如shell.php.jpg或者shell.asp;.jpg,并且评估一下Web服务器是否会利用Apache MIME types。
2:空子节:使用一个空子节%00在文件名末尾,或者这样,shell.php%0delete0.jpg。观察应用程序的响应。
3:可以上传点文件。如果可以上传.htaccess文件,利用AddType:AddType application/x-httpd-php .foo 。
4:注意上传文件的任何处理 比如:可以在稍后由后端备份脚本,处理的文件名中使用命令注入?
5:注意服务器处理的上传文件。如果压缩文件允许上传,应用程序是否会提取其中的内容。反之亦然。
6:服务器防病毒是否处理上传了文件?尝试上传压缩文件类型如.zip,.rar等,如果服务器端防病毒易受攻击,可以利用并获得命令执行。
任意文件上传防御对上传文件格式限制,只允许某些格式文件上传。使用白名单
对文件格式进行校验,前端和服务器端都需要校验。
将上传文件的目录,设置权限。一般上传的都是静态文件,所以需要对其目录设置禁止执行权限。
将上传的文件的名字进行随机命名。
参考