### 简要描述: FineCMS任意用户密码重置 ### 详细说明: finecms最新版2.3.0,官方2014年4月18号更新。 finecms在密码找回功能处存在设计缺陷,导致可重置任意用户密码。 来看看密码找回的代码: ``` /** * 找回密码 */ public function find() { $step = max(1, (int)$this->input->get('step')); $error = ''; if (IS_POST) { switch ($step) { case 1: if ($uid = get_cookie('find')) { $this->member_msg( lang('m-093'), dr_member_url('login/find', array('step' => 2, 'uid' => $uid)), 1 ); } else { $name = $this->input->post('name', TRUE); $name = in_array($name, array('email', 'phone')) ? $name : 'email'; $value = $this->input->post('value', TRUE); $data = $this->db ->select('uid,username,randcode') ->where($name, $value) ->limit(1) ->get('member') ->row_array(); if ($data) { $randcode = rand(1000, 9999); if ($name == 'email') { $this->load->helper('email'); if (!$this->sendmail($value, lang('m-014'), dr_lang('m-187', $data['username'], $randcode, $this->input->ip_address()))) { $this->member_msg(lang('m-189')); } set_cookie('find', $data['uid'], 300); $this->db ->where('uid',...
### 简要描述: FineCMS任意用户密码重置 ### 详细说明: finecms最新版2.3.0,官方2014年4月18号更新。 finecms在密码找回功能处存在设计缺陷,导致可重置任意用户密码。 来看看密码找回的代码: ``` /** * 找回密码 */ public function find() { $step = max(1, (int)$this->input->get('step')); $error = ''; if (IS_POST) { switch ($step) { case 1: if ($uid = get_cookie('find')) { $this->member_msg( lang('m-093'), dr_member_url('login/find', array('step' => 2, 'uid' => $uid)), 1 ); } else { $name = $this->input->post('name', TRUE); $name = in_array($name, array('email', 'phone')) ? $name : 'email'; $value = $this->input->post('value', TRUE); $data = $this->db ->select('uid,username,randcode') ->where($name, $value) ->limit(1) ->get('member') ->row_array(); if ($data) { $randcode = rand(1000, 9999); if ($name == 'email') { $this->load->helper('email'); if (!$this->sendmail($value, lang('m-014'), dr_lang('m-187', $data['username'], $randcode, $this->input->ip_address()))) { $this->member_msg(lang('m-189')); } set_cookie('find', $data['uid'], 300); $this->db ->where('uid', $data['uid']) ->update('member', array('randcode' => $randcode)); $this->member_msg(lang('m-093'), dr_member_url('login/find', array('step' => 2, 'uid' => $data['uid'])), 1); } else { $result = $this->member_model->sendsms($value, dr_lang('m-088', $randcode)); if ($result['status']) { // 发送成功 set_cookie('find', $data['uid'], 300); $this->db ->where('uid', (int)$data['uid']) ->update('member', array('randcode' => $randcode)); $this->member_msg(lang('m-093'), dr_member_url('login/find', array('step' => 2, 'uid' => $data['uid'])), 1); } else { // 发送失败 $this->member_msg($result['msg']); } } } else { $error = $name == 'phone' ? lang('m-182') : lang('m-185'); } } break; case 2: $uid = (int)$this->input->get('uid'); $code = (int)$this->input->post('code'); $data = $this->db ->where('uid', $uid) ->where('randcode', $code) ->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, '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; } } $this->template->assign(array( 'step' => $step, 'error' => $error, 'action' => 'find', 'mobile' => $this->get_cache('member', 'setting','ismobile'), 'meta_name' => lang('m-014'), 'result_error' => $error, )); $this->template->display('find.html'); } ``` 可以看到: 首先通过email,发送4为数字的验证码到email的邮箱。 然后跳转到重置密码的链接。 输入验证码和新密码就可重置密码了。 这里的uid已经返回在重置密码的链接里面了。 所以我们只需要用户注册的email地址,然后重置此用户名的密码。 然后爆破4位数字就可,一共的可能只有9000种可能,而且这里没有次数限制,爆破这样的数字太easy了。 ### 漏洞证明: 第一步重置密码,发送验证码到邮箱: [<img src="https://images.seebug.org/upload/201405/10160618643c44a6b29f2792bdd82912d1076006.png" alt="111.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201405/10160618643c44a6b29f2792bdd82912d1076006.png) 第二步填写验证码和新密码,抓包: [<img src="https://images.seebug.org/upload/201405/10160629676c066c17ad4b3c248a1962cffa52aa.png" alt="222.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201405/10160629676c066c17ad4b3c248a1962cffa52aa.png) 第三步遍历爆破验证码即可: [<img src="https://images.seebug.org/upload/201405/1016064464fcd74d70b485128f2ec132213320fc.png" alt="333.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201405/1016064464fcd74d70b485128f2ec132213320fc.png) 此时已经成功重置了该用户的密码。