upload-labs通关详解
upload-labs通关详解
一、Pass-01
查看源码,发现变量前有var,可以代码语言是JS
substring():裁剪字符串
lastIndexOf():返回某个子字符串在字符串中最后出现的位置
var ext_name = file.substring(file.lastIndexOf("."));的含义为把"."和"."后面的字符串裁剪出来放到ext_name中
方法1:
由代码可知是JS语言且为前端验证,可以直接禁用JS直接上传php文件
方法2:
上传一个普通图片,使用burp抓包,修改图片内容和文件后缀
打开图像地址,输入参数phpinfo验证是否执行木马
二、Pass-02
由源码可知,代码语言为PHP,且此题判断MIME类型
只需要使用burp修改Content-Type即可成功上传
三、Pass-03
查看代码,此题为黑名单过滤
array():数组
trim():删除首尾的空
deldot():删除文件名末尾的点
strrchr():用某一字符去分割字符串,本题为用"."分割文件名获取后缀名
strtolower():转为小写
str_irplace():替换,本体为把文件名中的"::$DATA"替换为空
修改文件名,直接上传即可
四、Pass-04
代码和上一题差不多,只是增加了黑名单的内容
我们可以上传htaccess,通过h来指定某个后缀名用php引擎解析(Apache特性)
此.htaccess的作用:让服务器访问当前目录下的文件时,遇到app后缀文件就使用php的引擎去解析并执行
先上传shell.app文件,成功后可以打开图片地址,但它内部的一句话木马并不会执行被当作php脚本执行,而是直接展示出来
之后再上传.htaccess文件,刷新图片地址,一句话木马就可以执行了
五、Pass-05
这道题是针对Nginx环境的题目,但此靶场用的是Apache环境,所以这里就不涉及了
六、Pass-06
由源码可知,这一关没有强制将大写转换为小写,所以我们可以上传纯大写或者大小写结合的后缀名
修改文件名为纯大写,直接上传即可
七、Pass-07
查看源码,发现和前面相比缺少了trim()【首尾去空】,可尝试用空格绕过
【strrchr()用点去分割时,分割到了.php 的内容,但.php 并不在黑名单中于是上传成功,又因为在存储文件时windows会自动去除文件名末尾的空格,所以就只剩下了.php】
先用burp拦截,在文件名的后缀后面加上空格后发包,即可上传成功
八、Pass-08
此题没有了删去末尾的点,我们可以利用windows自动去除文件名后缀后面的点这一特性进行绕过
先上传shell.php,使用burp拦截,在后缀后面加上点
发包即可成功上传
九、Pass-09
此题缺少了把"::$DATA"替换为空,那么我们就可以使用burp拦截并在后缀后面加上”::$DATA“发包即可成功上传(访问图片地址时要去掉”::$DATA“)
::$DATA为NTFS文件流的特性,其表示为文件内容本身,大部分windows系统都是NTFS文件系统
十、Pass-10
此题为代码逻辑的问题,先删除首尾的空格(如,asdad a ,其只会删除a后的空格变成asdad a),然后删除文件名末尾的点(如a. .删除末尾的点后变成a. ),所以我们可以构造一个特殊的后缀(根据代码反着来),使其经过删除后还能保留一些东西
构造好的后缀:xxx.php. .
先经过首尾去空(首尾没有空)——>xxx.php. .——>去除末尾的点——>xxx.php. ——>首尾去空——>xxx.php.
获取到的文件名后缀为.php.,并不在黑名单中,而windows在复制或移动文件时自动去掉后缀名中的“.”,后缀名就变为了php
使用burp拦截,更改后缀名
发包,成功绕过
十一、Pass-11
由代码可知,此题将文件名后缀与黑名单匹配,若在黑名单中则替换成空
看到replace,尝试双写绕过
两种双写:pphphp和phphpp,文件读取是从左往右读取,后者会直接读取到php然后删除
我们直接双写文件名后缀然后上传,即可成功
十二、Pass-12
计算机存储字符串是通过其结尾的结束符(00)来分辨是否结束读取(如,8023占5个空间,包含了一个结束符),这也是截断漏洞的产生原因
substr(被裁剪的字符串,从哪个位置开始裁剪)
strrpos(待寻找的字符串,要寻找的字符):在字符串中寻找某个字符并返回它的位置
由代码可知,此题为白名单
我们先上传一个jpg文件,开启burp拦截,然后修改save_path
发包,复制图片地址,成功访问(去掉php后面的东西)
save_path拼接原理:
%00为url编码,但服务器接收的是一个ASCII码为00的字符(字符串结束符)
所以把"../upload/xxx.php[]/5520230110152511.jpg"传进去后,系统保存时要读取变量,当读取到php后的字符串结束符时会认为文件名已读完,从而把文件存储为"../upload/xxx.php"【jpg后面本身也有一个字符串结束符】
十三、Pass-13
代码和Pass-12基本完全一样,只是把GET请求换成了POST请求
我们可以上传一个图片抓包验证一下
我们可以看到save_path在POST请求中
这样就不能和Pass-12一样直接在路径后面加上xxx.php%00绕过了(%00为URL编码,只能在GET请求中使用,在POST请求会把%00的三个ASCII码而不是一整个字符串结束符发送给服务器)
那么我们可以先上传jpg文件,用burp拦截,然后在路径后写上yyy.php,并在后面随便输入一个占位符(如:#,ASCII码为23或空格,ASCII码为20)
使用Hex模块,找到路径位置,修改#的ASCII码为00,使其变为字符串结束符
此时,回到Raw模块,我们就可以看到php后面有个像空格而不是空格东西
发送数据包即可成功上传,删除截断后的内容即可成功访问图片地址
十四、Pass-14
点击文件包含漏洞,查看代码
$file = $_GET['file'];含义为:把用户使用get请求传输的file参数赋值给新定义的变量file,然后判断用户 是否为file,若不是file则显示源代码(当前页面);若是,则包含此文件
再查看源码
$bin = fread($file, 2);含义读文件的两个字节,用来判断文件头是否是真的图片文件(每一个图片的文件头都是固定的,如ping的开头为GIF89a)
所以,我们需要制作一个图片码
上传制作好的图片码,利用文件包含漏洞去包含我们上传的图片码即可成功执行
十五、Pass-15
$info = getimagesize($filename); 含义为获取图片大小(像素信息),若是php文件重命名为图片文件,是没有像素、尺寸等信息的
所以我们可以继续使用图片码来绕过
操作同Pass-14
十六、Pass-16
$image_type = exif_imagetype($filename);检验图片的扩展信息,如下图所示
本题通过exif信息来检测是否为图片文件,那么我们依旧可以使用图片码来绕过
操作同Pass-14和Pass-15
十七、Pass-17
此题使用了imagecreatefromjpeg()二次渲染(可以理解成将上传的图片再另存为一份,虽然图片一样,但内部信息会有所不同),所以图片码中的php脚本会消失
jpg内容少,php代码无论插入哪个位置都容易被压缩掉;png有严格的格式(每隔几位都有校验)【这两个都可以插入,但是要特别精细,需要第三方软件的帮助】
所以我们选择gif插入php语句
上传一个gif文件,开启burp拦截并且插入php代码(在中间偏下的位置)
发包后,图片底色变绿,说明没有什么问题
使用文件包含,成功执行
十八、Pass-18
此题为条件竞争漏洞
unlink():删除
由代码可知此题整个上传的流程为:①把文件移动到web可访问的目录②判断文件是否合法,合法则重命名,不合法则删除
但是此逻辑存在问题,在把文件移动到web可访问的目录到删除非法文件之间的时间里,我们是可以访问非法文件的(此时文件还在验证或还没删除),于是就可以利用这个时间差进行攻击
因为我们上传的文件是一个不持久的文件,无论怎样其只能存在很短的时间(不到1ms),若用这1ms去提交一个请求,那完全是可以的,但要是想用蚁剑或菜刀进行连接,我们就需要一个稳定的,可持续化的连接(有一个持久的文件放在服务器上供我们访问),但因为由过滤存在,只要是不合法文件,最后必然会被删除,我们只能尽量去延长其存在的时间(ms级别的延长),于是我们可以制作一个生成木马的木马
例如,上传一个生成木马的木马gen.php,我们在文件移动到删除的时间差里访问该木马,其就会输出一个shell.php放到服务器中,那么此时时间线向后推移,服务器开始删除非法文件,但服务器删除的是gen.php(因为用户上传的是gen.php,而前面验证的也是gen.php,也就是说gen.php生成的shell.php是排除在时间线之外的,不参与整个程序的逻辑,前面所有流程,上传、移动、验证、删除都是针对gen.php的),于是我们就可以通过gen.php获取持久化的连接
解决了持久化连接的问题,我们还需要解决如何快速触发gen.php的问题(尽快、频繁的访问,也可以尽快、频繁的上传【发包】)
首先,制作生成木马的木马
然后我们可以使用burp抓包(访问和上传两个包),发送到攻击器,从而达到频繁访问/上传
上传gen.php,此时提示上传失败(说明文件已经通过了流程,并进行了最后一步的删除)
再上传一个jpg,访问其图片地址,但要把文件名改为gen.php,从而获取访问gen.php的数据包
把这两个包发送至攻击器
不需要变量(清空),设置no payload,只需要提交请求即可(两个都这么设置)
修改线程数(拉高)
开始爆破(先上传后访问)【可能不能一次成功,多尝试几次】
根据长度排序(状态码排序找不出),找到成功上传
将图片地址改为shell.php即可访问
十九、Pass-19
require_once()为文件包含:在一个文件中引入另一个文件
require_once("./myupload.php");含义为在index.php中引入 myupload.php
由代码可知,此题有后缀名检查的白名单(checkExtension),可以考虑截断/解析漏洞
并且可由代码看到上传的流程:检查后缀名——>移动——>重命名
所以,此题可以使用Apache解析漏洞(因为没有用户可控的文件名和路径,所以不能用截断)
我们需要找到一个在白名单中,但Apache不识别的后缀名(如7z和rar),进行尝试
先上传一个jpg找到重命名规则,访问图片地址,发现文件名被重命名为一个随机数
所以我们只有在移动和重命名之间访问才能触发解析漏洞,那么此题也是条件竞争【Apache解析漏洞+条件竞争的综合利用】,和Pass-18差不多
首先使用burp抓两个包(上传gen.php.7z和访问gen.php.7z)发送至攻击器
其余设置同Pass-18
此题成功率较高,访问大部分都是200(因为代码较长,执行时间比Pass-18长),与Pass-18相反
上传成功,访问shell.php
二十、Pass-20
$file_name = $_POST['save_name'];含义为获取文件名
$file_ext = pathinfo($file_name,PATHINFO_EXTENSION);含义为取后缀名
此题也是截断漏洞
看到文件路径和文件名是可控的,首先要想到截断漏洞!!!
我们可以在保存名称处同Pass-12、Pass-13一样,设置截断
开启burp拦截,上传一个jpg文件(保存名称随意),在burp中修改保存名称
在Hex模块中修改占位符为00
回到Raw中,可以看到修改成功
发送数据包即可成功上传
二十一、Pass-21
$file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];含义为:若用户没有使用post表单定义文件名,则使用文件本身的文件名;若提交了名称,则用提交的名称赋值
explode():把字符串用某一字符打散,如:‘aaa.bbb.ccc’——>【‘aaa’,‘bbb’,'cc'】
end():取末尾元素
reset():取开头元素
count():计算数组中元素个数
此题使用了MIME和后缀名白名单,且通过拼接无法使用Apache解析漏洞
开启burp拦截,上传shell.jpg
将下图的内容复制一份
修改内容
发送数据包即可成功上传
因为我们上传的是jpg文件,所以一开始的MIME验证就已经绕过了
检查文件名和:若用户提交的save_name为空,则用文件名;若不是空,则用用户提交的save_name,而我们提交了save_name[0]
接下来判断数组,很明显save_name[0]是数组(只有数组才有下标),所以没有用”.“打散
而在上图中,我们可以看到,我们给数组0号元素赋值为webshell.php,2号元素赋值为jpg,所以上传上去的数组内容是[‘webshell.php’, ,'jpg'](没有上传1号元素)
然后end()取文件末尾元素(后缀名)jpg,通过判断jpg符合白名单
reset()取头元素webshell.php,加上一个”.“,count()计算数组中的元素个数为2,然后$file[count($file)-1]取数组的第一个元素(空),所以此时存在服务器的文件名为webshell.php.,而windows会自动把最后的点去掉,那么最后剩下一个webshell.php
于是我们就通过数组的特性来绕过本题的过滤