文件上传
文件上传
0x01 简介
文件上传漏洞的由来
通过客户端的POST请求上传文件,由于消息主体就是一些上传信息。前端上传页面需要指定 enctype 为 multipart/form-data 或者 Multipart/form-data 才能正常上传文件。
1 | <form action='' enctype='multipart/form-data' method='POST'> |
multipart 格式的数据会将一个表单拆分为多个部分(part),每个部分对应一个输入域。在一般的表单输入域中,
它所对应的部分中会放置文本型数据,但是如果上传文件的话,它所对应的部分可以是二进制,下面展现了 multipart 的请求体:
filename 字段是必要的,指定了上传时的那个文件的文件名。其他的可有可无
1 | Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA |
这里在每个字段之间使用 ———WebKitFormBoundaryxxx 隔开,boundary是一个字符串,用来切分数据。
这里就和 post 请求一样,可以自己增加参数,就形如下面这样,将参数名放到 name 里,参数值放到下面:
1 | ------WebKitFormBoundary1PkqXeou9aUAIMHr |
那么这里就增加了一个参数 filename = ‘1.php’
产生原因
1 | 1.对于上传文件的后缀名(扩展名)没有做较为严格的限制 |
常见Bypass
前端检测-JS验证
前端对上传文件后缀进行检查,常见js代码
1 | function checkFile() { |
抓包修改后缀绕过
先上传符合题目要求的后缀名文件,可以是php一句话木马文件改成的图片马
修改完点击forward,到服务器后端发现成功上传成php文件
其他绕过方式:
1.在控制台重新定义函数 function checkFile(){}
回车即可(注:需要在未触发该函数前)
2.F12打开控制台,选择关闭JavaScript
后端白名单绕过
MIME
在传输过程中标记文件类型的一种方法,也就是 HTTP 文件请求头中的 Content-Type
常见源码
白名单检测
1 | if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) |
绕过
bp抓包,上传php木马,而后修改Content-Type 为题目要求,也可尝试再将上面的Content-Type的multipart/form-data 第一个字符 m 改成 M,即 Multipart/form-data(不影响传输)
大写 Multipart绕过同样也要改
00截断-1(GET|POST)
关于上传中00截断的理解与分析 | Tatsumaki’Blog
要求GPC处于关闭状态,且php版本小于5.3.29才可利用
在数据包中,含有上传后文件目录的情况才可使用。比如在数据包中存在path:/uploads/
这样一来,程序提取后缀名的时候就会合法,然后拼接路径与文件名。这个时候的拼接结果应该就是:/uploads/1.php%00/xxxxxxxx.php
于是移动文件的时候,就会把00后面的东西视作不存在,结果就变成了/uploads/1.php,从而getshell。
path在url、cookie或者上传方式不是multipart/from-data的时候,就不用进行url编码
后端黑名单绕过
特殊解析后缀
黑名单规则不严谨,在某些特定的环境中,某些特殊的后缀名仍然会被当做php文件解析。
Php|php2|php3|php4|php5|php6|php7|pht|phtm|phtml
.htaccess利用
原理:
- .htaccess 文件提供了针对目录改变配置的方法, 即在一个特定的文档目录中放置一个包含一条或多条指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过 Apache 的 AllowOverride 指令来设置。
2.htaccess 中有 # 单行注释符, 且支持 \拼接上下两行。
上传.htaccess文件内容为
1 | <FilesMatch "1.jpg"> |
将上传的1.jpg文件按php文件执行
SetHandler指令可以强制所有匹配的文件被一个指定的处理器处理。
.htaccess总结
1.htaccess文件使用要开启apache httpd.config AllowOverride All 而且要重启服务才能生效 和LoadModule rewrite_module modules/mod_rewrite.so 没关系
2.集成环境简单但是不安全所有的安全配置都是开启的,原始平台安装配置稍复杂但是安全系数高配置都是默认关闭的,而且一般集成环境拿到的shell基本上是最高权限
3.上传使用.htaccess文件如果碰到是黑名单处理并且是集成环境搭建的环境那就又很大的可能绕过验证getshell,不是的话就只能凭运气看站长是否开启了AllowOverride All
大小写绕过
window对大小写不敏感,linux对大小写敏感
1 | 1.Php |
黑名单替换要注意替换字符,如果替换成空字符串,则可以双写绕过,如果替换成空格或其他字符,则要放弃双写思路,尝试大小写绕过
::$$DATA绕过
利用NTFS文件流特性
在window的时候如果文件名+
"::$DATA"
会把::$DATA
之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA
之前的文件名,他的目的就是不检查后缀名
点绕过
windows等系统默认删除文件后缀的.和空格,查看网站源码发现,没有过滤点
配合解析漏洞
Apache HTTPD换行解析漏洞(CVE-2017-15715)
在2.4.0~2.4.29版本存在一个解析漏洞,在解析php时,1.php\x0A将按照php后缀进行解析,导致绕过一些服务器的安全策略
- 上传一个包含换行符的文件。注意,只能是
\x0A
,不能是\x0D\x0A
,所以我们用hex功能在1.php后面添加一个\x0A
- 然后访问
/1.php%0A
,即可发现已经成功getshell
获取文件名时不能用
$_FILES['file']['name']
,因为他会自动把换行去掉,这一点有点鸡肋默认的Apache配置即可利用,因为默认Apache配置就使用了
<FileMatch>
:
1
2
3 <FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>所以理论上,只要用正则来匹配后缀进行php解析的Apache就有这个问题。而这个做法刚好是为了解决Apache老的解析漏洞 而做的,可谓非此即彼,必然存在一种解析漏洞。
Nginx 解析漏洞
由于nginx.conf的如下配置导致nginx把以’.php’结尾的文件交给fastcgi处理,对于任意文件名,在后面添加/xxx.php(xxx)为任意字符后,即可将文件作为php解析。
1 | 上传shell.jpg |
其他
文件头检测
当文件上传到服务器,白名单进行的文件头检测。
JPEG (jpg),文件头:FFD8FF
PNG (png),文件头:89504E47
GIF (gif),文件头:47494638
png有时会加入HIDR头检测,主要标志是getimagesize函数
二次渲染
上传文件后,网站会对图片进行二次处理(格式、尺寸要求等),处理后在放到网站对应的标签进行显示。
如何绕过呢
1.将一句话插入网站二次处理的图片,把一句话插入图片在二次渲染后会保留的那部分数据里,确保不会在二次处理时删除掉。
选择gif文件成功率大,出现无变化片段大几率大
条件竞争漏洞
条件竞争为特别漏洞,是文件上传进行验证的短暂时间内。对传入的文件进行了临时保存,可能是一秒,也可能是0.几秒。但在这短暂时间内php是可以解析的,如果解析的速度够快。
绕过:
上传1.php文件,利用bp抓包,设置多线程,不断发包。浏览器访问连接我们上传的1.php文件。不断刷新,会在某瞬间,执行1.php成功。
危险函数检测
一般为waf对上传文件的内容进行检测
1.使用动态调用绕过,例如:
1 | <?php $_GET['0']($_GET['1']);?> |
2.上传编码后的webshell配合.htaccess来解析
3.上传编码后的webshell,再另外上传一个脚本文件解码webshell并写入新文件,例如下面这段代码为1.php
1 | PD9waHAgZXZhbCgkX1BPU1RbJ2EnXSk7Pz4= |
上传后再上传下面为2.php
1 | <?php |
然后访问后再访问test.php即可getshell
- 标题: 文件上传
- 作者: Sl0th
- 创建于 : 2022-03-04 00:09:02
- 更新于 : 2024-07-04 00:09:29
- 链接: http://sl0th.top/2022/03/04/文件上传/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。