文件上传漏洞

前端JS验证

要么看源码,要么抓包监听,如果上传文件的时候还没有抓取到数据包,但是浏览器就提示文件类型不正确的话,那么这个多半就是前端校验了:

直接将 shell.php 重命名为 shell.png 上传,抓包的时候再将文件名修改为 shell.php 即可绕过前端限制,成功上传 webshell。或者直接在浏览器上禁用 JS。

.htaccess 文件

AddType application/x-httpd-php .png
# 把.png文件解析成php

上传shell.php,抓包。

文件名改成.htaccess,内容改成AddType application/x-httpd-php .png 。

shell.php更改后缀名为.png再上传。

成功上传后门。

MIME类型

直接上传shell.php,抓包修改Content-Type 类型为:image/png 等合法的类型。

文件头

上传shell.php,更改MIME,并在文件头部加上GIF89a:

黑名单

嵌套

代码过滤不严:黑名单后缀设置为空,但是无递归,只检测一次,所以直接使用嵌套后缀:shell.pphphp

大小写

函数缺陷:str_replacestr_ireplace 都是 PHP 中用于字符串替换的函数,它们之间的区别在于str_replace区分大小写,只有完全匹配的字符串会被替换,这样很容易就被大小写绕过。

因为 Windows 环境下不区分大小写,所以更改后缀名为.PHp ,但是 Linux 区分大小写。

fuzz

burpsuite抓包,发送到Intruder,php后缀添加载荷。点击Payloads,载入fuzzdbmaster项目中针对php后缀的字典。

查看不同长度的响应,寻找可以绕过的后缀名。

00截断

抓包发现路径信息通过 GET 方式传递给后端,直接在路径后添加/new.php%00,这样保存的文件名就是这样的效果:

/usr/local/apache2/htdocs/upload/new.php%00shell.jpg

因为 %00 起到截断的作用,所以最终会在 upload 目录下面生成 new.php 的 webshell。

以上是GET型00截断,在url上%00自动解码一次。如果是POST型00截断,就需要手工解码:

条件竞争

源码有逻辑缺陷,是先上传再判断。所以在删除之前,访问上传的用来生成恶意shell的文件,创建一个新的shell文件。

上传shell.php,抓包,发送到Intruder。

因为上传了服务器就会删除,所以要不断上传,以便抓取访问shell.php的数据包。

与此同时,相同操作不断访问/upload/shell.php。

访问/upload/xiao.php,发现已存在,生成webshell成功。

二次渲染

准备一个gif,上传之后再导出。打开010Editor,对比两个文件内容:

灰色部分就是内容一致的部分,把后门代码插入到灰色部分:

上传之后复制图片链接,利用文件包含漏洞,可执行任意命令:

move_uploaded_file 缺陷

当 $img_path 可控的时候,将文件命名为shell.php/.,会把/.忽略,就可以上传一个php文件: