Fork me on GitHub

EIS_yzmcms_getshell

EIS中有一道cms 后台getshell的实战类题目,其中写入配置文件从而getshell的方式很经典,这里简单一下这个getshell的原理,仅作学习

来看写入配置文件的逻辑,全局搜索file_put_contents就可以找到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 设置config文件
* @param $config 配置信息
*/
function set_config($config) {
$configfile = YZMPHP_PATH.'common'.DIRECTORY_SEPARATOR.'config/config.php';
if(!is_writable($configfile)) showmsg('Please chmod '.$configfile.' to 0777 !', 'stop');
$pattern = $replacement = array();
foreach($config as $k=>$v) {
$pattern[$k] = "/'".$k."'\s*=>\s*([']?)[^']*([']?)(\s*),/is";
$replacement[$k] = "'".$k."' => \${1}".$v."\${2}\${3},";
}
$str = file_get_contents($configfile);
$str = preg_replace($pattern, $replacement, $str);
return file_put_contents($configfile, $str, LOCK_EX);
}

Config.php的内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
<?php
return array(

//系统配置
'site_theme' => 'default', //站点默认主题目录
'url_html_suffix' => '.html', //URL伪静态后缀
'set_pathinfo' => false, //Nginx默认不支持PATHINFO模式,需配置此项为true,则Nginx可支持PATHINFO,系统默认为false

//数据库配置
'db_type' => 'pdo', // 数据库链接扩展 , 支持 pdo | mysqli | mysql
'db_host' => 'mysql', // 服务器地址
'db_name' => 'yzmcms', // 数据库名
'db_user' => 'root', // 用户名
'db_pwd' => 'root@3556', // 密码
'db_port' => 3306, // 端口
'db_prefix' => 'yzm_', // 数据库表前缀

//路由配置
'route' => array('m' => 'index', 'c' => 'index', 'a' => 'init'), //默认加载配置,基中“m”为模块,“c”为控制器,“a”为方法
'route_mapping' => true, //是否开启路由映射
//路由映射规则
'route_rules' => array(),

//Cookie配置
'cookie_domain' => '', //Cookie 作用域
'cookie_path' => '/', //Cookie 作用路径
'cookie_ttl' => 0, //Cookie 生命周期,0 表示随浏览器进程
'cookie_pre' => 'yzmphp_', //Cookie 前缀,同一域名下安装多套系统时,请修改Cookie前缀
'cookie_secure' => false, //是否通过安全的 HTTPS 连接来传输 cookie

//缓存配置
'cache_type' => 'file', // 缓存类型【暂支持 file , redis , memcache 】
//缓存类型为file缓存时的配置项
'file_config' => array (
'cache_dir' => YZMPHP_PATH.'cache/chche_file/', //缓存文件目录
'suffix' => '.cache.php', //缓存文件后缀
'mode' => '2', //缓存格式:mode 1 为serialize序列化, mode 2 为保存为可执行文件array
),
//缓存类型为redis缓存时的配置项
'redis_config' => array (
'host' => '127.0.0.1', // redis主机
'port' => 6379, // redis端口
'password' => '', // 密码
'select' => 0, // 操作库
'timeout' => 0, // 超时时间(秒)
'expire' => 3600, // 有效期(秒)
'persistent' => false, // 是否长连接
'prefix' => '', // 前缀
),
//缓存类型为memcache缓存时的配置项
'memcache_config' => array (
'host' => '127.0.0.1', // memcache主机
'port' => 11211, // memcache端口
'timeout' => 0, // 超时时间(秒)
'expire' => 3600, // 有效期(秒)
'persistent' => false, // 是否长连接
'prefix' => '', // 前缀
),

//系统语言
'language' => 'zh_cn', //【暂支持 简体中文zh_cn 和 美式英语en_us】

//附件相关配置
'upload_file' => 'uploads', //上传文件目录,后面一定不要加斜杠(“/”)
'watermark_enable' => '1', //是否开启图片水印
'watermark_name' => 'mark.png', //水印名称
'watermark_position' => '9', //水印位置

//其他设置
'sql_execute' => false, //是否允许在线执行SQL命令
'edit_template' => false, //是否允许在线编辑模板

);
?>

这里的逻辑是正则匹配出原config.php文件的key=>value对,然后替换为新的配置。

这个cms存在全局过滤,过滤机制类似phpcms的过滤函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 安全过滤函数
*
* @param $string
* @return string
*/
function safe_replace($string) {
$string = str_replace('%20','',$string);
$string = str_replace('%27','',$string);
$string = str_replace('%2527','',$string);
$string = str_replace('*','',$string);
$string = str_replace('"','',$string);
$string = str_replace("'",'',$string);
$string = str_replace(';','',$string);
$string = str_replace('<','&lt;',$string);
$string = str_replace('>','&gt;',$string);
$string = str_replace("{",'',$string);
$string = str_replace('}','',$string);
$string = str_replace('\\','',$string);
return $string;
}

可以看到我们想要的单引号被过滤了,没有办法直接拼接单引号来注入代码到config.php中。

然而可以注意到replacement的内容为:

1
$replacement[$k] = "'".$k."' => \${1}".$v."\${2}\${3},";

再查看我们的匹配正则

1
$pattern[$k] = "/'".$k."'\s*=>\s*([']?)[^']*([']?)(\s*),/is";

https://res.cloudinary.com/durtftgrv/image/upload/v1574758722/blog/%E4%B8%8B%E8%BD%BD_pdhepw.png

可以看到匹配到的${1}正是单引号本身,因此我们只要添加值为${1}.phpinfo().${1}即可重新引入被

过滤掉的单引号,从而逃逸出来成功注入任意代码。

参考文档

https://blog.wonderkun.cc/2017/02/28/php%E5%86%99%E5%85%A5%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%9A%84%E7%BB%8F%E5%85%B8%E6%BC%8F%E6%B4%9E/