文件上传


文件上传漏洞

简单认识

文件上传就是上传脚本到服务器解析执行,获取网站控制权

描述

文件上传漏洞是指由于程序员未对上传的文件进行严格的验证和过滤,而导致的用户可以越过其本身权限向服务器上传可执行的动态脚本文件。

如常见的头像上传,图片上传,oa 办公文件上传,媒体上传,允许用户上传文件,如果过滤不严格,恶意用户利用文件上传漏洞,上传有害的可以执行脚本文件到服务器中,可以获取服务器的权限,或进一步危害服务器。

危害

非法用户可以上传的恶意文件控制整个网站,甚至是控制服务器,这个恶意脚本文件,又被称为 webshell,上传 webshell 后门 很方便地查看服务器信息,查目录,执行系统命令等。

文件上传过程

客户端 :

选择发送的文件->服务器接收->网站程序判断->临时文件->移动到指定的路径

服务器 :

接收的资源程序

服务器接收资源的代码

<?php
if ($_FILES["file"]["error"] > 0)
{
echo "Error: " . $_FILES["file"]["error"] . "<br />";
}
else
{
echo "Upload: " . $_FILES["file"]["name"] . "<br />";
echo "Type: " . $_FILES["file"]["type"] . "<br />";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
echo "Stored in: " . $_FILES["file"]["tmp_name"];
}
?>

客户端文件上传的代码

<html>
<head></head>
<body>
<form action="upload.php" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>

上传返回

文件上传时会返回一些代码,返回客户端,客户端根据这些值判断上传是否正常

  • 值:0;

    没有错误发生,文件上传成功。

  • 值:1;

    上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值。

  • 值:2;

    上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。

  • 值:3;

    文件只有部分被上传。

  • 值:4;

    没有文件被上传。

文件上传漏洞

文件上传漏洞分为 直接文件上传,这种漏洞类型是属于高危漏洞的一种,能直接 getshell,而且没有任何限制,攻击者很容易通过上传点,获取网站的控制权限。

另外一种是有条件的上传漏洞,这种漏洞一般是开发者经验不足,对文件上传做了简单的限制,如简单的前端认证,文件头文件检测,这种检测行为,可以完全绕过的。

另外一个方面就是权限认证没处理,没有对文件上传页面进行权限认证,匿名者就能访问上传文件,上传网页后门到网站目录,控制整个网站。

还有一些上传逻辑有问题,导致文件上传可以被绕过,上传后门到网站上。

有的文件上传漏洞则是通过中间件或者系统特性上传可以被服务器解析脚本文件,从而导致网站可被控制。

image-20210920102112727

修复方案

  • 在网站中需要存在上传模块,需要做好权限认证,不能让匿名用户可访问。
  • 文件上传目录设置为禁止脚本文件执行。这样设置即使被上传后门的动态脚本也不能解析,导致攻击者放弃这个攻击途径。
  • 设置上传白名单,白名单只允许图片上传如,jpg png gif 其他文件均不允许上传
  • 限制上传的后缀名,一定要设置成图片格式如 jpg png gif
  • 修复中间件漏洞
  • 禁止客户端存在可控参数

攻击方法

寻找测试网站的文件上传的模块,常见的头像上传,修改上传,文件编辑器中文件上传,图片上传、媒体上传等,通过抓包上传恶意的文件进行测试,上传后缀名 asp php aspx 等的动态语言脚本,查看上传时的返回信息,判断是否能直接上传,如果不能直接上传,再进行测试上传突破,例如上传文件的时候只允许图片格式的后缀,但是修改文件时,却没有限制后缀名,图片文件可以修改成动态语言格式如 php,则可能访问这个文件的 URL 直接 getshell,可以控制网站。

常见的网站文件后缀名

可执行脚本的文件后缀名,可被网站目录解析。以下是常见的后缀名

  • asp
  • asa
  • cdx
  • cer
  • php
  • aspx
  • ashxjsp
  • php3
  • php.a
  • shtml
  • phtml

有些网站会对 asp 或者 php 进行过滤转成空可用这些后缀名。

  • aspasp asaspp
  • phpphp

任意文件上传

危害极大,如果攻击者能直接上传恶意脚本到网站存放的目录,且这个目录可解析动态脚本语言,那么攻击者就能够直接获取网站权限,甚至进一步权限提升,控制服务器。

