百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

文件上传漏洞学习笔记—原理、危害、解析、绕过、编辑器、服务器

off999 2025-03-14 19:46 10 浏览 0 评论

黑客教程、技术文章,关注公众号:掌控安全EDU

文件上传解析漏洞

文件上传漏洞

文件上传漏洞是指网络攻击者上传了一个可执行的文件到服务器并执行。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。

由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致用户可以越过其本身权限向服务器上传可执行的动态脚本文件。

打个比方来说,如果你使用 windows 服务器并且以 asp 作为服务器端的动态网站环境,那么在你的网站的上传功能处,就一定不能让用户上传 asp 类型的文件,否则他上传一个 webshell,你服务器上的文件就可以被他任意更改了。因此文件上传漏洞带来的危害常常是毁灭性的,Apache、Tomcat、Nginx等都曝出过文件上传漏洞。

文件上传漏洞危害

上传漏洞与SQL注入或 XSS相比,其风险更大,如果 Web应用程序存在上传漏洞,攻击者上传的文件是Web脚本语言,服务器的Web容器解释并执行了用户上传的脚本,导致代码执行。如果上传的文件是Flash的策略文件crossdomain.xml,黑客用以控制Flash在该域下的行为。

如果上传的文件是病毒、木马文件,黑客用以诱骗用户或者管理员下载执行。如果上传的文件是钓鱼图片或为包含了脚本的图片,在某些版本的浏览器中会被作为脚本执行,被用于钓鱼和欺诈。甚至攻击者可以直接上传一个webshell到服务器上 完全控制系统或致使系统瘫痪。

文件上传漏洞原理

大部分的网站和应用系统都有上传功能,而程序员在开发任意文件上传功能时,并未考虑文件格式后缀的合法性校验或者是否只在前端通过js进行后缀检验。

这时攻击者可以上传一个与网站脚本语言相对应的恶意代码动态脚本,例如(jsp、asp、php、aspx文件后缀)到服务器上,从而访问这些恶意脚本中包含的恶意代码,进行动态解析最终达到执行恶意代码的效果,进一步影响服务器安全。

文件上传漏洞满足条件

1. 文件上传功能能正常使用

2. 上传文件路径可知

3. 上传文件可以被访问

4. 上传文件可以被执行或被包含

文件上传数据包解析

Content-Length:即上传内容大小

MAX_FILE_SIZE:即上传内容的最大长度

Filename:即上传文件名

Content-Type:即上传文件类型

请求包中的乱码字段,即是所上传文件的内容

文件上传漏洞绕过技巧

1、客户端校验(js检测):

一般是在网页上写一段Js脚本,用Js去检测,校验上传文件的后缀名的合法性问题。

在检查扩展名是否合法的时候,有两种策略:白名单策略和黑名单策略。

判断方式:在浏览加载文件,但还未点击上传按钮时便弹出对话框,内容如:只允许上传.jpg/.jpeg/.png后缀名的文件,而此时并没有发送数据包,所以可以通过抓包来判断,如果弹出不准上传,但是没有抓到数据包,那么就是前端验证。其实,也可以直接查看网页源代码,源代码中如果没有js前端效验,那么就一定是后端效验喽。

绕过方法:这个限制是在客户端进行的,这种限制形同虚设。传正常文件改数据包就可以绕过,甚至关闭JS都可以尝试绕过。

黑白名单机制:

黑名单:不允许上传什么,文件扩展名在黑名单中的为不合法。

白名单:只允许上传什么,文件扩展名不在白名单中的均为不合法。

白名单比黑名单更安全

2、服务端检测:

检查Content-Type (内容类型)

检查后缀 (检查后缀是主流)

检查文件头

绕过方法:假如将webshell代码文件后缀改为其它被服务器认为是安全的后缀,再通过解析漏洞让其按照脚本文件进行解析,就达到了最终的目的。

服务端MIME检测绕过(Content-Type检测)

HTTP协议规定了上传资源的时候在Header中加上一项文件的MIMETYPE,来识别文件类型,这个动作是由浏览器完成的,服务端可以检查此类型不过这仍然是不安全的,因为HTTP header可以被发出者或者中间人任意的修改,不过加上一层防护也是可以有一定效果的。

绕过方法:使用burp代理,修改Content-Type的参数。

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文档)

application/(编程语言) 该种语言的代码

