pass11(双写绕过)
查看源码:
1 | if (file_exists(UPLOAD_PATH)) { |
我们发现了新代码
1 | $file_name = str_ireplace($deny_ext,"", $file_name); |
- 这行代码使用
str_ireplace()
函数尝试从文件名中移除数组$deny_ext
中列出的所有扩展名。
我们可以想到双写来绕过。
当我们把文件后缀设置为**.pphphp**,中间的php会被删除,留下**.php**,这样我们就上传成功了。
空字符
0x00,%00都是空字符,0x00是编程语言中使用的,%00是在url编码中使用的,他们的作用是截断字符串,例如“up0x00load”,系统在读到0x00时自动停止,那么读取到的只剩下“up”。
pass12(%00绕过)
查看源码:
1 | if(isset($_POST['submit'])){ |
我们发现文件的保存路径是可以被修改的,我们可以想到用%00(因为这里的路径是通过get方法获取的)将$img_path = $_GET[‘save_path’]后面的代码给截断掉,这样我们就可以任意修改文件名了。
不过这需要php版本低于5.3
pass13(0x00)
这关是用post方法传输的,我们抓包完发现可以在请求体中修改路径,不过我们这里不能直接在后面加上0x00,因为php并不会把0x00解释为空字符并停止读取,我们可以在后缀名之后加个空格或者随便加个字符,再把他改为16进制为0的字符,这样就会被识别为空字符以截断$img_path = $_GET[‘save_path’]后面的语句。
这也需要低版本php
pass14(字节标识符绕过)
字节标识符(文件头)是指文件最开始的几个字节,用于标识文件类型。
常见的如下:
- JPEG 图像文件
- 字节标识:
FF D8 FF
- 字节标识:
- PNG 图像文件
- 字节标识:
89 50 4E 47 0D 0A 1A 0A
- 字节标识:
- GIF 图像文件
- 字节标识:
47 49 46 38 37 61
(GIF87a) 或47 49 46 38 39 61
(GIF89a)
- 字节标识:
- PDF 文件
- 字节标识:
%PDF-
(ASCII 字符串,通常后跟版本号)
- 字节标识:
我们查看本关的源码:
1 | function getReailFileType($filename){ |
这是用来检测图片前俩个字节是否是jpg,png,gif的标识符的代码。
我们利用vscode中的hex editor将木马文件的前两个字节改为89 50
可以看到它已经被识别为png文件,这时候我们需要用到文件包含漏洞来使得这个文件能被解释为php文件。
这里是通过get方法获取文件来进行包含。由于include.php在我们上传的木马的上一级目录,我们需要这样
这时include.php文件便可以包含并以php解释我们的木马。
我们再用蚁剑测试可以连接成功。
pass15(图片马)
查看源码:
1 | function isImage($filename){ |
getimagesize($filename)
函数获取图像文件的相关信息,包括图像的宽度和高度,以及一个表示图像类型的常量(=1,2,3…)。image_type_to_extension()
函数将getimagesize()
返回的图像类型转换为对应的文件扩展名。
我们修改它的文件头为47 49 46 38即gif,再用文件包含漏洞,便能成功连接。
pass16
和15关差不多,不过检测函数变成了exif_imagetype()它只会检测图片类型,不会检测高宽什么的。
less17(二次渲染)
查看源码发现有新函数
1 | $im = imagecreatefromjpeg($target_path); |
imagecreatefromjpeg()
:这是PHP中的一个内置函数,用于从JPEG文件创建一个新的图像资源。该函数读取指定的JPEG文件,并返回一个图像标识符,代表了一幅图像,可以用于进一步的图像处理。
当然不止重新生成jpeg的,还有别的,问题就是重新生成后文件中的一些内容会被改写,我们的木马就可能被改写,因此我们要在不会被改写的地方写入我们的一句话木马再用文件包含漏洞进行上传shell。这里我们用最简单的gif二次渲染,别的图片可以查看这个博客【文件上传绕过】——二次渲染漏洞_二次渲染绕过-CSDN博客
这是在未改写区修改后的图片,上传后发现还在
我们再利用文件上传漏洞
成功。
less18(条件竞争)
查看源码
1 | if(isset($_POST['submit'])){ |
原理
发现服务器先通过move_uploaded_file()将文件保存到指定路径再来判断后缀名是否相符。这时文件是会在服务器上先存在一定的时间的,我们这时在访问这个文件(这个文件会生成一个含有一句话木马的文件),只要在文件还存在的时候访问,这样木马便会生成在upload目录下。
我们需要用到bp来进行不断发送与访问文件。且只有一定的几率成功。
less19(apache解析漏洞+条件竞争)
apache解析漏洞
apc是从又往左读取文件名的,如果一个文件shell.php.*,其中的 *是apc不能解析的后缀,那么他就会往前读也就是以php的形式解析。
思路
查看源码可知
1 | $ret = $this->move(); |
这关的文件移动是在文件检查之前,在文件重命名之后,那么我们可以利用条件竞争在文件被重命名之前访问shell.php.7z,这样就有机会在upload目录下生成木马,不过复现只是有概率成功,主要看服务器处理的速度与请求发送的速度。
less20
查看源码
1 | if (isset($_POST['submit'])) { |
发现我们可以自定义文件名,且只有黑名单过滤,且没有条件竞争。我们可以利用user.ini,点加空格加点,加点,::$DATA,apc解析漏洞,不过这些都要注意php或者apache版本不能太高。
less21
看源码:
1 | if(!empty($_FILES['upload_file'])){ |
首先,判断文件的Content-Type
类型是否在白名单中
如果POST
接收的save_name
为空,则赋值为$_FILES['upload_file']['name']
,不为空就为本身
if (!is_array($file))
- 这一行检查变量$file
是否不是数组。如果$file
不是数组,那么花括号内的代码将会被执行。
explode()
函数把字符串根据**”.”**打散为数组.
end()
函数将 array
的内部指针移动到最后一个单元并返回其值reset()
函数将 array
的内部指针倒回到第一个单元并返回第一个数组单元的值count()
函数计算数组中的单元数目或对象中的属性个数
重点是 $file_name = reset($file) . '.' . $file[count($file) - 1];
是根据flie数组的第一个和数组元素-1个的元素命名的,那么我们可以让file[0]=shell,file[2]=php,file[3]=jpg,这样3-1=2,file[2]就是我们想要的php后缀。
上传成功。