文件上传漏洞浅析

文件上传漏洞的定义

文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。这种攻击方式是最为直接和有效的,“文件上传” 本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。如果服务器的处理逻辑做的不够安全,则会导致严重的后果。

上传漏洞的原理

大部分的网站和应用系统都有上传功能,一些文件上传功能实现代码没有严格限制用户上传的文件后缀以及文件类型,导致允许攻击者向某个可通过web访问的目录上传任意PHP文件,并能够将这些文件传递给PHP解释器,就可以在 进程服务器上执行任意PHP脚本。

当系统存在文件上传漏洞时攻击者可以将病毒,木马,WebShell,其他恶意脚本或者是包含了脚本的图片上传到服务器,这些文件将对攻击者后续攻击提供便利。根据具体漏洞的差异,此处上传的脚本可以是正常后缀的PHP,ASP以及JSP脚本,也可以是篡改后缀后的这几类脚本。

文件上传的一些基础知识

文件上传的过程

客户端 选择发送的文件->服务器接收->网站程序判断->临时文件->移动到指定 的路径

文件上传返回值

0:上传成功

1:上传的文件大小超过了php.ini限制

2:上传文件大小超过了HTML表单的限制

3:只有部分问文件被上传

4:没有文件被上传

Webshell的分类

分类 体量 特点
大马 体积大,包含很多功能 通常会包含调用系统的关键函数,所以通常会加密代码用来隐藏。
小马 体积小,通常只包含文件上传功能 通常会包含调用系统的关键函数,所以通常会加密代码用来隐藏。
一句话木马 代码极短(只有一行) 使用方便,可以单独作为一个文件,也可以插入其他正常文件中;变形多,难以查杀。

常见的上传绕过

https://blog.csdn.net/beijimao_/article/details/127002057

https://www.freebuf.com/articles/web/179954.html

https://www.freebuf.com/vuls/279171.html

https://www.freebuf.com/articles/web/265245.html

总结一下,有这么几点

绕过前端JS检测上传文件

有些网站会通过前端JS对上传的文件进行一个检测,这些数据没有经过目标服务器,是可控的,对于前端JS检测有很多绕过的方法:

1、禁用浏览器JS功能

2、F12删除对应的规则

3、Burp等工具抓包

绕过contnet-type检测

有些网站在上传文件时会检测HTTP请求的请求头中的contnet-type,通过用Burp等软件进行抓包并修改请求头中的contnet-type就可以实现文件上传。

黑名单绕过

有些网站在上传文件时会获取文件的后缀名并将其与黑名单进行比对,如果攻击者的文件后缀名在黑名单中则上传文件会被拦截。

对于黑名单我们只需要将文件后缀名改成不在黑名单内的即可(黑盒情况下一个一个试),例如php1、php2、php3、phtml、ashx、phP等等

使用.htaccess绕过

简介

假如网站的黑名单设置的很全面,将所有可用后缀名(如.phtml)都屏蔽了,我们可以尝试上传.htaccess来实现绕过。

htaccess 文件的作用是可以帮我们实现包括:文件夹密码保护、用户自动重定向、自定 义错误页面、改变你的文件扩展名、封禁特定 IP 地址的用户、只允许特定 IP 地 址的用户、禁止目录列表,以及使用其他文件作为index文件等一些功能。在 htaccess 里写入 SetHandler application/x-httpd-php 则可以将文件重写成php文 件。要htaccess的规则生效则需要在apache开启rewrite重写模块,因为apache是多数都开启这个模块,所以规则一般都生效。

原理

在Apache里,.htaccess是一个配置文件。它可以用来控制所在目录的访问权限以及解析设置。可以通过修改该文件的配置项,该目录下的所有文件作为php文件来解析

.htaccess可以写入apache配置信息,改变当前目录以及子目录的apache配置信息。

应用场景

黑名单没有禁止.htaccess文件上传。

服务端允许.htaccess文件生效,需要在httpd.conf中,修改两处配置项:

  • Apache加载rewrite模块

    LoadModule rewrite_module modules/mod_rewrite.so

  • AllowOverride All(默认为None)

绕过方法