application/msword(Microsoft Word文件)

message/rfc822(RFC 822形式)

multipart/alternative(HTML邮件的HTML形式和纯文本形式,相同内容使用不同形式表示)


application/x-www-form-urlencoded(POST方法提交的表单)

multipart/form-data(POST提交时伴随文件上传的表单)

服务端扩展名检测绕过:

在文件被上传到服务端的时候,对于文件名的扩展名进行检查,如果不合法,则拒绝这次上传。在检查扩展名是否合法的时候,有两种策略:黑名单策略和白名单策略。

白名单策略是更加安全的,通过限制上传类型为只有我们接受的类型,可以较好的保证安全,因为黑名单我们可以使用各种方法来进行注入和突破。

绕过方法:

文件名大小写绕过,例如Php,AsP等类似的文件名

后缀名字双写嵌套,例如pphphp,asaspp等

可以利用系统会对一些特殊文件名做默认修改的系统特性绕过

可以利用asp程序中的漏洞,使用截断字符绕过

可以利用不再黑名单列表中却能够成功执行的同义后缀名绕过黑名单的限制。

可以利用解析/包含漏洞配合上传一个代码注入过的白名单文件绕过。

1.老版本的IIS中的目录解析漏洞,如果网站目录中有一个 /.asp/目录,那么此目录下面的一切内容都会被当作asp脚本来解析

2.老板本的IIS中的分号漏洞:IIS在解析文件名的时候可能将分号后面的内容丢弃,那么我们可以在上传的时候给后面加入分号内容来避免黑名单过滤,如 a.asp;jpg

3.旧版Windows Server中存在空格和dot漏洞类似于 a.php. 和 a.php[空格] 这样的文件名存储后会被windows去掉点和空格,从而使得加上这两个东西可以突破过滤,成功上传,并且被当作php代码来执行

4.nginx空字节漏洞 xxx.jpg%00.php 这样的文件名会被解析为php代码运行

5.apache的解析漏洞,上传如a.php.rar a.php.gif 类型的文件名,可以避免对于php文件的过滤机制,但是由于apache在解析文件名的时候是从右向左读,如果遇到不能识别的扩展名则跳过,rar等扩展名是apache不能识别的,因此就会直接将类型识别为php,从而达到了注入php代码的目的

服务端文件头内容检测绕过:

这种方法利用的是每一个特定类型的文件都会有不太一样的开头或者标志位。可以通过比如php的exif_imagetype()函数来检测。

通过检查头几位字节,可以分辨是否是图片文件。

不同类型的文件都有对应的文件类型签名(也叫类型幻数,简称文件头),比如,PNG 的文件头为十六进制的 89 50 4E 47 0D 0A 1A 0A;GIF 为 47 49 46 38 37 61、JPG 为 FF D8 FF E0。

通过在文件中添加正常文件的标识或其他关键字符绕过。

给上传脚本加上相应的幻数头字节就可以,php引擎会将 <?之前的内容当作html文本,不解析直接跳过,后面的代码仍然能够得到执行。

其他类型的二进制文件,也有相应的头字节。

文件加载检测绕过,针对渲染加载测试。

代码注入绕过,针对二次渲染测试。

3、文本编辑器的漏洞

很多网站为了节省开发成本,直接使用现成的文本编辑器,如fckeditor,这种编辑器经常在网上被爆出漏洞,可以对这些漏洞进行利用。

3.1、文件解析漏洞

攻击者在利用上传漏洞时,通常会与Web容器的解析漏洞配合在一起。所以我们首先来了解一下解析漏洞,这样才能更深入地了解上传漏洞,并加以防范

常见的Web容器有ⅡS、Apache、Nginx、Tomcat等,下面主要讲IIS、Apache、Nginx容器。

3.2、服务器解析漏洞

Apache1.x 2.x解析漏洞

Apache 解析文件的规则是从右到左开始判断解析,如果后缀名为不可识别文件解析,就再往左解析,直到碰到认识的扩展名为止,如果都不认识,则会暴露其源代码。

这种方法可以绕过基于黑名单的检查。比如test.php.owf.rar。".owf"和".rar" 这两种后缀是apache不可识别解析,apache就会把wooyun.php.owf.rar解析成php。

