几年前的一个洞,发现依然存在
if ('download' == $do) {
$data = base64_decode($post);
if (base64_encode($data) !== $post) {
$data = $post;
}
$ret = iunserializer($data);
$gz = function_exists('gzcompress') && function_exists('gzuncompress');
$file = base64_decode($ret['file']);
if ($gz) {
$file = gzuncompress($file);
}
$_W['setting']['site']['token'] = authcode(cache_load(cache_system_key('cloud_transtoken')), 'DECODE');
$string = (md5($file) . $ret['path'] . $_W['setting']['site']['token']);
if (!empty($_W['setting']['site']['token']) && md5($string) === $ret['sign']) {
if (0 === strpos($ret['path'], '/web/') || 0 === strpos($ret['path'], '/framework/')) {
$patch_path = sprintf('%s/data/patch/upgrade/%s', IA_ROOT, date('Ymd'));
} else {
$patch_path = IA_ROOT;
}
$path = $patch_path . $ret['path'];
load()->func('file');
@mkdirs(dirname($path));
file_put_contents($path, $file);
$sign = md5(md5_file($path) . $ret['path'] . $_W['setting']['site']['token']);
if ($ret['sign'] === $sign) {
exit('success');
}
}
exit('failed');
}
以上是漏洞的核心代码,我简单说明一下,首先依次顺序是:
1.base解密我们post提交的内容
2.反序列化j解密后内容
3.检测是否存在gzuncompress与gzcompress并将返回赋值gz
4.判断gz是否为true当为true则用gzuncompress再解内容
5.获取cloud_transtoken的内容并通过authcode解密
6.将获取到的token与我们md5后的file以及post反序列化后的path进行拼接
7.判断是否获取到token以及进行了常规的sign验证
8.当验证都通过后进行file_put,因为path、file、content均可控所以导致任意文件写入。只需要获取拿到token值即可
cache_load(cache_system_key('cloud_transtoken'))
我们这里的token是从data下的cache中获取到的,我们看看还有没其他方法可以获取到
旧版本这里没有判断token是否为默认的,高版本这里判断了非auth时进行默认检查