PHP文件上传漏洞浅析

PHP文件上传漏洞的浅析。

文件上传简介

在一个正常的网站中,通常都会存在一些允许用户上传文件的地方。但是有一些上传功能的地方没有对用户上传的内容进行过滤,导致会上传木马到服务器并执行命令,甚至控制服务器的权限。

文件上传实现

前端代码。

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>File uploads</title>
</head>
<body>
    <form action="dofile.php" method="post" enctype="multipart/form-data">
    请选择上传的文件:
    <input type="file" name="myfile" /><br/>
    <input type="submit" value="上传文件" />
    </form>
</body>
</html>

服务器端代码。

<?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 测试文件上传类型
  1. 手工测试一个请求,该请求会收到拒绝上传此类型之类等错误响应。
  1. 发送这个请求到Burp intruder模块
    1. 清除其中默认的选项

    2. 选择文件上传类型的点

    3. 选择不同的文件名,比如php.jpg,asp.jpg等

    4. 在选项中,配置grep匹配在第一步中响应出现的字符串。

    5. 开始进行测试,那些没有匹配到错误响应字符串的后缀,需要进一步的验证和测试,是否可以上传成功。

关键点

使用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.asp\file.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.xmlclientaccesspolicy.xml文件。

11:尝试使用编码绕过。比如URL,HTML,Unicode或者双重编码

12:结合以上所有的绕过技术。

13:尝试替换HTTP请求方法。使用POST替换PUT或者GET(反之亦然)。

14:确保所有的输入点进行模糊测试。

绕过文件上传白名单

1:枚举出白名单并测试允许的扩展名来利用

2:测试文件内容正在验证中

3:测试扩展重命名技术,如shell.php.png

绕过文件大小上传机制

恶意文件内容

测试上传任何文件上传的内容是否被应用程序处理。比如你可以将XSS载荷写入到ExcelCSVtxt文件中,稍后看是否会由应用程序呈现。使用Burp repwaterintruder尝试在文件导入和上传功能函数中注入各种的载荷,测试应用程序的响应。

图像数据

可以在图像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等,如果服务器端防病毒易受攻击,可以利用并获得命令执行。

任意文件上传防御
  1. 对上传文件格式限制,只允许某些格式文件上传。使用白名单
  2. 对文件格式进行校验,前端和服务器端都需要校验。
  3. 将上传文件的目录,设置权限。一般上传的都是静态文件,所以需要对其目录设置禁止执行权限。
  4. 将上传的文件的名字进行随机命名。
参考

https://www.aptive.co.uk/blog/unrestricted-file-upload-testing/

https://www.exploit-db.com/exploits/42934/