若一个文件名abc.x1.x2.x3,Apache会从x3开始解析,如果x3不是一个能解析的扩展名(mime.types文件里面没有定义的扩展名),就往前解析x2以此往复,直到能遇到一个能解析的文件名为止,如果都不认识就暴露源码。

如果上传的文件名使我们可以定义的,那么我们可以完全上传一个xxx.php.abc这样名字的webshell,Apache仍然会当做PHP来解析。

IIS 5.x/6.0解析漏洞

asa cer cdx 也会被解析

IIS6.0除了将ASP后缀当做ASP进行解析的同时,当文件后缀名字为.asa .cer.cdx 也会当做asp去解析,这是因为IIS6.0在应用程序扩展中默认设置了.asa.cer.cdx 都会调用 asp.dll。

IIS 6.0在处理含有特殊符号的文件路径时会出现逻辑错误,从而造成文件解析漏洞。IIS5.1和IIS7.5无此漏洞。

这一漏洞有两种完全不同的利用方式文件解析和目录解析:

1. 文件解析:分号后面的不被解析

test.asp;1.jpg 或者test.asp;.jpg 他将当做asp进行解析(特殊符号是";")。

在IIS6.0下,分号后面的不被解析。

应用程序在验证文件后缀的时候是验证文件名最后的字串,如:text.asp;1.jpg,是图片,但是在IIS6.0里解析的时候,是忽略掉分号后面的字串,直接解析为test.asp。

2. 目录解析:在文件夹为.asp和 .asa内的所有文件被当成解析文件解析

test.asp/1.jpg 他将当做asp进行解析(特殊符号是"/")。

IIS6.0 在解析 asp 时,如果任意目录名为 .asp、.asa 的文件夹,其目录内的任何扩展名的文件都被IIS当作asp文件来解析并执行。

创建目录test.asp,此目录下的文件将被当作asp文件来执行。如果可以控制上传文件夹路径,就可以不管你上传后你的图片改不改名都能拿shell了。

IIS6.0解析原理:

请求 /test.asp;1.jpg

N1:从头部查找,查找 "."号,获得 .asp;1.jpg。

N2:查找";"号,如果有则内存截断。

N3:查找"/",如果有则内存截断。

最终,将保留下来 .asp 字符串,从META_SCRIPT_MAP脚本映射表里与扩展名匹配对比,并反馈给了asp.dll处理。

IIS7.0/7.5 对php解析有所类似于 Nginx 的解析漏洞。只要对任意文件名在url后面追加上 字符串 / 任意文件名.php 就会按照php去解析。

举个栗子:把一下代码做成图片马text.jpg。





上传test.jpg,然后访问test.jpg/.phptest.jpg/abc.php当前目录下就会生成一句话木马 123.php。

IIS 7.0/IIS 7.5/ Nginx <8.03畸形解析漏洞

在某些使用Nginx的网站中,访问
http://www.xxx.com/1.jpg/1.php,此时的1.jpg会被当作PHP脚本来解析,此时1.php是不存在的,却可以看到1.jpg已经按照PHP脚本来解析了,问题就出现在这个"1.PHP"上(1.php并不是特定的,可以随机命名)。这就意味着攻击者可以上传合法的"图片"(图片木马),然后在URL后面加上"/xxx.php",就可以获得网站的WebShell。

这不是Nginx特有的漏洞,在IIS7.0、IIS7.5、Lighttpd等Web容器中也经常会出现这样的解析漏洞。

这个解析漏洞其实是PHP CGI的漏洞,在PHP的配置文件中有一个关键的选项cgi.fix_pathinfo在本机中位于C:\wamp\bin\php\php5.3.10\php.ini,默认是开启的,当URL中有不存在的文件,PHP就会向前递归解析。

Nginx解析原理

以下三个解释,那个好理解就理解那个。

解释一:

nginx在接受请求后会得到一个地址URL/abc.jpg/c.php

在经过location指令,将请求交给fastcgi处理,nginx为其设置环境变量SCRIPT_FILENAME,内容为/abc.jpg/c.php

后端的fastcgi在接受到该选项时,会根据PHP的fix_pathinfo配置决定是否对SCRIPT_FILENAME进行额外的处理,一般情况下如果不对fix_pathinfo进行设置将影响使用PATH_INFO进行路由选择的应用,

