源码下载地址:http://discuz.ml/download
0x01 简析
通过渠道已知是cookie
-> language
这里出现的问题,可直接加个/
符构造报错,至于为什么呢?往下看漏洞成因就能理解了
在 PHP Debug 信息中从上至下跟一下
跟入 forum_index.php 可以看到是包含临时文件,暂时没有具体的内容,跟进 template
include template('diy:forum/discuz:'.$gid);
下面是关键几行代码
function template($file, $templateid = 0, $tpldir = '', $gettplfile = 0, $primaltpl='') {
...
/*vot*/ $cachefile = './data/template/'.DISCUZ_LANG.'_'.(defined('STYLEID') ? STYLEID.'_' : '_').$templateid.'_'.str_replace('/', '_', $file).'.tpl.php';
...
checktplrefresh($tplfile, $tplfile, @filemtime(DISCUZ_ROOT.$cachefile), $templateid, $cachefile, $tpldir, $file);
return DISCUZ_ROOT.$cachefile;
}
在$cachefile
参数值中,通过阅读代码可以明确只有DISCUZ_LANG
是非直接从上层传递过来的,并在checktplrefresh()
中判断如果模板缓存文件不存在,或者缓存文件的更改时间小于模板文件的更改时间,则生成新的缓存文件
那么假如能控制DISCUZ_LANG
,等于能控制一部分文件名
跟入定义,DISCUZ_LANG 值来源于 $lng
define('DISCUZ_LANG', $lng);
注意到,$lng
可以来源于两个地方,$_GET
以及$_COOKIE
,但是对GET
会有检查导致无法利用,而对cookie
则是完全信任没有过滤
那么现在通过设置cookie
-> language
就可以控制文件名了,那么如何控制文件内容呢?
回到开始,由于include
存在,我们控制的点实际是类似这样的
include('test'.phpinfo().'');
所以实际为代码注入,执行效果类似如下
0x02 利用
目标页面只要使用
include template()
即可修改
cookie
->xxxx_language
值满足以下格式即可