绕过方法:首先上传一个.htaccess文件,.htaccess文件内容如下。如果Apache允许.htaccess文件生效,并且.htaccess文件没有被重命名。那么就可以改变当前目录以及子目录的Apache配置信息,将其他后缀的文件作为PHP文件解析。

.htaccess文件中有两种写法

<FilesMatch "xxx.png">
SetHandler application/x-httpd-php
</FilesMatch>

xxx.png即可作为php脚本解析

或者是

AddType application/x-httpd-php .gif

.gif为后缀额度文件都当做php解析

.user.ini绕过

应用场景

  • 服务器脚本语言为PHP,并且使用CGI/FastCGI模式,php版本>5.3.0
  • 上传目录下要有可执行的php文件

.user.ini,它会影响php.ini中的配置,从而将指定的文件内容按php来解析,影响的范围该文件所在的目录以及子目录。需要等待php.ini中的user_ini.cache_ttl设置的时间或重启Apache才能生效,且只在php5.3.0之后的版本才生效。.user.ini.htaccess用的更广,不管是nginx/Apache/IIS,只要是以fastcgi运行的php都可以用这个办法。如果使用Apache,则用.htaccess文件有同样的效果。

注意:.htaccess只能用于Apache。

php.ini中,有两个新的INI指令

; Name for user-defined php.ini (.htaccess) files. Default is ".user.ini"
; 用户自定义的php.ini文件的名字,默认是.user.ini
user_ini.filename = ".user.ini"

; TTL for user-defined php.ini files (time-to-live) in seconds. Default is 300 seconds (5 minutes)
; 重新读取用户INI文件的时间间隔,默认是300秒(5分钟)
user_ini.cache_ttl = 300

大致意思是:我们指定一个文件(如,xxx.jpg),那么该文件就会被包含在要执行的php文件中(如index.php),类似于在index.php中插入一句:require(./xxx.jpg);

这两个设置的区别只是在于auto_prepend_file在文件前插入auto_append_file在文件最后插入(当文件调用exit()时该设置无效)。

利用方法:

可以上传一个这样的.user.ini

auto_prepend_file = xxx.jpg

然后再上传一个图片马xxx.jpg

<script language='php'>system('whoami');</script>

如果在上传目录中还有一个可执行的php文件,访问php文件,就达到了执行系统命令的效果。

总结一下:上传目录中有一个可执行的php文件,我们先上传一个.user.ini文件,这个文件的内容为auto_prepend_file=xxx.jpg起到的作用相当于在可执行的php文件前插入图片马中的内容。然后图片马中的恶意代码也会被当做PHP解析。

大小写绕过

有的限制条件没有严格过滤大小写,可以通过更改大小写进行上传,如php可以改为PHP、Php、pHp等后缀,即可绕过上传

空格绕过

如果有的网站没有对上传的文件进行首尾去空处理,那么在传输过程中抓包,将文件名的后面接入一个空格即可实现上传。

加点绕过

有的网站不会对文件后缀名后面的点进行过滤,可以抓包加点进行绕过。

利用系统特征绕过

Windows后缀忽略:在Windows中文件后缀名.系统会自动忽略。所以shell.php. 和shell.php被系统认为是一样的。所以可以在上传时抓包后文件名后面加上.绕过。

Windows叠加特征:在windwos中如果上传文件名ant.php:.jpg 的时候,会在目录下生产空白的文件名ant.php

再利用php和windows环境的叠加属性,

以下符号在正则匹配时相等:

双引号" 等于 点号.

大于符号> 等于 问号?

小于符号< 等于 星号*

文件名.<或文件名.<<<或文件名.>>>或文件名.>><空文件名

NTFS交换数据流绕过

抓包在文件名后面加入::$DATA进行绕过

双写绕过

有的网站会自动删除后缀中的敏感内容(如a.php会变成a.),这时候可以对文件后缀进行双写,比如.php写成.pphphp这样网页再过滤的时候自动就删除了中间的php,最后得到的是一个.php文件。

(右手就行)

. .绕过

有的网站之过滤一次空格和.所以可以用.空格.来绕过。

目录可控%00 截断绕过

上传参数可控时当gpc关闭的情况下,可以用%00对目录或者文件名进行截断。

POST%00截断绕过

