文件上传漏洞
文件上传漏洞的产生与危害
概念
上传文件的时候,如果服务器脚本语言,未对上传文件进行严格的验证和过滤,就有可能上传恶意的脚本文件,从而控制整个网站,甚至服务器。
文件上传检测绕过
upload-labs靶场安装
配置要求如下,要求还是挺苛刻的,下面使用集成好了的环境。
配置项 | 配置 | 描述 |
---|---|---|
操作系统 | windows or linux | 推荐使用windows,除了Pass-19必须在linux下,其余Pass都可以在Windows上运行 |
PHP版本 | 推荐5.2.17 | 其他版本可能导致Pass无法突破 |
PHP组件 | php_gd2.php_exif | 部分Pass依赖这两个组件 |
中间件 | 设置Apache以mouce方式连接 |
解压下面文件
修改网站目录,点击“应用”后,重启Apache
打开靶场
Pass-01(JS绕过)
思路
这个主要是js验证,很容易通过
步骤
保存当前页面,ctrl+s保存
使用编辑器打开页面,修改代码
Pass-02(文件类型验证)
通过下面的代码可以看出,他验证的是文件类型
思路
修改文件类型就可以
步骤
使用bp拦截
修改后,解除拦截
成功破解
Pass-03(黑名单验证)
思路
apache服务器能够使用php解析.phtml.php3
步骤
上传
上传成功,复制图像地址(步骤同前),成功破解
Pass-04(黑名单验证.htaccess)
思路
使用.htaccess(超文本访问)
是许多Web服务器根据目录应用设置的有用文件,允许在运行时覆盖Apache服务器的默认配置。使用.htaccess,我们可以在运行时轻松启用或禁用任何功能。
步骤
-
新建文件.htaccess,并上传,它会把后面上传的loudong.jpg文件后缀,修改为“.php”
<FilesMatch "loudong.jpg"> SetHandler application/x-httpd-php </FilesMatch>
-
把php文件重命名
-
上传成功后,复制图像地址,访问,破解成功
Pass-05(大小写绕过)
思路
代码里面没有验证大写,可以把文件名变成大写
步骤
把文件后缀名修改为.PHP
成功破解
Pass-06(末尾空格)
思路
比上一关少了一行首尾去空的代码
步骤
利用bp,在上传时给文件名加个空格
上传成功,复制图像地址,浏览,破解成功
Pass-07(增加一个.)
思路
由代码可见,只删除一次.
步骤
上传成功,复制图像地址,浏览,破解成功
Pass-08(增加一个::$DATA)
思路
在windows的时候,如果文件名+“:: D A T A ”会把 : : DATA”会把:: DATA”会把::DATA之后的数据当成文件流处理,不会检测后缀名,且爆出::DATA之前的文件名,他的目的就是不检查后缀名。
步骤
放行,上传成功,复制图像地址,浏览
删除地址末尾的::$DATA
成功破解
Pass-09(代码不严谨)
思路
借助的是代码不严谨
deldot,即从字符串的尾部开始,从后向前删除点.,直到该字符串的末尾字符不是.为止。而如果中间有个空格,就不会继续删除。
<?php
include '../common.php';
$file_name = deldot('image.jpg. .');//删除文件名末尾的点
echo $file_name;
?>
步骤
放行,复制图像地址,浏览,成功破解
Pass-10(PPHPHP)
思路
str_ireplace 函数用于字符串替换操作,不区分大小写
其语法是 str_ireplace(find,replace,string,count)。参数 find 必需,规定要查找
的值;replace 必需,规定替换 find 中的值的值;string 必需,规定被搜索的字符
串
<?php
$deny_ext =
array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","js
w","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htacces
s");
$file_name = str_ireplace($deny_ext,"", "info.pphphp");
echo $file_name;
?>
步骤
成功破解
Pass-11(GET 0x00截断)
思路
关键的代码在于这里的’save_path 是一个可控的变量,但是后面还拼接上一个后缀
名,也需要绕过。
个人理解:由于filename需要被检查,所以在上传前,把恶意代码文件的.php后缀改为.jpg,先绕过filename的检查。然后通过抓包修改savepath,添加上正确的恶意代码文件名“info.php”,并通过%00截断后面的filename拼接。
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
关于0x00截断
00 截断是操作系统层的漏洞,由于操作系统是 C 语言或汇编语言编写的,这两种语言
在定义字符串时,都是以\0(即 0x00)作为字符串的结尾。操作系统在识别字符串
时,当读取到\0 字符时,就认为读取到了一个字符串的结束符号。因此,我们可以通
过修改数据包,插入\0 字符的方式,达到字符串截断的目的
save_path=../upload/
filename="loudong.jpg"
智榜样
正常情况:../upload/loudong.jpg
save_path=../upload/1.php%00
filename="loudong.jpg" 拼接的路径为:../upload/1.php%00loudong.jpg :由于%00 当作结尾,故最终保存的文件
为../upload/1.php
步骤
- 把恶意代码文件的.php后缀改为.jpg,先绕过filename的检查
- 然后通过抓包修改savepath,添加上正确的恶意代码文件名“info.php”,并通过%00截断后面的filename拼接。
-
查看upload路径下的文件,恶意代码文件成功上传
-
成功破解
Pass-12(Post 0x00截断)
思路
GET 型提交的内容会被自动进行 URL 解码,在 POST 请求中,%00 不会被自动解码
个人理解:由于post不会自动解码%00,所以需要在bp手动先对%00进行解码,其它步骤与GET截断一致
步骤
上传成功,复制图像地址,浏览,成功破解
Pass-13(图片木马-读取文件前两行内容)
这个案例会验证上传内容,确认是图片格式,所以不能简单把 php 转化为 jpg,需要使用图片木马。
思路
需要在正常图片里面加入恶意代码。
步骤
-
准备一张正常图片,和一个恶意代码文件
-
cmd,进入命令行
-
执行命令
copy image.png /b + info.php /a webshell.png
-
可以看到该目录下多了一个图片
-
用notepad++打开图片,可以看见恶意代码被添加了进来
-
正常上传图片,复制上传的图片地址
-
进入漏洞
-
在url末添加上传图片的地址
出现乱码,不要慌,是正常的图片解析,破解内容在页面下方,页面往下拉即可
破解成功
只成功上传了png的图片,gif的出问题
Pass-14(图片木马–绕过getimagesize() 函数)
getimagesize() 函数用于获取图像大小及相关信息,成功返回一个数组,失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息
步骤
和pass-13一致。
Pass-15(图片木马–绕过**exif_imagetype()**函数)
PHP 中的 **exif_imagetype()**函数用于确定图像的类型。此函数读取给定图像的第一个字节并检查其签名.
当找到正确的签名时,则 exif_imagetype()返回适当的常量值;否则它返回 False。
步骤
和Pass-13一致
Pass-16(二次渲染绕过)
这个案例使用的是 imagecreatefromjpeg、imagecreatefrompng、imagecreatefromgif
三个不同的方法来验证不同的文件,绕过格式不正确,会报出异常
思路
个人理解:先将通过copy方式植入木马的图片上传,若发现植入的木马无效,将上传后的图片从服务器中下载下来。
通过010 Editor 对比上传前和上传后图片的区别,在没有发生改变的像素位置上添加木马,实现木马植入。
但这题重新渲染了图片,图片实际已经被删除了
这个案例建议使用 gif 的文件来上传木马,gif 最高支持 256 种颜色。由于这种特性,重新渲染
改动不会太多!
步骤
-
安装010 Editor
-
上传插入木马的gif图片,步骤与pass-13一致
-
将上传前和上传后的图片在010-Editor进行对比,在相同的位置添加木马
-
破解成功
Pass-17(条件竞争)
这个是白名单验证,unlink 函数是删除文件,rename 函数进行文件的移动(也会删除源
文件),注意这个代码可以借助文件包含漏洞,但这个代码明显不允许使用了
但仔细看这段代码,是不管什么文件都能传,但不管是否图片,后门都删除,可以考
虑条件竞争
就是没删除之前,如果文件是打开的状态,可能删除失败,这样就能保留原理的文件
思路
个人理解:由于无论上传什么文件都会被移动路径,相当于文件会在很短的时间内被删除,所以,要在更短的时间内进入到破解页面。故使用bp进行持续爆破。
步骤
1.上传info.php文件,利用bp进行拦截,修改文件名,在末尾加一个空格,选中空格进行爆破
-
进入爆破模块,选中空格,添加标记
-
进入载荷选项,选择“无载荷”类型,选择持续攻击,start attack
-
浏览器进入localhost/upload/info.php进行不断刷新,频繁访问地址,直到出现破解的页面,破解成功
Pass-18(解析漏洞)
后台代码一看就是白名单,只允许上传这里面的文件,所以不能传 php 等文件
文件上传之后又对其进行了重命名,不能使用文件包含的漏洞
结合 apache 的解析漏洞,考虑 apache 未知扩展名解析漏洞
不管最后后缀为什么,只要是.php.*结尾,就会被 Apache 服务器解析成 php 文件!
这里是先移动文件,再修改文件名,所以的话是存在利用条件竞争。
步骤
-
复制一个文件,后增加后缀7z
-
上传该文件,bp拦截,发送到爆破模块,文件名末尾添加空格,并对空格进行标识
-
进入载荷选项,选择无载荷类型,选择持续爆破,start attack
-
上一步骤和pass-17似曾相识,下一步频繁访问也是一样,但要注意访问的地址是怎样的(根据地址与文件名拼接进行猜测,或者到服务器目录观察是哪个目录)
-
持续访问,破解成功
-
Pass-19(黑名单)
这个题目使用的是黑名单,并且文件名是可以控制的
方法1 步骤
使用前面讲的 0x00 截断
文件上传后保存的是 php 文件
方法2 步骤
如果文件名
upload-19.php/.
那么验证的是 php/.可以验证通过
破解成功
Pass-20(白名单)
<?php
$fileName = array("upload-20","jpg");
$ext = end($fileName);
echo $ext."</br>";
$f = reset($fileName);
echo $f;
echo "</br>------------------------------</br>";
//$fileName = array("upload-20.php",null,"jpg");
$fileName = array();
$fileName[0] = "upload-20.php";
$fileName[2] = "jpg";
$ext = end($fileName);
echo $ext."</br>";
$f = reset($fileName);
echo $f;
echo "</br>";
$real_name = reset($fileName). "." . $fileName[count($fileName) -1];
echo "</br>------------------------------".$real_name;
?>
end() 函数将数组内部指针指向最后一个元素,并返回该元素的值,所以这个函数可以接受数组的reset() 函数将内部指针指向数组中的第一个元素,并输出,所以这个函数也可以接受数组的count() 统计数组有多少个元素
既然可以接受数组save_name[0]=upload-20.php
save_name[2]= jpg
这行代码拼接的名字为
upload-20.php+“.” +save_name[1]的数据
由于 save_name[1]没有,结果为 upload-20.php.
思路
个人理解:利用数组特性,该题是通过数组拼接文件名,利用count函数不记空数组的特性,使数组【0】存放文件名“upload-20.php”,数组【1】存放“null”,数组【2】存放【后缀】,那么count检查数组内容数为“2”,2-1为1,那么程序只会将数组【0】和数组【1】的内容拼接成新的文件名,也就是“upload-20.php”.
步骤
-
上传假图片(实际内容是info.php),使用bp拦截
-
bp放行,复制图像地址访问,破解成功