代码分析

image-20210920104931946

获取文件名,把上传的临时文件移动到hackable/uploads/目录下

利用

直接上传文件,网页返回路径信息

image-20210920105143742

访问路径

上传的php文件被执行了

image-20210920105218696

绕过前端JS检测上传

在文件上传时,用户选择文件时或者提交时,有些网站会对前端文件名进行验证,一般检测后缀名是否为上传的格式。如果上传的格式不对,则弹出提示文字。

此时数据包并没有提交到服务器,只是在客户端通过 js 文件进行校验,验证不通过则不会提交到服务器进行处理。

image-20210920110356919

俩种绕过js检测方法

  • 按 F12 使用网页审计元素,把校验的上传文件后缀名文件删除,即可上传。
  • 把恶意文件改成 js 允许上传的文件后缀,如 jpg、gif、png 等,再通过抓包工具抓取 post 的数据包,把后缀名改成可执行的脚本后缀如 php 、asp、jsp、net 等。即可绕过上传。

第一种:

image-20210920110901937

image-20210920111019980

第二种:

image-20210920120628367

image-20210920120734423

即可绕过

前端JS检测代码分析

image-20210920121905998

绕过content-type检测上传

有些上传模块,会对 http 的类型头进行检测,如果是图片类型,允许上传文件到服务器,否则返回上传失败。

服务端是通过 content-type 判断类型,content-type 在客户端可被修改。则此文件上传也有可能被绕过的风险。

分析content-type代码

image-20210920123007542

首先进行submit提交判断,然后允许规定的格式上传

利用:

https://www.runoob.com/http/http-content-type.html

image-20210920123902360

image-20210920123937896

image-20210920124130044

绕过黑名单上传

上传模块,有时候会写成黑名单限制,在上传文件的时获取后缀名,再把后缀名与程序中黑名单进行检测,如果后缀名在黑名单的列表内,文件将禁止文件上传。

黑名单代码分析:

image-20210920124945553

上传图片时,如果提示不允许 php、asp 这种信息提示,可判断为黑名单限制,上传黑名单以外的后缀名即可。

在 iis 里 asp 禁止上传了,可以上传 asa cer cdx 这些后缀,如在网站里允许.net执行,可以上传 ashx 代替 aspx。如果网站可以执行这些脚本,通过上传后门即可获取 webshell。

在不同的中间件中有特殊的情况,如果在 apache 可以开启 application/x-httpd-php,在 AddType application/x-httpd-php .php .phtml .php3后缀名为 phtml 、php3 均被解析成 php 有的 apache 版本默认就会开启。上传目标中间件可支持的环境的语言脚本即可,如.phtml、php3。

image-20210920125450769

image-20210920125539198

.htaccess重写解析绕过上传

上传模块,黑名单过滤了所有的能执行的后缀名,如果允许上传.htaccess,也可进行绕过

.htaccess

文件的作用是 可以帮我们实现包括:文件夹密码保护、用户自动重定向、自定义错误页面、改变你的文件扩展名、封禁特定 IP 地址的用户、只允许特定 IP 地址的用户、禁止目录列表,以及使用其他文件作为 index 文件等一些功能。

在 htaccess 里写入 SetHandler application/x-httpd-php 则可以文件重写成 php 文 件。

要 htaccess 的规则生效 则需要在 apache 开启 rewrite 重写模块,因为 apache是多数都开启这个模块,所以规则一般都生效。

源码分析:

image-20210920130027903

黑名单
".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf"

我们先上传含有phpinfo的jpg,发现并未被解析为php,然后我们上传.htaccess,再次访问jpg发现被解析为php了

.htaccess

<FilesMatch "jpg">
SetHandler application/x-httpd-php
</FilesMatch>

image-20210920131134054

上传.htaccess后成功解析为php

image-20210920131146170

fck编辑器通过此方法

大小写绕过上传

有的上传模块 后缀名采用黑名单判断,但是没有对后缀名的大小写进行严格判断,导致可以更改后缀大小写可以被绕过。如 PHP、 Php、 phP、pHp

分析源码:

image-20210920131445342

这个黑名单里还加了.htaccess

既然少了这个函数,那我们显然是可以进行大小写绕过

image-20210920131811493