有些网站使用POST传参,这样我们直接修改路径是无效的,需要修改路径后使用urldecode(burpsuit右键菜单中自带)转码后再传参方可使用。

配合解析漏洞

Apache HTTPD 换行解析漏洞(CVE-2017-15715)

Apache HTTPD是一款HTTP服务器,它可以通过mod_php来运行PHP网页。其2.4.0~2.4.29版本中存在一个解析漏洞,在解析PHP时,1.php\x0A将被按照PHP后缀进行解析,导致绕过一些服务器的安全策略。

Apache HTTPD 多后缀解析漏洞

pass

Nginx 解析漏洞IIS7.5解析漏洞IIS6解析漏洞日后再看

绕过文件头检查

上传具有正常文件头的图片马即可。

gif的文件头为GIF89a。png的文件头为89504E47。jpg的文件头为FFD8FF

此时如果不存在上述的漏洞,只能上传图片格式的后缀,还需使用文件包含漏洞运行图片马中的恶意代码。

突破getimagesize()

getimagesize()函数会返回一个数组,其中下标2是图像的类型。1=GIF,2=JPG, 3=PNG。这里上传一个正常图像后缀的图片马,使用文件包含漏洞运行图片马中的恶意代码即可。

突破exif_imagetype()

exif_imagetype() 判断一个图像的类型。检查图像的第一个字节。可能返回的常量有IMAGETYPE_GIF=1IMAGETYPE_JPEG=2;MAGETYPE_PNG=3;文件头不正确返回false。

上传具有正常文件头的图片马即可。

gif的文件头为GIF89apng的文件头为89504E47jpg的文件头为FFD8FF。然后使用文件包含漏洞运行图片马中的恶意代码。

二次渲染

gif:找到渲染前后没有变化的位置,将PHP代码写进去。

png:写入IDAT数据块

使用脚本生成图片马

<?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,'./idat.png');
?>

可以看到,在IDAT数据块中,有一句话木马:<?=$_GET[0]($_POST[1]);?>,这里利用了PHP中的短开标签。

注意:使用短开标签,需要在php.ini中,将short_open_tag=On

jpg:未测试成功。

MIME检查

MIME类型是描述消息内容类型的因特网标准。

HTTP头部的Content-Type字段的内容就是MIME类型。

只需要将MIME类型修改为白名单中允许的类型即可。

比如,图片上传点,允许上传gif、jpeg、png。用Burp抓包,将HTTP头部的Content-Type字段内容修改为:

Content-Type: image/gif`或`Content-Type: image/jpeg`或`Content-Type: image/png

%00截断

%00是chr(0),空字符。

程序会把%00当做结束符,后面的数据直接忽略掉

在文件上传中,利用%00截断,在文件扩展名验证时,是取文件的扩展名来验证,但是最后文件保存在本地时,%00或截断文件名,只保存%00之前的内容。

应用场景:白名单、上传路径可控、php.ini中的magic_quotes_gpc为off

利用方式

如果上传文件的路径为:用户可控的上传路径/随机数.白名单中的后缀

正常情况下,服务器拼接得到的上传路径为:

$img_path = ../upload/5920201223231032.gif;

而用户在可控的上传路径中,使用%00截断后,拼接得到的上传路径为:

$img_path = ../upload/xxx.php%00/5920201223231032.gif

对后缀进行白名单检测,为gif。但是保存在服务器上的文件,却是xxx.php,因为%00之后的内容被截断了。

0x00截断

条件:php版本<5.3.4、php.ini中的magic_quotes_gpc设置为off、上传路径可控、白名单

利用方式:

如果上传文件的路径为:用户可控的上传路径/随机数.白名单中的后缀

正常情况下,服务器拼接得到的上传图像地址为$img_path =../upload/5920201223231032.gif

但是,用户如果在可控上传路径中写入一个php后缀,并且php后缀后面有一个0x00字符

服务器拼接得到的上传图像地址会变为$img_path =../upload/xxx.php[0x00]/5920201223231032.gif

对后缀进行白名单检测,为gif。但是保存在服务器上的文件,却是xxx.php,因为0x00之后的内容被截断了。

0x0a截断

与上文同理

posted @ 2024-02-03 21:12  TLSN  阅读(134)  评论(0编辑  收藏  举报