首页 » 漏洞 » phpcms安全防范:记录一次开启GPC导致的注入

phpcms安全防范:记录一次开启GPC导致的注入

 

phpcms安全防范:记录一次开启GPC导致的注入,一个利用ThinkPHP 3.1.2二次开发的CMS。

问题代码如下:

$id = ACTION_NAME;

//判断是否为列表页

$categoryid = get_regex_value('/(?<=^lists-).+$/i', strtolower($id));

if($categoryid){

    $_GET["category_id"]   = $categoryid; //复制当前分类ID

    $this->lists();

}

else{

    //调用特定函数,来获取数据

    //$cms = PitCMS::NewPitCMS($cms_model);

    $dataArray = $cms->details($id);

    echo M("CmsNews")->getDbError();

    //返回值进行模板变量赋值

    $this->assignArray($dataArray);

    //根据类别获取模板

    //$category = $dataArray["category"];

    $tpl = "details";

    if($dataArray["tpl"]){

        $tpl = $dataArray["tpl"];

    }           

    $this->cms_display($cms_model, $tpl);

}

$id = ACTION_NAME;

//判断是否为列表页

$categoryid = get_regex_value('/(?<=^lists-).+$/i', strtolower($id));

if($categoryid){

    $_GET["category_id"]   = $categoryid; //复制当前分类ID

    $this->lists();

}

else{

    //调用特定函数,来获取数据

    //$cms = PitCMS::NewPitCMS($cms_model);

    $dataArray = $cms->details($id);

    echo M("CmsNews")->getDbError();

    //返回值进行模板变量赋值

    $this->assignArray($dataArray);

    //根据类别获取模板

    //$category = $dataArray["category"];

    $tpl = "details";

    if($dataArray["tpl"]){

        $tpl = $dataArray["tpl"];

    }           

    $this->cms_display($cms_model, $tpl);

}

上面的参数id是直接从ACTION_NAME获取的$id = ACTION_NAME;,下面继续看details()函数的定义:

function details($id){

    $md = $this->db->getById($id);

    //print_r($md);

    $arr = array(

            "md"    => $this->cms_model->convertDataBack($md)

    );

    $category_id   = $md["category_id"];

    if($category_id){

        $category       = D("CmsCategory")->getById($category_id);

        $arr["category"] = $category;

        $arr["category_list"]  =  $this->f_GetParentCategoryList($category_id);

        $arr['tpl']         = $category["details_tpl"];

        //判断访问权限

        $category  = $arr["category"];

        if($category['roles']){

             $roles = json_decode($category['roles']);

             if($roles && !in_array($this->current_member_user['role_id'],$roles)){

                 $backurl = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

                 header("location:".U('/member/login')."?backurl=".$backurl);

             }

        }

    }

    $this->db->where("id=".$id)->setInc("click_count");    // 这里其实也有一个注入的,只不过是盲注或者报错注入。

    return $arr;

}

function details($id){

    $md = $this->db->getById($id);

    //print_r($md);

    $arr = array(

            "md"    => $this->cms_model->convertDataBack($md)

    );

    $category_id   = $md["category_id"];

    if($category_id){

        $category       = D("CmsCategory")->getById($category_id);

        $arr["category"] = $category;

        $arr["category_list"]  =  $this->f_GetParentCategoryList($category_id);

        $arr['tpl']         = $category["details_tpl"];

        //判断访问权限

        $category  = $arr["category"];

        if($category['roles']){

             $roles = json_decode($category['roles']);

             if($roles && !in_array($this->current_member_user['role_id'],$roles)){

                 $backurl = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

                 header("location:".U('/member/login')."?backurl=".$backurl);

             }

        }

    }

    $this->db->where("id=".$id)->setInc("click_count");    // 这里其实也有一个注入的,只不过是盲注或者报错注入。

    return $arr;

}

数据没有经过过滤直接使用了$md = $this->db->getById($id);,但是我在本地测试的时候发现$id是经过了过滤的,应该是在过滤时候判断出现了问题,然后挨着定位到了DbMysql.class.php文件的escapeString()函数

public function escapeString($str) {

    if (!get_magic_quotes_gpc()){

     if($this->_linkID) {

         return mysql_real_escape_string($str,$this->_linkID);

     }else{

         return mysql_escape_string($str);

     }

    }else {

        return $str;

    }

}

public function escapeString($str) {

    if (!get_magic_quotes_gpc()){

     if($this->_linkID) {

         return mysql_real_escape_string($str,$this->_linkID);

     }else{

         return mysql_escape_string($str);

     }

    }else {

        return $str;

    }

}

如果开启了GPC反而不再过滤但是,你以为这样就完了么,ThinkPHP的getBy系列函数有个很重要的一步就是根据字段类型进行强制转换。意思就是说如果如果id字段是int类型,那么会对强制使用intval()函数,下面看看处理函数是怎么写的。

protected function _parseType(&$data,$key) {

    $fieldType = strtolower($this->fields['_type'][$key]);

    if(false === strpos($fieldType,'bigint') && false !== strpos($fieldType,'int')) {

        $data[$key]   =  intval($data[$key]);

    }elseif(false !== strpos($fieldType,'float') || false !== strpos($fieldType,'double')){

        $data[$key]   =  floatval($data[$key]);

    }elseif(false !== strpos($fieldType,'bool')){

        $data[$key]   =  (bool)$data[$key];

    }

}

protected function _parseType(&$data,$key) {

    $fieldType = strtolower($this->fields['_type'][$key]);

    if(false === strpos($fieldType,'bigint') && false !== strpos($fieldType,'int')) {

        $data[$key]   =  intval($data[$key]);

    }elseif(false !== strpos($fieldType,'float') || false !== strpos($fieldType,'double')){

        $data[$key]   =  floatval($data[$key]);

    }elseif(false !== strpos($fieldType,'bool')){

        $data[$key]   =  (bool)$data[$key];

    }

}

它处理了整型中的非bigint类型、浮点型、布尔型,然后我回头去看了看当前表中的id类型,是bigint类型的。刚好引起了注入!

原文链接:phpcms安全防范:记录一次开启GPC导致的注入,转载请注明来源!

0