PHPB2B某处sql注入(危害巨大)


官网下载的最新版本


绕过全局防注入。



我们先看看全局防注入怎么写的。



以下是全局防注入用到的函数

function pb_attack_filter($StrFiltKey,$StrFiltValue,$ArrFiltReq){ if(is_array($StrFiltValue)) { $StrFiltValue=@implode(",", $StrFiltValue); } if (preg_match("/".$ArrFiltReq."/is",$StrFiltValue)==1){ echo $StrFiltValue; header_sent("Warning : Illegal operation!"); exit(); } } function pb_hack_check(){ $getfilter="'|(and|or)\\b.+?(>|<|=|in|like)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)"; $postfilter="\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|ascii|load_file|substring|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)"; $_PG=array_merge($_GET,$_POST); foreach($_PG as $key=>$value){ pb_attack_filter($key,$value,$getfilter); pb_attack_filter($key,$value,$postfilter); } }



其核心在于,对post和get传递过来的参数值进行了一次过滤

foreach($_PG as $key=>$value){ pb_attack_filter($key,$value,$getfilter); pb_attack_filter($key,$value,$postfilter); }



但是还是有不足的地方。



register.php



83-117行

if(isset($_POST['register'])){ $is_company = false; $if_need_check = false; $register_type = trim($_POST['register']); $register_typename = trim($_POST['typename']); pb_submit_check('data'); $default_membergroupid_res = $pdb->GetRow("SELECT * FROM {$tb_prefix}membertypes WHERE name='".$register_typename."'"); $default_membergroupid = $default_membergroupid_res['default_membergroup_id']; if(empty($default_membergroupid)) $default_membergroupid = $membergroup->field("id","is_default=1"); if ($default_membergroupid_res['id']>1) { $is_company = true; } $member->setParams(); $memberfield->setParams(); //exception if(!$member->checkException($member->params['data']['member'], array( 'username', 'email', 'userpass', ))){ flash("sys_error"); } $member->params['data']['member']['membergroup_id'] = $default_membergroupid; $time_limits = $pdb->GetOne("SELECT default_live_time FROM {$tb_prefix}membergroups WHERE id={$default_membergroupid}"); $member->params['data']['member']['service_start_date'] = $time_stamp; $member->params['data']['member']['service_end_date'] = $membergroup->getServiceEndtime($time_limits); $member->params['data']['member']['membertype_id'] = ($is_company)?2:1; if($member_reg_auth=="1" || $member_reg_auth!=0 || !empty($G['setting']['new_userauth'])){ $member->params['data']['member']['status'] = 0; $if_need_check = true; }else{ $member->params['data']['member']['status'] = 1; } $updated = false; $updated = $member->Add();



代码比较长,其中比较关键的函数有

第96行



$memberfield->setParams();





看看setparams函数怎么写的

function setParams($extra = array()) { $params = array(); if (isset($_POST)) { $params['form'] = $_POST; if (ini_get('magic_quotes_gpc') === '1') { $params['form'] = pb_addslashes($params['form']); } if (pb_getenv('HTTP_X_HTTP_METHOD_OVERRIDE')) { $params['form']['_method'] = pb_getenv('HTTP_X_HTTP_METHOD_OVERRIDE'); } if (isset($params['form']['_method'])) { if (isset($_SERVER) && !empty($_SERVER)) { $_SERVER['REQUEST_METHOD'] = $params['form']['_method']; } else { $_ENV['REQUEST_METHOD'] = $params['form']['_method']; } unset($params['form']['_method']); } } $params = array_merge($extra, $params); if (isset($_GET)) { if (ini_get('magic_quotes_gpc') === '1') { $url = stripslashes_deep($_GET); } else { $url = $_GET; } array_unique($url); if (isset($params['url'])) { $params['url'] = array_merge($params['url'], $url); } else { $params['url'] = $url; } } if (isset($params['action']) && strlen($params['action']) === 0) { $params['action'] = 'list'; } if (isset($params['form']['data'])) { $params['data'] = $params['form']['data']; unset($params['form']['data']); } $this->params = $params; }



代码又臭又长,其实这个函数主要的功能就是把post过来的数据全部放入当前实例的params属性中,且params是一个数组。

也就是



$_POST[a]=1--->$this->params[a]=1



然后继续往下看



在第117行



调用了$member->Add()这个函数



跟踪看看。

function Add() { global $_PB_CACHE, $memberfield, $phpb2b_auth_key, $if_need_check; $error_msg = array(); if (empty($this->params['data']['member']['username']) or empty($this->params['data']['member']['userpass']) or empty($this->params['data']['member']['email'])) return false; //判断各种数值不能为空 $space_name = $this->params['data']['member']['username']; $userpass = $this->params['data']['member']['userpass']; $this->params['data']['member']['userpass'] = $this->authPasswd($this->params['data']['member']['userpass']); if(empty($this->params['data']['member']['space_name'])) $this->params['data']['member']['space_name'] = PbController::toAlphabets($space_name);//Todo: $uip = pb_ip2long(pb_getenv('REMOTE_ADDR')); if(empty($uip)){ pheader("location:".URL."redirect.php?message=".urlencode(L('sys_error'))); } $this->params['data']['member']['last_login'] = $this->params['data']['member']['created'] = $this->params['data']['member']['modified'] = $this->timestamp; $this->params['data']['member']['last_ip'] = pb_get_client_ip('str'); $email_exists = $this->checkUserExistsByEmail($this->params['data']['member']['email']); if ($email_exists) { flash("email_exists", null, 0); } $if_exists = $this->checkUserExist($this->params['data']['member']['username']); //检测是否已经存在该用户名 if ($if_exists) { flash('member_has_exists', null, 0); //如果已存在就跳出 }else{ $this->save($this->params['data']['member']); $key = $this->table_name."_id"; if($this->ins_passport) $this->passport(array($this->$key, $this->params['data']['member']['username'], $userpass, $this->params['data']['member']['email']), "reg"); $memberfield->primaryKey = "member_id"; $memberfield->params['data']['memberfield']['member_id'] = $this->$key; $memberfield->params['data']['memberfield']['reg_ip'] = $this->params['data']['member']['last_ip']; //各种参数设定完毕 $memberfield->save($memberfield->params['data']['memberfield']); //带入save函数执行 if (!$if_need_check) { $user_info['id'] = $this->$key; $user_info['username'] = $this->params['data']['member']['username']; $user_info['userpass'] = $userpass; $user_info['useremail'] = $this->params['data']['member']['email']; $user_info['lifetime'] = $this->timestamp+86400; $user_info['is_admin'] = 0; $this->putLoginStatus($user_info); } } return true; }