2015-04-09: 细节已通知厂商并且等待厂商处理中 2015-04-10: 厂商主动忽略漏洞,细节向第三方安全合作伙伴开放 2015-06-04: 细节向核心白帽子及相关领域专家公开 2015-06-14: 细节向普通白帽子公开 2015-06-24: 细节向实习白帽子公开 2015-07-09: 细节向公众公开
TinyShopV1.4最新版(4月3日更新)SQL注入,无视GPC
漏洞文件:protected/controllers/simple.php 第113行:
public function activation_user() { $code =Filter::text(Req::args('code')); $email_code = substr($code,32); $valid_code = substr($code,0,32); $email = Crypt::decode($email_code);//解密email_code $model = new Model('user'); $user = $model->where("email='".$email."'")->find();//这里直接带入查询,没有过滤 if($user && $user['status']==0 && md5($user['validcode'])==$valid_code){ $model->data(array('status'=>1))->where('id='.$user['id'])->update(); $this->redirect("/index/msg",false,array('type'=>"success","msg"=>'账户激活成功',"content"=>"账户通过邮件成功激活。","redirect"=>"/simple/login")); }else{ $this->redirect("/index/msg",false,array('type'=>"fail","msg"=>'账户激活失败',"content"=>"你的连接地址无效,无法进行账户激活,请核实你的连接地址无误。")); } }
我们跟进Crypt::decode:
private static function code($string, $op="decode", $key='', $expiry=0) { global $auchcode_key; $op=strtolower($op); $key_length=10; $key=md5($key?$key:isset($auchcode_key)?$auchcode_key:"%@&!!");//这里都是相同的key。。。导致我们可以生成 //生存256长度的密码 $key_1=md5(substr($key,0,4)); $key_2=md5(substr($key,4,4)); $key_3=md5(substr($key,8,4)); $key_4=md5(substr($key,12,4)); $key_5=md5(substr($key,16,4)); $key_6=md5(substr($key,20,4)); $key_7=md5(substr($key,24,4)); $key_8=md5(substr($key,28,4)); $key_e= $key_length ? ($op == 'decode' ? substr($string, 0, $key_length): substr(md5(microtime()), -$key_length)) : ''; $cryptkey = md5($key_1|$key_e).md5($key_3|$key_e).md5($key_5|$key_e).md5($key_7|$key_e).md5($key_8|$key_e).md5($key_6|$key_e).md5($key_4|$key_e).md5($key_2|$key_e); $cryptkey_length = strlen($cryptkey); $string = $op == 'decode' ? base64_decode(substr($string, $key_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$key_5), 0, 22).$string; $string_length = strlen($string); $result=""; //通过循环的方式异或的方式加密,异或方式是加密中常用的一种处理方式 for($i = 0; $i < $string_length; $i++) { $result .= chr(ord($string[$i]) ^ ($cryptkey[$i % 256])); } //解码部分 if($op == 'decode') { if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 22) == substr(md5(substr($result, 32).$key_5), 0, 22)) { return substr($result, 32); } else { return ''; } } else { return $key_e.str_replace('=', '', base64_encode($result)); } }
这里的KEY是默认的,导致我们也可以生成~~我们看下刚下载的压缩包~依然是这个key:
于是,我们再看下email_code的生成:
$email_code = Crypt::encode($email); $valid_code = md5($validcode); $str_code = $valid_code.$email_code; $activation_url = Url::fullUrlFormat("/simple/activation_user/code/$str_code");
这里需要加一个$valid_code因此,我们构造如下php文件来生成email_code:
测试代码里
生成code:
之后我们在find()里面加一个echo,方便显示:
public function find() { $this->limit(1); $this->changeWhere(); if($this->sql['where']!='') { echo $this->createSql(); $result = $this->query($this->createSql()); return isset($result[0])?$result[0]:$result; } return null; }
最终注入成功(这里用的是延迟5秒):
危害等级:无影响厂商忽略
忽略时间:2015-07-09 16:00
360库带已经有人提交过。
漏洞Rank:4 (WooYun评价)
暂无