简述
因为主要是初学者学习相关知识点,而不是为了练手,所以基本先看提示,提示不行了,再看源码。
预备知识
提交的MIME 类型只是客户告知服务器应该怎样处理,服务器完全可以无视。而响应的 MIME 是告知 浏览器应该如何显示。提交的 MIME 是浏览器通过上传文件的后缀名推导出来的。
特殊点:
-
.user.ini 与 .htaccess 当上传文件成功后没有对文件重命名时,可以考虑上传这两个配置文件进行试探。
-
关于不同平台的特性,
windows 平台时 apache 可以将以下 url 中的文件识别为网站的 inj.php 文件,并且将其当作 php 执行。 inj.php.. inj.php空. inj.php空空 inj.php.空. 但在 Linux 平台上,url 的文件必须和网站的文件完全匹配。并且,当文件后缀含有空格,将不会被 apache 当作脚本识别。例如 inj.php空 不支持,会直接显示源码。 inj.php. 可以正常当作 php 脚本执行。
-
代码正面刚。
labs
-
lab-1: 提示是 js 检查,故尝试将后缀修改为 .png ,而在数据包中将文件名后缀修改为 .php 成功。
-
lab -2:提示MIME 检查,故可以直接上传 .png 的后门文件,此时 MIME 为浏览器推导出来的 image/png ,然后再在数据包中修改文件后缀为 php 即可
-
lab-3: 提醒不允许上传指定后缀的文件,尝试利用后缀大小写都失败了。。。
考点是默认 apache 配置文件中有 AddType application/x-httpd-php .php .phtml
$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
因为通过验证后会修改文件名,所以无法上传 .htaccess 或者 .user.ini 。
因为是提取过滤后的后缀作为文件后缀,所以无法使用文件名末尾加
. .
的形式在 windows 平台进行绕过。无法使用 %00 截断,因为用户提交的数据是以 $_FILE 的形式接受,已经产生截断。
-
考察的是上传配置文件 .htaccess。
'inj.php. .' //行末写出处理后的结果 $file_name = trim($_FILES['upload_file']['name']); //'inj.php. .' $file_name = deldot($file_name); //'inj.php. ' $file_ext = strrchr($file_name, '.'); //'. ' $file_ext = strtolower($file_ext); //'. ' $file_ext = str_ireplace('::$DATA', '', $file_ext); //'. ' $file_ext = trim($file_ext); //'.' $img_path = UPLOAD_PATH.'/'.$file_name; //'inj.php. '
所以就可以上传 .htaccess 文件。
首先考虑绕过,采取
inj.php. .
在 windows 平台下可以直接上传。而linux 平台由于后缀中存在空格,所以不行。.htaccess 因为没有在黑名单内,故也可以上传。
.user.ini 因为黑名单有 .ini 所以无法直接上传,但可以采用
.user.ini. .
的形式在windows 平台下上传。在 windows 下,任何格式通过 在后缀添加
. .
使得都可以上传。 -
考察的是windows平台特性。
和第四关代码处理逻辑基本相同,可以看到代码中禁止了 .htaccess 上传。但没有 .ini 后缀限制。
所以这块的目的是使得后缀通过验证 而 文件可以被当作 php 文件执行。
这就利用windows 特性,考虑这样的文件
'inj.php. .' //行末写出处理后的结果 $file_name = trim($_FILES['upload_file']['name']); //'inj.php. .' $file_name = deldot($file_name); //'inj.php. ' $file_ext = strrchr($file_name, '.'); //'. ' $file_ext = strtolower($file_ext); //'. ' $file_ext = str_ireplace('::$DATA', '', $file_ext); //'. ' $file_ext = trim($file_ext); //'.' $img_path = UPLOAD_PATH.'/'.$file_name; //'inj.php. ' 'inj.php.. ..'
最终得到的后缀为一个点,由于它不在黑名单内,故通过验证。而在 windows 平台 最终的文件名保存时会自动去除尾部的空格和点。
而在我的 Linux 平台下,当文件后缀含有空格时无法正常解析。
-
细细分析
$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
上传成功后会更名,所以 .htaccess 和 .user.ini 没有太大的上传意义。(如果配合解析漏洞)
代码正面刚的话,由于缺少转换大小写,只要对后缀进行大小写绕过黑名单即可。
前面几关在 windows 平台下末尾加
. .
的方法依然可行 -
和第六关几乎一样,因为会更改文件名,所以两个配置文件没有太大上传意义。所以在windows 平台下,末尾加空格或点的时候依然可行。
-
没有对文件重命名,所以可以通过在文件末尾加点的方式成功上传。
-
首先,上传成功后会文件重命名,所以 两个配置文件没有太大上传意义。再因为是以过滤后的后缀作为文件后缀,所以 Windows 平台下文件名后加
. .
无效。但代码中没有对
::$DATA
进行过滤,故文件名后加上即可。但 Linux 平台下暂时无解。
-
因为没有文件重命名 windows 平台下,可以 后缀加
. .
从而直接绕过代码逻辑,上传所有类型的文件。 -
代码中是采用正则表达式来过滤后缀,但是这个方法只是一次过滤,而并不是递归过滤。所以可以采用双写的方式上传两个配置文件,或者直接上传 php 文件。
-
考察的是00截断,可以注意到数据包中请求路径有 save_path
代码是通过 POST 中的文件名来判断是否在白名单内,而保存的时候使用 GET 中 save_path 加上日期文件名来保存
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1); $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
所以就可以利用 00 截断,直接将 POST 文件后缀更改为 .png 并且将 GET 中的 save_path 中加上文件名与 %00 从而达到截断效果
-
和12 关一样,区别在于是 POST 型提交,需要手动转码。
-
文件包含漏洞加文件上传。查看提示,说是检查文件内容前两个字节。那么直接以文本文件的形式打开一个图片,然后在之后加上php 代码。
这里奇怪的是,我在文件内容前面加上响应的字节却没有作用。后来发现,直接在数据包修改会被当作 unicode 码,%ff 经转码后再提交给 代码时会被识别为 %u00ff 也就是十进制 195191。所以像文件内容这类编码的东西,最好不要在数据包中修改,直接在文件中修改。2020.12.1 版本的 burp 没有了 hex 视图功能,所以不能经过 url 编解码进行修改
-
和14 关解法一样,不过代码检验逻辑不同,是用到了getimagesize() 函数
-
和前两关类似,不过使用的是exif_imagetype()。因为我们是给一个正常图片末尾加上 php 代码,所以这三关的验证都可以正常通过。
-
感觉是绕过 imagecreatefromjpeg,又感觉是条件竞争,但题目又说是二次渲染。
新感觉,二次渲染
新新感觉,上传之后重命名是二次渲染,也就是说同时只存在一个文件。所以应该是文件包含 加上条件竞争
所以,二次渲染+文件包含 或者 条件竞争+文件包含 都可以。不过前者明显更能持久创建后门。
这块就先试试条件竞争,条件。
条件竞争成功,但是如果 图片 太大,好像include 不成功。include 应该有大小限制
-
经典的条件竞争
-
代码稍微有点多,要理清思路。
根据源码,大概猜想它某一处完成的工作。大概是检查后缀、大小、文件是否存在,移动文件,对文件重命名。
奇怪的是,在我的电脑上,它一直提醒文件无法上传到临时目录,所以要看看是这个lab 出问题还是其它lab 也这样。
条件竞争+解析漏洞
-
感觉更简单了?因为黑名单没有大小写检验,故可以直接大小写后缀的形式绕过。如果是搭建在 windows 下,直接截断也可通过。即构造文件名 inj.php%00.png
-
通过数组的方式进行绕过