前言
一、文件上传漏洞的原理
- 文件上传漏洞是指用户上传了一个可执行的脚本文件(php、jsp、xml、cer等文件),而WEB系统没有进行检测或逻辑做的不够安全。
- 文件上传功能本身没有问题,问题在于上传后如何处理及解释文件。
- 一般情况下,Web应用都会允许用户上传一些文件,如头像、附件等信息,如果Web应用没有对用户上传的文件进行有效的检查过滤,那么恶意用户就会上传一句话木马等Webshell,从而达到控制Web网站的目的。
- 存在文件上传功能的地方都有可能存在文件上传漏洞,比如相册、头像上传,视频、照片分享。论坛发帖和邮箱等可以上传附件的地方也是上传漏阔的高危地带,另外像文件管理器这样的功能也有可能被攻击者所利用。
- 这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等
二、利用方式
1.上传WebShell文件,攻击者可通过这些网页后门执行命令并控制服务器。
2.上传文件是钓鱼图片或者包含了脚本的图片时,图片中的脚本,在某些版本的浏览器上会被作为脚本执行,从而被利用于钓鱼或者欺诈
3.上传病毒、木马文件,用于诱骗用户和管理员下载执行或者直接自动运行。
4.上传文件是其他恶意脚本时,攻击者可直接执行脚本进行攻击。
三、常用防御方式
- 检查文件上传路径 ( 避免 0x00 截断、 IIS6.0 文件夹解析漏洞、目录遍历 )
- 文件扩展名检测 ( 避免服务器以非图片的文件格式解析文件 ),验证文件扩展名 通常有两种方式 : 黑名单和白名单 .
- 文件 MIME验证 ( 比如 GIF 图片 MIME为 image/gif,CSS 文件的 MIME为 text/css 等 )
- 图片二次渲染 ( 最变态的上传漏洞防御方式 , 基本上完全避免了文件上传漏洞 )
- 文件重命名 ( 如随机字符串或时间戳等方式 , 防止攻击者得到 webshell 的路径 )
- 隐藏上传路径
- 文件内容检测 ( 避免图片中插入 webshell)
四、绕过方式
1.前端检测
主要是通过JavaScript代码进行检测,是最简单的绕过
绕过方法:
- 删除或者禁用js:火狐–>点击JS使其为灰色->成功禁用
- 使用代理上传文件,brup suite;上传符合要求的文件类型,抓包修改文件类型
2.后端_扩展名检测
针对文件的扩展名后缀进行检测,主要通过黑白名单进行过滤检测,若不符合过滤规则则不允许上传。
2.1黑名单
黑名单检测:一般有个专门的blacklist文件或列举出黑名单,里面会包含常见的危险脚本文件。
绕过方法
- 大小写绕过: 服务端没有将后缀名转换为统一格式进行比对,导致可以上传后缀为pHp的文件,又因为Windows操作系统大小写不敏感,所以.pHp扔回被当成php文件解析。
$is_upload = false; $msg = null; if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess"); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name);//删除文件名末尾的点 $file_ext = strrchr($file_name, '.'); $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA $file_ext = trim($file_ext); //首尾去空 if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件类型不允许上传!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; } }
- 通过源代码可见,黑名单里虽然看似过滤得很全面,但还是出现了纰漏–没有将后缀名转为小写,若后缀名为.pHP,则可以进行大小写绕过,成功上传文件。
$file_ext = strtolower($file_ext); //转换为小写
- 修改后缀名绕过:
- 黑名单中不允许上传.asp,.php,.jsp,.exe后缀的文件
- 但可上传
—asa cer aspx
—php php3 php4 php5 phtml pht
—jspx jspf
—exee - 前提是apache的httpd.conf中有如下配置代码
1 | AddType application/x-httpd-php .php .phtml .phps .php5 .pht
- 当我们修改文件名后,可以发现文件上传成功
- 重写(双写)绕过
- 服务端将黑名单的后缀名替换为空,但只进行一次。上传.pphphp后缀,替换一个php为空,则后缀名变为.php,成功绕过。
$is_upload = false; $msg = null; if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess"); $file_name = trim($_FILES['upload_file']['name']); $file_name = str_ireplace($deny_ext,"", $file_name); $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; } }
- 利用Windows的命名机制
shell.php. shell.php空格 shell.php:1.jpg shell. php::$DATA shell.php:1.jpg
在Windows中,后缀名后面的点和空格都会被删除掉
- 解析漏洞
- .htaccess文件解析漏洞
- apache解析漏洞
- IIS7.0或IIS7.5或nginx的解析漏洞
- IIS6.0解析漏洞
- 截断上传
- 截断类型:PHP%00截断
- 截断原理:由于00代表结束符,所以会把00后面的所有字符都截断
- 截断条件:PHP版本小于5.3.4,PHP的magic_quotes_gpc为OFF状态
2.2白名单
原理:白名单检测:一般有个专门的 whitelist 文件,里面会包含的正常文件:
Jpg png GIF
绕过方法
文件包含
3.后端检测_00截断
点击进入: 【文件上传绕过】——后端检测_文件名检测00截断绕过
原理:虽然web应用做了校验,但是由于文件上传后的路径用户可以控制,攻击者可以利用手动添加字符串标识符0X00的方式来将后面的拼接的内容进行截断,导致后面的内容无效,而且后面的内容又可以帮助我们绕过黑白名单的检测。
思路: 在C语言中,空字符有一个特殊含义,代表字符串的拼接结束。
这里我们使用的是php语言,属于高级语言,底层靠C语言来实现的,也就是说空字符的字符串拼接结束功能在PHP中也能实现。但是我们在URL中不能直接使用空,这样会造成无法识别;我们通过查看ASCII对照表,发现ASCII对照表第一个就空字符,它对应的16进制是00,这里我们就可以用16进制的00来代替空字符,让它截断后面的内容。
使用burpsuite进行抓包,因为这里是通过URL进行传递的文件上传后存储路径,所以需要对16进制的00进行URL编码,编码的结果就是%00,通过这种方式,就可以用%00截断后面的内容,让拼接的文件名不再进行生效:
4.后端检测_MIME检测:
MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。
常见MIME类型
text/plain (纯文本)
text/html (HTML文档)
text/javascript (js代码)
application/xhtml+xml (XHTML文档)
image/gif (GIF图像)
image/jpeg (JPEG图像)
image/png (PNG图像)
video/mpeg (MPEG动画)
application/octet-stream (二进制数据)
application/pdf (PDF文档)
检测方式: 在文件上传过程中,服务端会针对我们的上传的文件生成一个数组,这个数组其中有一项就是这个文件的类型file_type;服务端对文件进行检测时,就是通过检测脚本中的黑白名单和这个数组中的file_type进行对比,如果符合要求就允许上传这个文件。
MIME绕过原理: 部分Web应用系统判定文件类型是通过content-type字段,黑客可以通过抓包,将content-type字段改为常见的图片类型,如image/gif,从而绕过校验。
5.后端检测_文件头检测漏洞
原理: 在每一个文件(包括图片,视频或其他的非ASCII文件)的开头(十六进制表示)实际上都有一片区域来显示这个文件的实际用法,这就是文件头标志。我们可以通过16进制编辑器打开文件,添加服务器允许的文件头以绕过检测。
常见文件头
GIF:47 49 46 38 39 61
png: 89 50 4E 47 0D 0A 1A 0A
jpg:FF D8 FF E0 00 10 4A 46 49 46
在进行文件头绕过时,我们可以把上面的文件头添加到我们的一句话木马内容最前面,达到绕过文件头检测的目的。
6.后端_内容检测图片马绕过
**原理:**一般文件内容验证使用getimagesize函数检测,会判断文件是否是一个有效的文件图片,如果是,则允许上传,否则的话不允许上传。
图片马制作
准备一张图片,这里为a.png,和一个一句话木马,通过以下命令合成一个图片马3.php:
a.php内容:
<?php phpinfo(); ?>
命令:
1 | copy a.png /b + a.php /a 3.php 2 | /b:指定以二进制格式复制、合并文件,用于图像或者声音类文件 3 | /a:指定以ascii格式复制、合并文件用于txt等文本类文件
注:这条命令的意思是:通过copy命令,把a.png图片文件,以二进制文件形式添加到a.php文件中,以ASCII文本文件形式输出为3.php文件。
7.解析漏洞
7.1 .htaccess文件解析漏洞
漏洞利用前提: web具体应用没有禁止.htaccess文件的上传,同时web服务器提供商允许用户上传自定义的.htaccess文件。
原理: .htaccess文件(或者”分布式配置文件”) ,全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法,即,在一个特定的文档目录中放置一个包含一个或多个指令的文件,以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。
利用方式: 上传覆盖.htaccess文件,重写解析规则,将上传的带有脚本马的图片以脚本方式解析。
.htaccess文件内容:
.htaccess文件解析规则的增加,是可以按照组合的方式去做的,不过具体得自己多测试。
<FilesMatch "evil.gif"> SetHandler application/x-httpd-php #在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行 AddHandler php5-script .gif #在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行 </FilesMatch>
7.2 Apache解析漏洞
原理: Apache 解析文件的规则是从右到左开始判断解析,如果后缀名为不可识别文件解析,就再往左判断。比如test.php.a.b的“.a”和“.b”这两种后缀是apache不可识别解析,apache就会把test.php.a.b解析成test.php。
7.3 IIS6.0解析漏洞
IIS6.0解析漏洞分两种:
1、目录解析:
以xx.asp命名的文件夹里的文件都将会被当成ASP文件执行。
2、文件解析:
xx.asp;.jpg 像这种畸形文件名在;后面的直接被忽略,也就是说当成xx.asp文件执行。
IIS6.0 默认的可执行文件除了asp还包含这三种 .asa .cer .cdx。
7.4 IIS7.0 | IIS7.5 | Nginx的解析漏洞
原理: Nginx拿到文件路径(更专业的说法是URI)/test.jpg/test.php后,一看后缀是.php,便认为该文件是php文件,转交给php去处理。php一看/test.jpg/test.php不存在,便删去最后的/test.php,又看/test.jpg存在,便把/test.jpg当成要执行的文件了,又因为后缀为.jpg,php认为这不是php文件,于是返回Access denied。
这其中涉及到php的一个选项:cgi.fix_pathinfo,该值默认为1,表示开启。开启这一选项PHP可以对文件路径进行修理。
举个例子,当php遇到文件路径/1.jpg/2.txt/3.php时,若/1.jpg/2.txt/3.php不存在,则会去掉最后的/3.php,然后判断/1.jpg/2.txt是否存在,若存在,则把/1.jpg/2.txt当做文件/1.jpg/2.txt/3.php,若/1.jpg/2.txt仍不存在,则继续去掉/2.txt,以此类推。
漏洞形式: www.xxxxx.com/UploadFiles/image/1.jpg/1.php
另外两种解析漏洞:
www.xxxxx.com/UploadFiles/image/1.jpg%00.php
www.xxxxx.com/UploadFiles/image/1.jpg/%20\0.php
8.二次渲染漏洞
原理: 在我们上传文件后,网站会对图片进行二次处理(格式、尺寸要求等),服务器会把里面的内容进行替换更新,处理完成后,根据我们原有的图片生成一个新的图片并放到网站对应的标签进行显示。
绕过:
1、配合文件包含漏洞:
将一句话木马插入到网站二次处理后的图片中,也就是把一句话插入图片在二次渲染后会保留的 那部分数据里,确保不会在二次处理时删除掉。这样二次渲染后的图片中就存在了一句话,在配合文件包含漏洞获取webshell。
2、可以配合条件竞争:
这里二次渲染的逻辑存在漏洞,先将文件上传,之后再判断,符合就保存,不符合删除,可利用条件竞争来进行爆破上传
如何判断图片是否进行了二次处理?
对比要上传图片与上传后的图片大小,使用16进制编辑器打开图片查看上传后保留了哪些数据,查看那