image-20210920131841935

空格绕过上传

在上传模块里采用黑名单过滤,如果没有对空格进行过滤有可能被绕过

源码分析:

image-20210920132120986

既然少了trim这个函数,我们可以通过给文件名前后加上空格进行绕过

image-20210920132725136

image-20210920132752988

可以看到上传成功并且作为php解析

利用windows系统特征绕过上传

在 windows 中,文件后缀名. 系统会自动忽略.,所以 shell.php. 和 shell.php 的效果一样。所以可以在文件名后缀加上.绕过。

源码分析:

image-20210920133124158

既然少了这个函数我们显然可以通过给末尾增加.的方式绕过

image-20210920133240894

image-20210920133313854

NTFS交换数据流::$DATA绕过上传

如果后缀名没有对::$DATA 进行判断,利用 windows 系统 NTFS 特征可以绕过上传。

源码分析:

image-20210920141121292

我们在文件后缀后加上::$DATA即可绕过

这里俩个冒号的含义是创建并写入内容,如果只是一个冒号只会创建文件,并不会写入内容

这里我上传是显示上传出错,查看上传地方发现文件没有被上传,我把冒号换成中文才能上传成功,但是无法作为php解析

正常情况下可以上传成功,去掉::$DATA即可看到phpinfo的内容

经过研究发现是php版本的问题,原来是php5.2版本,换为php5.4之后可以正常操作

image-20210920150038023

image-20210920152544768

image-20210920153009380

利用Windows环境的叠加特征绕过上传

在 windwos 中如果上传文件名 moonsec.php:.jpg 的时候,会在目录下生产空白的文件名 moonsec.php,再利用 php 和 windows 环境的叠加属性,

以下符号在正则匹配时相等

双引号” 等于 点号.

大于符号> 等于 问号?

小于符号< 等于 星号*

文件名.<或文件名.<<<或文件名.>>>或文件名.>><空文件名

源码分析:

image-20210920151003491

利用:

image-20210920153131378

查看上传处发现创建了一个空的1.php

image-20210920153207388

image-20210920153245278

查看上传地方,发现1.php内容被写入了

image-20210920153306045

双写后缀名绕过上传

在上传模块,有的代码会把黑名单的后缀名替换成空,例如 a.php 会把 php 替换成空,但是可以使用双写绕过例如 asaspp,pphphp,即可绕过上传。

源码分析:

image-20210920153656711

image-20210920153830281

image-20210920153915807

目录可控%00截断绕过上传

以上都是一些黑名单被绕过的,如果黑名单上传检测后,没有限定后缀名,绕过的方法很多

与黑名单相对的就是白名单,使用白名单验证会相对比较安全,因为只允许指定的文件后缀名。

但是如果有可控的参数目录,也存在被绕过的风险。

GET

源码分析:

image-20210920154517269

上传参数可控

  • 当 gpc 关闭的情况下,可以用%00 对目录或者文件名进行截断。
  • php 版本小于 5.3.4

首先上传一个jpg文件抓包修改

image-20210920160327417

image-20210920160406227

image-20210920160415340

可以看到上传了一个1.php

POST

image-20210920160623133

上传jpg文件抓包修改

image-20210920161128240

因为post上传提交的话需要进行url编码再给服务器,所以我们把%00进行url decode在提交

image-20210920161307068

查看上传点上传成功了

image-20210920161356998

文件头检测绕过

有的文件上传,上传时候会检测头文件,不同的文件,头文件也不尽相同。常见的文件上传图片头检测它检测图片是两个字节的长度,如果不是图片的格式,会禁止上传。

常见的文件头:

  • JPEG(jpg),文件头:FFD8FF
  • PNG(png),文件头:89504E47
  • GIF(gif),文件头:47494638
  • TIFF(tif),文件头:49492A00
  • WindowsBitmap(bmp),文件头:424D

源码分析:

image-20210921154007167

image-20210921154704781

如果上传的文件符合数字即可通过

利用:

  • 制作图片一句话,使用copy命令将php文件附加到jpg文件上,之后再上传
  • 或者在提交时在前面加上GIF89a

第一种:

copy 1.gif/b+1.php test1.php

image-20210921155118113

我们直接上传

image-20210921155745571

