代码审计
漏洞文件:yzmphp\core\class\cache_file.class.php
- 代码171-179行,使用了file_put_contents(),其中
$file
和$contents
可控
protected function _fileputcontents($file, $contents){
if($this->config['mode'] == 1){
$contents = serialize($contents);
}else{
$contents = "<?php\nreturn ".var_export($contents, true).";\n?>";
}
$filesize = file_put_contents($file, $contents, LOCK_EX);
return $filesize ? $filesize : false;
}
- 我们继续跟进
_fileputcontents()
,在同一文件代码62-75行调用了该方法,我们继续跟进set()
漏洞文件:yzmphp\core\function\global.func.php
global.func.php
的1017-1021中的setcache()
方法疑似调用了set()
方法,并且$name, $data, $timeout
均可控,我们跟进load_sys_class('cache_factory','',0);
看看get_instance()->get_cache_instances()
到底调用了哪个文件。
漏洞文件:\yzmphp\core\class\cache_factory.class.php
- 很明显
C('cache_type')
决定了他调用哪个文件中的set()
方法,我们跟进cache_type
- 跟进发现在
common\config\config.php
做了定义,cache_type
默认使用file
,mode
存在两种模式,我们选择1
-序列化看看或许可能读取缓存存在反序列化的可能。那么回头看他默认使用file
也就是调用了cache_file.class.php
所以我们的猜测没错。同时这里还是用了file_config
这个参数,我们继续跟进setcache()
方法
漏洞文件:\common\function\system.func.php
- 这里$modelinfo是从数据库中得到所以可控,$filename指定了名称
modelinfo
或者modelinfo_all
。我们继续跟进get_modelinfo()
会发现都不传入参数,所以默认$typeall = 0,也就是说文件名称固定modelinfo
- 我们再回到
yzmphp\core\class\cache_file.class.php
,发现文件名称和路径由_file()
方法决定。而$id
正是我们传入的。我们跟进_file()
方法
- 我们可以得知filename是由config[‘cache_dir’] 和传入的
$id
和config['suffix']
拼接而成。我们再看config['suffix']
和'cache_dir'
是什么?
- 我们在审计
common\config\config.php
时候已经发现这里定义了file_config
,这样我们就完整知道缓存文件写在cache/chche_file/modelinfo.cache.php
- 而且这里是模型的缓存,我们直接到后台写入一个php代码看看。
- 需要访问前台让其生成新的缓存文件。我们打开:
cache/chche_file/modelinfo.cache.php
看看
- 我们访问
http://域名/cache/chche_file/modelinfo.cache.php
看看,成功getshell
后记
- 如果
mode
选择的模式是2的话是无法getshell的,由于var_export()
进行了转义,暂时没有找到方法,但是该cms默认的是选择2
导致这个漏洞有点鸡肋。