笔者在看一篇代码审计的文章时,对其中作者提及的一处地方感到迷惑,思考无果遂便自己展开了一次粗浅的分析,最终弄明白了自己的困惑并在Window环境下实现了两种思路去达到GetShell目的。
官网:http://www.sem-cms.com/xiazai.html
下载地址:http://www.sem-cms.com/TradeCmsdown/php/SEMCMS_PHP_3.9.zip
Linux:
安装完成后会给出后台登陆信息:
网站后台地址为:你的域名+N8D3ch_Admin/ 请牢记,后台默认帐户:Admin 密码:1 登陆后进行修改
Window:
网站后台地址为:你的域名+rhDOEr_Admin/ 请牢记,后台默认帐户:Admin 密码:1 登陆后进行修改
访问:http://localhost:8887/semcms/N8D3ch_Admin/SEMCMS_Upload.php
上传抓包
1)第一步
传入这个参数之后,会进入代码的拼接过程
最终执行的$newname
, 是将文件的内容写入到111.jpg.php:.jpg
,$Imageurl
可以控制向上目录穿越,这里不设置,默认则为空。
move_uploaded_file($_FILES["file"]["tmp_name"],$Imageurl.$newname); //文件写入文件夹
:
从而写入ADS流文件,会导致生成一个111.jpg.php
的空文件和一个111.jpg.php:.jpg
的实际内容为<?php phpinfo();?>
的隐藏文件。111.jpg.php:.jpg<<<
,可惜访问111.jpg.php
,并没有发现有内容写入,所以在这里我对原文中作者的描述,产生了质疑。:
冒号和<
追加符号结合的方式,一般用于绕过黑名单的限制。为了理解这种方式,我们需要了解并学习下Window的特性。<?php
/**
* Created by PhpStorm.
* User: xq17
* Date: 4/17/22
* Time: 7:07 PM
*/
header("Content-Type: text/html; charset=UTF-8");$filename = $_FILES["file"]["name"];
if($filename){
# 获取后缀名
$uptype = strtolower(end(explode(".", $filename)));
print_r("suffix:".$uptype."\n");
# 判断是否在黑名单里面
if(in_array($uptype, array('php', 'phtml'))){
print_r("不允许上传php文件!");
die(0);
}else{
// 通过黑名单检验
move_uploaded_file($_FILES["file"]["tmp_name"], $filename);
print_r("上传成功!");
}
}
.
来绕过黑名单。.
::$data
这一默认流类型来绕过黑名单。::$data
,而是作为默认流类型,保留了3.php
这一原文件名达到绕过目的。<
:匹配0个以上的字符>
:匹配一个字符"
:匹配点号
7.php:jpg
,即可上传成功一个空文件<
、"
或者>
号进行覆盖写入<
可以匹配多个字符,即7.p<
能够匹配到7.php
>
只能匹配单个字符,故用7.p>>
能够匹配到7.php
使用"
来匹配点号。
111.jpg.php:.jpg<<<
文件名结合0x3.1的Window特性来看并没有很大意义。111.jpg.php:.jpg<<<
匹配的就是111.jpg.php:.jpg
+后面任意字符的文件名,根本匹配不到111.jpg.php
这个我们想要覆盖的文件。.
,要不然会被分割,所以后缀我们是没办法构造出php
的。move_uploaded_file
的值为ttt.jpg.php:.jpg
wname
的值为ttt
,后缀控制为1.jpg<
,那么拼接之后的值便是ttt.jpg<
,按道理来说是应该能匹配到ttt.jpg.php
,因为<
其实等价于*
的作用。
<
并没有匹配成功,使用两个以上<
即可匹配成功。<
被过滤的时候,我们可以通过构造jpg\"php
来匹配上jpg.php
这个格式。好文推荐