文件上传漏洞
为了上传“不合规”文件(后门)
题目:在BUUCTF中(BUUCTF在线评测)
windows特性
-
Windows系统下,文件名后缀最后一个“.”和空格会被自动去除,例如黑名单为.php 那么可以上传.php.,.php或者.php 来绕过黑名单,Windows在解析时会删除最后一个.和还有空格
-
在Windows的时候如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA之前的文件名
-
Windows 文件系统将文件和目录名称视为不区分大小写。 FOO.txt 和 foo.txt 将被视为等效文件。
-
Linux 文件系统将文件和目录名称视为区分大小写。 FOO.txt 和 foo.txt 将被视为不同文件。
pass1-前端检验
源码
错误提示
分析:可以发现这是有由前端js进行校验
解决方法
1.禁止浏览器使用js
2.用bp抓包,修改后缀名
pass2-后端MIME验证
源码
分析
(mime与文件后缀名作用类似,来告诉服务器文件的性质和格式,但比后缀名更详细,浏览器一般用mine而不用后缀名)
1.可以知道这里Content-type(Mine)进行限制(只允许上传jpeg,png……)
解决方法
1.用bp抓包,修改Content-type为(imag/jpeg……)(就是直接把PHP文件的mime改成图片的mine)
pass3-黑名单验证
出错提示
分析
1.不是前端js校验,直接用bp改后缀名没用
2.在Apache平台phtml,php3,php5,pht都会被解析为php(D:\phpstudy_pro\Extensions\Apache2.4.39\conf\httpd.conf)
解决方法
1.上传后缀名为phtml,php3,php5,pht的文件
pass4-黑名单验证
源码
题目提示
分析(strrchr() 函数查找字符在指定字符串中从后面开始的第一次出现的位置,如果成功,则返回从该位置到字符串结尾的所有字符,如果失败,则返回 false。与之相对应的是strchr()函数,它查找字符串中首次出现指定字符的位置。)
1.几乎禁止了所有格式(可能有害的(PHP……))
2.发现 .htaccess没有被禁止
(htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。)
解决方法
1.创建一个 .htaccess文件,写入
SetHandler application/x-httpd-php
(意思是将所有文件以php的格式解析)
2.上传 .htaccess文件,在将要上传的php文件(或其他文件)后缀修改为txt(或其他在黑名单之外的),然后上传
pass5-大小写绕过
源码和提示
分析
1.可以看到 .htaccess文件也被过滤,无法上传
2.与pass4相比发现没有strtolower函数(转换为大小写),所以考虑大小写转换
解决方法
1.上传 1.Php 文件(或 . pHP)
pass6-空格绕过
源码与提示
分析
-
.htaccess 文件被过滤
-
与pass5相比有了大小写转换,没有了首尾去空
-
windows特性,会自动删除文件后的空格,可以正常解析文件(“1.php”与“1.php ”不相等)
解决方法
-
在 .php(后添加空格)
pass7-点绕过
源码和提示
分析
1.所有文件的无法上传
2.与pass6相比没有deldot 函数,所以考虑点运算
3.windows会自动删除文件后的点
解决方法
1.在 1.php文件后台添加 .(一个点)
Pass8-::$DATA绕过
源码和提示
分析
1.与pass7相比,没有str_ireplace函数(去除字符串::$DATA)
(当文件末尾添加::$DATA 之后会将该文件当做文件流处理,且保持之前的文件名,比如 " 1. p h p : : DATA之后会将该文件当做文件流处理,且保持之前的文件名,比如"1.php::DATA",Windows会自动去掉末尾的::$DATA变成"1.php")
解决方法
1.在1.php后添加 ::$DATA
pass9-点+空格+点绕过
源码和提示
分析
1.pass5~7的方法都无法使用
2.该php获取文件后缀名,首先去除文件名前后的空格和最后的点,再转换为大小写,再去除::$DATA和空格。但在最后保存文件路径的时候就用了$file_ext,所以相当于只去除前后空格和最后的一个点,还有一个点没被去除,就能利用Windows特性(自动去除文件后的带点)
解决方法
-
使用 1.php. .(点+空格+点)(后面的点不连续,就只会删除最后一个点,还会留下一个点,实现点绕过)
-
pass8也可用此方法
pass10-双写绕过
源码和提示
分析
-
str_replace(1,2,3),在字符串3中将所有1替换为2,
-
将文件名中的php替换为空,但只会替换一次(),所以使用双写(pphphp->php,pphphphppphp->php)
解决方法
-
使用双写
pass11-00截断(get传参)
源码和提示
分析
-
substr(1,2,3),从2(字符串或数字)开始在1中截取长度为3的字符串(3不写,就从2开始截到尾)
-
strrpos(1,2)查找2在1中最后出现的位置
-
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1); (就是获取文件中最后一个点的之后的字符串(后缀名),防止了点绕过)
-
$img_path是由$_GET拼接起来的,可以抓包修改GET(较少)
(00截断原理:在PHP中00代表结束符,所以会把00后的所有字符串删除)
解决方法
-
将GET修改为1.php%00
注意
1.截断条件为:但是截断条件为:php版本小于5.3.4,php的magic_quotes_gpc为OFF状态(5.3.4的该漏洞已被修复)
pass12-00截断(post传参)
源码
分析
-
与pass11相似,只是POST不会像GET对%00进行自动解码,所以需要在二进制中进行修改。
解决方法
-
在文件名后添加任意一个字符
-
然后再Hex(16进制)中将对应的编码改为00
注意:与pass11有同样的版本要求
.user.ini
.user.ini中两个中的配置就是auto_prepend_file和auto_append_file。这两个配置的意思就是:我们指定一个文件(如1.jpg),那么该文件就会被包含在要执行的php文件中(如index.php),相当于在index.php中插入一句:require(./1.jpg)。这两个设置的区别只是在于auto_prepend_file是在文件前插入,auto_append_file在文件最后插入。
利用.user.ini的前提是服务器开启了CGI或者FastCGI,并且上传文件的存储路径下有index.php可执行文件。
GIF89a
auto_prepend_file=ini.png
(ini.png为后门文件,GIF89a是文件幻术头(把它解析为gif))
(接下来是去访问index.php,而不是ini.png)
总结
对于黑名单,先检查是否禁止.htaccess,如果被禁止,就看能不能点,空格,大小写等绕过
pass13/14/15-图片马
图片马制作流程
原料:一张图片,一个php文件
步骤
-
进入cmd
-
执行命令
copy 1.jpg /b + 2.php /a 新图片名
/b二进制,/a追加,就是将2.php追加到1.jpg中,制作完成
解决
-
上传图片,并复制上传后的文件地址
-
进入文件包含漏洞
-
对URL执行 ?file=图片地址(通过在新标签页打开图像,得到图片地址->然后进入包含文件,在include.php后编写file)
文件包含漏洞
文件包含漏洞简单说就是,在这个include.php中需要引用其他应用程序,php中应用程序文件是.php也就是说,他本来想引用一个php文件,但是漏洞就是,他不会识别什么是php文件,只要是他引用的,他都当php来解析,所以如果他引用的是jpg,但是jpg中有图片马,那么他就相当于引用了图片马,如果没这个漏洞,这个图片马就无法生效
注意:pass14/15和13区别不大
pass16-图片二次渲染
pass17-竞争条件上传
结论
1.看是否是前端验证
2.对 mime类型进行测试
3.看是黑/白名单
黑:
-
首先用 .htaccess 看是否可以(SetHandler application/x-httpd-php)
-
使用 点+空格+点进行测试
-
大小写,空格,点,::$DATA
白:
-
00截断
-
图片马