漏洞编号:SSV-97087 实验版本:dedecms v5.7SP2
下载地址:http://updatenew.dedecms.com/base-v57/package/DedeCMS-V5.7-UTF8-SP2.tar.gz
参考文章:https://www.seebug.org/vuldb/ssvid-97074
如果要把一个
key
存储到cookie
中,织梦的存储方式是把key
和加密key
同时存储在cookie中。每次读取用户传来的key时,将key
进行加密后与传来的加密key
比对,如果相同则认为这个key合法。注意!!!如果我们能模拟出这个加密算法,我们将可以从
cookie
中传递任何key
。或者将想要的key
传给服务器,让服务器加密后拿来用。这次的漏洞就是需要一个00001
的cookie值,所以我们注册一个用户名为00001
账号就可以获奖00001
加密后的值。
admin
账号信息存在两个表中:管理员账号表dede_admin
和会员账号表dede_member
。两张表中密码相同。cookie
中的mid
(用户id)来登录其他账号,本次就是将mid
修改为1
来登录admin
的前台。dede_admin
和dede_member
中的密码同时修改。Q:修改密码时需要原密码,怎么获得原密码?
A:原密码可以通过利用
前台任意密码修改漏洞
获取。Q:
前台任意密码修改漏洞
不会同时修改dede_admin
和dede_member
两个表的密码吗?A:不会,此漏洞只会修改
dede_member
表的密码。Q:既然可以获取
admin
的前台密码,为什么不直接登录然后修改密码?A:
admin
是不能直接登录前台的。
前台任意密码修改漏洞链接:
https://www.cnblogs.com/masses0x1/articles/14433241.html
首先我们来看一下是怎么写cookie的:
文件位置:dedecms/include/helpers/cookie.helper.php
,21行。
if ( ! function_exists('PutCookie'))
{
function PutCookie($key, $value, $kptime=0, $pa="/")
{
global $cfg_cookie_encode,$cfg_domain_cookie;
setcookie($key, $value, time()+$kptime, $pa,$cfg_domain_cookie);
setcookie($key.'__ckMd5', substr(md5($cfg_cookie_encode.$value),0,16), time()+$kptime, $pa,$cfg_domain_cookie);
}
}
我们再看一下$cfg_cookie_encode
变量:
$cfg_cookie_encode = '~cookieEncode~';
假如我们存个mid=1
,那么cookie会存两个变量:分别为mid=1
和mid_ckMd5=fd3b4f2a75d4965a
。
其中fd3b4f2a75d4965a
是通过函数substr(md5(~cookieEncode~1),0,16)
得到。
然后我们再看一下cookie是怎么获取的:
文件位置:dedecms/include/helpers/cookie.helper.php
,54行。
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];
}
}
}
}
只有key
与key__ckMd5
相对应才能获取cookie。
下面我们来看看怎么获取1对应的__ckMd5
,下面是访问dedecms/member/index.php
时提交的cookie:
Cookie: PHPSESSID=ddafb3894d16a96197233b6ab28c98ba;
last_vtime=1614052745;
last_vtime__ckMd5=6cc13992c8ce524d;
last_vid=00001; last_vid__ckMd5=6d9d0779185557cd;
_csrf_name_66650920=cc35349958296fded35969877cf44b84;
_csrf_name_66650920__ckMd5=d389d371487e2e14; DedeUserID=5;
DedeUserID__ckMd5=d1ff790bc9a1a796; DedeLoginTime=1614086248;
DedeLoginTime__ckMd5=a041486d5d63ce4d
以上cookie我们可控的只有last_vid
,那我们怎样控制last_vid
呢?
再看看关于last_vid
的代码:
文件位置:dedecms/member/index.php
,123行
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, '/');
last_vid
保存的数据就是以前登录过得uid
。所以我们只要用一个名为1的用户登录,last_vid
就会保存1,last_vid__ckMd5
保存的数据就是1对应的__ckMd5
。
最后我们看一下登录代码:
文件位置:dedecms/include/memberlogin.class.php
,161行
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"));
$this->M_LoginTime = GetCookie("DedeLoginTime");
$this->fields = array();
$this->isAdmin = FALSE;
if(empty($this->M_ID))
{
$this->ResetUser();
}else{
$this->M_ID = intval($this->M_ID);
if ($cache)
{
$this->fields = GetCache($this->memberCache, $this->M_ID);
if( empty($this->fields) )
{
$this->fields = $dsql->GetOne("Select * From `#@__member` where mid='{$this->M_ID}' ");
} else {
$formcache = TRUE;
}
} else {
$this->fields = $dsql->GetOne("Select * From `#@__member` where mid='{$this->M_ID}' ");
}
if(is_array($this->fields)){
#api{{
if(defined('UC_API') && @include_once DEDEROOT.'/uc_client/client.php')
{
if($data = uc_get_user($this->fields['userid']))
{
if(uc_check_avatar($data[0]) && !strstr($this->fields['face'],UC_API))
{
$this->fields['face'] = UC_API.'/avatar.php?uid='.$data[0].'&size=middle';
$dsql->ExecuteNoneQuery("UPDATE `#@__member` SET `face`='".$this->fields['face']."' WHERE `mid`='{$this->M_ID}'");
}
}
}
#/aip}}
//间隔一小时更新一次用户登录时间
if(time() - $this->M_LoginTime > 3600)
{
$dsql->ExecuteNoneQuery("update `#@__member` set logintime='".time()."',loginip='".GetIP()."' where mid='".$this->fields['mid']."';");
PutCookie("DedeLoginTime",time(),$this->M_KeepTime);
}
$this->M_LoginID = $this->fields['userid'];
$this->M_MbType = $this->fields['mtype'];
$this->M_Money = $this->fields['money'];
$this->M_UserName = FormatUsername($this->fields['uname']);
$this->M_Scores = $this->fields['scores'];
$this->M_Face = $this->fields['face'];
$this->M_Rank = $this->fields['rank'];
$this->M_Spacesta = $this->fields['spacesta'];
$sql = "Select titles From #@__scores where integral<={$this->fields['scores']} order by integral desc";
$scrow = $dsql->GetOne($sql);
$this->fields['honor'] = $scrow['titles'];
$this->M_Honor = $this->fields['honor'];
if($this->fields['matt']==10) $this->isAdmin = TRUE;
$this->M_UpTime = $this->fields['uptime'];
$this->M_ExpTime = $this->fields['exptime'];
$this->M_JoinTime = MyDate('Y-m-d',$this->fields['jointime']);
if($this->M_Rank>10 && $this->M_UpTime>0){
$this->M_HasDay = $this->Judgemember();
}
if( !$formcache )
{
SetCache($this->memberCache, $this->M_ID, $this->fields, 1800);
}
}else{
$this->ResetUser();
}
}
}
我们只要修改DedeUserID
和DedeUserID__ckMd5
为1和1对应的__ckMd5
就可以用admin
登录前台。
再看一下上面代码的这一句:
$this->M_ID = intval($this->M_ID);
所以这个DedeUserID不一定要为1,也可以为01,0001
等等,是要intval(DedeUserID)==1
即可。
此处不再复述环境搭建,可参考
https://www.cnblogs.com/masses0x1/articles/14433241.html
5.7版本首页打开缓慢,可删除广告模块和生成静态页面来提高速度。
注册会员名为00001。会员名不一定要为00001,会员名通过intval()
函数转化后等于1就可以。
需访问uploads/member/index.php?uid=00001
才能生成last_vid
。记住last_vid
和last_vid_cMd5
的值。
此处用的cookie管理插件是“Cookie Quick Manager”。
DedeUserID
和DedeUserID__ckMd5
分别将last_vid
和last_vid_ckMd5
的值赋给cookie中的DedeUserID
和DedeUserID_ckMd5
。
此处修改密码需要原密码,原密码的获取方法可通过另一个漏洞获取,链接如下:
https://www.cnblogs.com/masses0x1/articles/14433241.html
到此已获取后台密码,感谢师傅们阅读!