直接上传后此方法限制了文件后缀为gif,我们需要使用其中给的文件包含漏洞,让一句话来执行

image-20210921155927341

用它来访问我们的图片看看一句话执行了没有

image-20210921160017867

可以看到执行成功了

第二种:

我们上传一个gif抓包看下

image-20210921160131850

存在一个GIF8a,用来识别他的身份,让服务器知道它是一个gif,我们上传一个php,在前面加上GIF8a,猜测可以做到绕过

image-20210921160306587

可以看到上传成功了

同样他的后缀也是GIF,不能直接作为php解析,我们用文件包含来检测

image-20210921160456050

图片检测函数绕过上传

源码分析:

image-20210921162617199

利用:这样的话我们可以直接上传图片马

image-20210921162742424

同样上传后是gif,不能作为php解析,我们使用文件包含漏洞

image-20210921162852106

绕过图片二次渲染绕过

有些图片上传,会对上传的图片进行二次渲染后在保存,体积可能会更小,图片会模糊一些,但是符合网站的需求。

例如新闻图片封面等可能需要二次渲染,因为原图片占用的体积更大。访问的人数太多时候会占用,很大带宽。

二次渲染后的图片内容会减少,如果里面包含后门代码,可能会被省略。导致上传的图片马,恶意代码被清除。

源码分析:

image-20210921163820274

image-20210921163943861

png、gif大同小异

image-20210921164020241

可以看到使用了imagecreatefromxxx来进行二次渲染

利用:

首先我们看是否允许上传gif,因为gif图片在二次渲染后与原图差别不大,我们最好使用gif马。

我们将gif原图上传,将二此渲染后的土图片下载下来找到相同处,用一句话覆盖相同处上传即可绕过

image-20210921164614386

image-20210921165336570

同样用文件包含查看一句话是否能执行

image-20210921165404940

文件上传条件竞争绕过

在文件上传时,如果逻辑不对,会造成很大危害。

例如文件上传时,用move_uploaded_file 把上传的临时文件移动到指定目录,接着再用 rename 把文件设置为图片格式,如果在 rename 之前 进行move_uploaded_file 这个步骤,如果这个文件可被客户端访问,这样我们也可以获取一个 webshell。

源码分析:

image-20210921170459159

在rename之前没有进行后缀限制,如果这时我们可以访问文件就会让我们得到一个webshell

文件名可控绕过上传

文件上传时,文件名的可被客户端修改控制,会导致漏洞产生。

源码分析:

image-20210921173529944

利用:

  • 上传文件,文件码采用%00 截断,抓包解码例如 moon.php%00.php 截断后moon.php 或者使用/.

  • 与中间的漏洞配合使用

    例如 iis6.0 上传 1.php;1.jpg

    apache 上传 1.php.a 也能解析文件 a.asp;1.jpg 解析成 asp

第一种:

上传php码 通过1.php%00.jpg绕过

image-20210921173955594

image-20210921174053192

第二种:

利用apache解析漏洞,apache默认从右往左进行解析

image-20210921174423890

image-20210921174442922

也可用1.php;1.jpg

image-20210921174529109

改成iis6.0可解析文件

也可用/.

image-20210921174834788

image-20210921174848397

数组绕过上传

此方法一般通过代码审计发现

分析源码:

image-20210921175851920

所以我们需要让第二个数组大于1,这样他的值就获取不了,再用/这样就能上传了

利用:

首先我们过MIME检测,然后将变量设为数组,第二个数组大于1,用来过白名单

image-20210921184752082

image-20210921185102144

文件上传其他漏洞

nginx 0.83 /1.jpg%00php

apahce 1x 或者 2x

当 apache 遇见不认识的后缀名,会从后向前解析例如 1.php.rar 不认识 rar 就向前解析,直到知道它认识的后缀名。

phpcgi 漏洞(nginx iis7 或者以上) 上传图片后 1.jpg。访问 1.jpg/1.php 也会解析成php。

Apache HTTPD 换行解析漏洞(CVE-2017-15715)

apache 通过 mod_php 来运行脚本,其 2.4.0-2.4.29 中存在 apache 换行解析漏洞,在解析 php 时 xxx.php\x0A 将被按照 PHP 后缀进行解析,导致绕过一些服务器的安全策略。


文章作者: 晓莎K
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 晓莎K !
评论
  目录