所以该选项一般配置开启。php通过该选项之后将查找其中真正的脚本文件名字,查找的方式也是查看文件是否存在,这个时候将分离SCRIPT_FILENAME和PATH_INFO分别为/scripts/abc.jpg和c.php

最后,以/scripts/abc.jpg作为此次请求需要执行的脚本,攻击者就可以实现让nginx以php来解析任何类型的文件了。

解释二:

Nginx默认是以CGI的方式支持PHP解析的,普遍的做法是在Nginx配置文件中通过正则匹配设SCRIPT_FILENAME。

当访问
www.xx.com/phpinfo.jpg/1.php这个URL时,$fastcgi_script_name会被设置"phpinfo.jpg/1.php",然后构造成SCRIPT_FILENAME(绝对路径)传递给PHP CGI,如果开启了cgi.fix_pathinfo=1选项(这个默认值就是1,所以没有设置过就是开启),那么就会触发在PHP中的如下逻辑:

PHP会认为SCRIPT_FILENAME(绝对路径)是phpinfo.jpg,而1.php是PATH_INFO,所以就会phpinfo.jpg作为PHP文件来解析了。也是一个逻辑问题,所以说我们只需要在正常的.jpg后面加/.php就可以成功的绕过解析。

解释三:

IIS和Nginx在这一点上是一样的,一看到URL中文件后缀是.php,便无论该文件是否存在,都直接交给php处理,而php又默认开启"cgi.fix_pathinfo",会对文件路径进行"修理",何谓"修理"?举个例子,当php遇到文件路径"/aaa.xxx/bbb.yyy/ccc.zzz"时,若"/aaa.xxx/bbb.yyy/ccc.zzz"不存在,则会去掉最后的"/ccc.zzz",然后判断"/aaa.xxx/bbb.yyy"是否存在,若存在,则把"/aaa.xxx/bbb.yyy"当做文件"/aaa.xxx/bbb.yyy/ccc.zzz",若"/aaa.xxx/bbb.yyy"仍不存在,则继续去掉"/bbb.yyy",以此类推。

若有文件test.jpg,访问时在其后加/.php,便可以让IIS把"test.jpg/.php"交给php,php"修理"文件路径"test.jpg/.php"得到"test.jpg",该文件存在,便把该文件作为php程序执行了

asp没有"cgi.fix_pathinfo",所以不存在这一问题。

在默认Fast-CGI开启状况下,上传一个名字为xx.jpg,内容为:

<?PHP fputs(fopen('shell.php','w'),'');?>

的文件,然后访问xx.jpg/.php或xxx.jpg/1.php,在这个目录下就会生成一句话木马 shell.php文件。

Nginx <8.03 %00空字节执行php漏洞

Nginx如下版本:

0.5.*, 0.6.*, 0.7 <= 0.7.65, 0.8 <= 0.8.37

在使用PHP-FastCGI执行php的时候,URL里面在遇到%00空字节时与FastCGI处理不一致,导致可在非php文件中嵌入php代码,通过访问url+%00.php来执行其中的php代码。如:
http://local/robots.txt%00.php会把robots.txt文件当作php来执行。

PHP的path_info

Path_info是什么?

Path_info是PHP的一种路由模式,需要PHP.ini中设置cgi.fix_pathinfo=1才能开启该路由模式。该路由模式的URL格式为
http://www.xxx.com/index.php/模块/方法。

Path_info的运行机制

Apache容器

那在Apahce容器下,Path_info有什么用呢?

很多防火墙为了提高效率,遇到js,png,jpg等格式的后缀时,则不检测后面参数中是否有非法数据,因此我们可以构造
http://www.admintony.com/index.php/aaa.js?id=union select 1,2,3,4来绕过防火墙进行注入,当然也可以绕过防火墙进行代码执行、命令执行等操作

IIS和Nginx容器

在IIS和Nginx容器下,相比Apache少了一步对文件后缀的检测,因此产生了著名的安全问题CGI解析漏洞(也有称Nginx解析漏洞)。

其漏洞的利用方式就是上传一个含Webshell的图片,然后在图片地址后面加上/a.php使图片当作PHP解析。

比如 123.png/1.php,接收URL后,提取URL中请求的文件1.php,发现不存在就检查是否存在上一级目录,存在就把上级目录当做请求文件,再判断文件是否存在,文件123.png存在,然后就把123.png当做PHP解析执行,其中少了再次检测存在文件的后缀名的操作就直接当做请求最开始文件的类型解析了。

