本环境采用phpstudy一键搭建
环境配置
将压缩包解压到www目录下,因为压缩包内有一个名为runtime的空文件夹,可能解压时会被忽略,注意没有它会报错
在phpstudy中新建一个网站,我们需要在这个/www/zzzphp下新建一个网站。因为这个cms会有一个目录修改策略将zzzphp修改成zzzp6p,会影响我们的后续操作,所以直接在/zzzphp下建站就可以避免
然后就可以访问/www/zzzphp/install页面进行安装
一路默认到基本信息配置
点击安装完成就好了
代码审计
php涉及到删除的函数是unlink,他会返回true或false判断是否删除成功
我们搜索那些地方用到了该函数,于是发现了两个比较有嫌疑的函数
dellfiles丢弃
一、函数功能
这个名为delfiles
的函数用于删除指定路径下具有特定扩展名的文件。
二、参数说明
$path
:表示要进行操作的目录路径。$ext
:表示要删除的文件的扩展名。
三、代码详解
if (!is_dir( $path ) ) return FALSE;
:- 检查传入的
$path
是否是一个有效的目录。如果不是目录,则返回FALSE
,表示函数执行失败。
- 检查传入的
if ( substr( $path, strlen( $path ) - 1 )!= '/' ) return NULL;
:- 检查目录路径的末尾是否有斜杠(
/
)。如果没有,则返回NULL
。这一步通常是为了确保路径格式的一致性,方便后续的文件操作。
- 检查目录路径的末尾是否有斜杠(
$handle = opendir( $path );
:- 使用
opendir
函数打开指定的目录,并将返回的目录句柄存储在$handle
变量中。
- 使用
while ( false!== ( $file = readdir( $handle ) ) ) {... }
:- 使用
readdir
函数遍历目录中的文件和子目录。每次循环都会读取一个目录项,并将其存储在$file
变量中。只要readdir
函数没有返回false
,循环就会继续执行。
- 使用
if ( $file!= '.' && $file!= '..' ) {... }
:- 排除当前目录(
.
)和父目录(..
)。在遍历目录时,这两个特殊的目录项通常需要被排除,因为它们不是普通的文件或子目录。
- 排除当前目录(
$path2 = $path. $file;
:- 构建完整的文件路径,将当前遍历到的文件与传入的目录路径拼接起来。
if ( preg_match( "/\.(". $ext. ")$/i", $file ) ) {... }
:- 使用正则表达式
preg_match
函数检查当前文件的名称是否以指定的扩展名结尾。正则表达式中的/\.(". $ext. ")$/i
表示匹配以点(.
)和传入的扩展名$ext
结尾的文件名称,不区分大小写(i
标志)。
- 使用正则表达式
unlink( $path2 );
:- 如果文件符合扩展名要求,则使用
unlink
函数删除该文件。
- 如果文件符合扩展名要求,则使用
总结:这是一个可以删除文件的函数,但他会有一个拓展名匹配验证,可能出现某些拓展名删除不了的情况
我们去查找他的用法,但发现只在一处调用,且皆固定拓展名,于是放弃跟踪
del_file保留
一、函数功能概述
这个名为del_file
的函数主要用于尝试删除给定的文件。如果文件不能直接删除,它会尝试将文件重命名为一个随机名称。同时,对于包含特定字符串和特定扩展名的文件有特殊的处理逻辑。
二、参数说明
$file
:表示要进行操作的文件路径。
三、代码逐步分析
if (is_null($file)) return FALSE;
:- 首先检查传入的文件路径参数
$file
是否为null
。如果是,直接返回FALSE
,表示无法进行后续操作。
- 首先检查传入的文件路径参数
$file = is_file($file)? $file : $_SERVER['DOCUMENT_ROOT']. $file;
:- 判断
$file
所代表的路径是否是一个有效的文件。如果是,则保持$file
不变;如果不是,将服务器根目录(通过$_SERVER['DOCUMENT_ROOT']
获取)与传入的路径拼接起来,得到一个新的文件路径。
- 判断
if (is_file($file)) {...}
:- 再次确认经过处理后的路径是否确实指向一个文件。如果是,进入以下处理逻辑。
if (ifstrin($file, 'runtime')) {...}
:- 检查文件路径中是否包含字符串
'runtime'
。如果包含,使用unlink
函数直接删除该文件。
- 检查文件路径中是否包含字符串
else {...}
:- 如果文件路径不包含
'runtime'
,执行以下逻辑。 $ext = file_ext($file);
:获取文件的扩展名。if (in_array($ext, array('php', 'db', 'mdb', 'tpl'))) return FALSE;
:检查文件扩展名是否在指定的扩展名数组中。如果是,函数返回FALSE
,表示不进行删除操作。if (!unlink($file)) {...}
:尝试使用unlink
函数删除文件。如果删除失败,执行以下逻辑。$r = @rename($file, randname());
:使用rename
函数尝试将文件重命名为一个随机名称(通过randname()
函数生成)。@
符号用于抑制可能出现的错误信息。
- 如果文件路径不包含
总结:存在部分后缀过滤不能删,删除失败会被强制重命名,但可以尝试删除某些js文件或网站txt文件
查找那些地方调用过他,在delfile函数中使用到
其中的path通过post传递,再传递给file变量供del_file函数使用。在此函数中也存在校验,文件必须来自upload等三个目录下才能删除。跟踪delfile
通过act=delfile调用的delfile文件,act通过get传参得来
整理信息
实现此cms文件删除的逻辑是访问save.php,传递act值(get传递)调用delfile函数,添加path(post传递)为del_file函数服务,最终实现删除。
如果看不懂可以反过来查看整个逻辑,即从函数调用-函数声明
拓展
具有mcv架构源码的执行逻辑是直接找到关于删除函数的文件,构造url调用它就可以了,可以参考前几期的梦想cms。但是本cms仅仅是正常的,类似平常写的代码。我们则需要找到哪里调用了这个删除函数,需要构造url成它(哪里调用的地方)才行。
操作
因为save.php在后台,我们先登陆进去,遇到验证码查看不清楚的话,右键打开成新页面就好了
在/zzzphp目录下新建一个1.txt
添加一句输出方便得到路径
构造url,path参数必须携带四组目录中的一种不然不会有回显
知道路径后再次构造删除掉我们写入的1.txt
已经成功删除掉,我就不贴图了。但并不是所有文件都可以删,请牢记!
Comments NOTHING