相关推荐

「Python条件结构」if…else实现判断奇偶数

功能要求用户从键盘上输入一个整数,判断该数是奇数还是偶数。说明:能被2整除的整数叫偶数,不能被2整除的叫奇数;即该数除以2后余数为0时该数为偶数,否则该数为奇数。求余数运算符为“%”。实例代码num...

Python if else条件语句详解

前面我们看到的代码都是顺序执行的,也就是先执行第1条语句,然后是第2条、第3条……一直到最后一条语句,这称为顺序结构。但是对于很多情况,顺序结构的代码是远远不够的,比如一个程序限制了只能成年人使用,儿...

python基础篇: python中的流程控制,你都了解吗?

在之前的文章中大致的介绍过python中的流程控制语句,今天通过一些案例来详细了解一下python中的流程语句。目前python中流程控制语句,包含如下,如有遗漏欢迎留言补充。在python中条件判断...

python中if语句

if语句用来判断,当不同的条件成立去做与之对应事情;格式如下:if条件:执行代码条件为True才会去做执行代码布尔类型(bool)说到布尔类型,就像开关只有两个值一样,布尔类型的值只有两个...

python中的循环语句到底难不难

好多初学者会有一种这样的心里:循环难不难?该怎么学习?下面来给大家分析下.Python中的循环语句并不难,但需要理解其核心逻辑和应用场景。以下是针对零基础学习者的清晰解析,通过对比、示例和常见误...

Python6大基础运算符,看完这篇之后会让你有一个彻底认识

昨天我们准备好了Python程序所需要的的东西,那么今天我们开始了解Python的各种基础运算符,这些要是不熟悉下来你后面的路也会走的很艰难Python支持基础运算符,常见的算术运算符有+、-、*、/...

Python基础:条件语句和循环语句

下面会详细讲解一下Python关于条件语句和循环语句,会包含一些示例代码。我们首先来介绍条件语句(if-else),然后再讨论循环语句(for和while循环)。条件语句(if-else)在Pytho...

Python合集之Python循环语句(一)

在上一节的合集中,我们了解了Python流程控制语句中if语句的嵌套及条件表达会的相关知识,本节我们将进一步了解一下Python循环语句中的while语句的相关知识。在日常生活中很多问题都无...

Python“三步”即可爬取,毋庸置疑

声明:本实例仅供学习,切忌遵守robots协议,请不要使用多线程等方式频繁访问网站。#第一步导入模块importreimportrequests#第二步获取你想爬取的网页地址,发送请求,获取网页内...

「Python条件结构」if…else实现三角形判断

功能要求编写程序,判断输入的三个数是否能构成三角形的三个边。如果可以,打印“可以构成三角形”;如果不可以,打印“不可以构成三角形”。构成三角形的条件是:三条边都等于0,且任何2条边的边长之和都大于第三...

Python中检查对象是否具有某个属性的方法

技术背景在Python编程中,经常会遇到需要检查一个对象是否具有某个特定属性的情况。例如,在调用对象的属性之前,需要先确认该属性是否存在,以避免引发AttributeError异常。以下将介绍几种常见...

Python条件语句:从入门到精通

导语条件语句是编程中的基础概念,它允许我们根据不同的条件执行不同的代码块。在Python中,条件语句的灵活性和易读性使其成为编写逻辑判断和流程控制的强大工具。本教程将带您深入了解Python条件语句的...

简单学Python——条件语句if

条件语句是用来判断给定的条件是否满足(表达式值是否为0或False),并根据判断的结果(真或假)决定执行的语句。Python条件语句用的是if或if和else、elif等搭配实现的。代码执行的过程:i...

Python合集之Python跳转语句(一)

在上一节的合集中,我们了解了Python循环嵌套语句的相关知识,本节我们将进一步了解一下Python跳转语句中的break的相关知识。当循环条件一直满足时,程序会一直执行下去,如果希望在中间离开循环...

新手学Python避坑,学习效率狂飙! 八、Python 布尔值判断

布尔值判断系统知识在Python里,布尔类型仅有两个值:True和False,它们常被用于条件判断。下面从几个方面展开介绍:1.布尔运算逻辑与(and):只有当两个操作数都为True时,...

取消回复欢迎 发表评论: