7.4 Discuz! 管理员复制提权技术

使用Discuz! 建设论坛方便、快捷,不仅能够满足功能需求,而且安全性在同类软件中是最高的,因此深受广大用户的喜爱。

网络攻防技术研究的核心就是获取用户数据,以及获得系统的完全控制权限。本节主要针对如何获得Discuz! 数据库管理员权限展开研究。在某些情况下,我们完全可以获取一个WebShell。在获取WebShell的情况下,可以进一步获取MySQL等有关数据库连接的用户名和密码等信息。由于Discuz! 特有的加密方式,即使通过SQL注入猜解获取了Discuz! 论坛管理员的密码,也是无法破解的。因此,如何通过操作数据库来获得管理员权限尤为重要。本节研究的技术可以应用在以下两个方面。

搭建的实验环境如下。

7.4.1 Discuz! 论坛的加密方式

Discuz! 6.X及之后的Discuz! 7.0都采用MD5多重加密,其加密函数有checkmd5和authcode。如果以默认方式安装Discuz!,这些函数存在于“include”目录下的global.func.Php文件中。

采用salt方式随机获得一个字符串,然后对明文密码采取MD5加密,再与随机字符串连接起来,对连接后的字符串进行MD5加密。加密密码的函数为md5(md5 ($newpw).$salt)。其中,$salt为随机的,返回的字符串为$hash,大大提高了用户密码的安全性。

1.checkmd5函数

checkmd5函数的代码如下。

function checkmd5($md5, $verified, $salt = '') { 
 if(md5($md5.$salt) == $verified) { 
  $result = !empty($salt) ? 1 : 2; 
 } elseif(empty($salt)) { 
  $result = $md5 == $verified ? 3 : ((strlen($verified) == 16 && 
substr($md5, 8, 16) == $verified) ? 4 : 0); 
 } else { 
  $result = 0; 
 } 
 return $result; 
} 

以上代码主要度对密码进行检测,有3个参数,分别是“@param string $md5”、“@param string $verified”、“@param string $salt”。返回值为0表示失败;为1表示采用MD5 with salt方式;为2表示采用Dual MD5方式;为3表示采用正常的MD5加密方式;为4表示采用MD5-16方式。

2.authcode函数

authcode函数的代码如下。

function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) { 
 
 $ckey_length = 4; 
 $key = md5($key ? $key : $GLOBALS['discuz_auth_key']); 
 $keya = md5(substr($key, 0, 16)); 
 $keyb = md5(substr($key, 16, 16)); 
 $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0,  
$ckey_length): substr(md5(microtime()), -$ckey_length)) : ''; 
 
 $cryptkey = $keya.md5($keya.$keyc); 
 $key_length = strlen($cryptkey); 
 
 $string = $operation == 'DECODE' ? base64_decode(substr($string,  
$ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr 
(md5($string.$keyb), 0, 16).$string; 
 $string_length = strlen($string); 
 
 $result = ''; 
 $box = range(0, 255); 
 
 $rndkey = array(); 
 for($i = 0; $i <= 255; $i++) { 
  $rndkey[$i] = ord($cryptkey[$i % $key_length]); 
 } 
 
 for($j = $i = 0; $i < 256; $i++) { 
  $j = ($j + $box[$i] + $rndkey[$i]) % 256; 
  $tmp = $box[$i]; 
    $box[$i] = $box[$j]; 
  $box[$j] = $tmp; 
 } 
 
 for($a = $j = $i = 0; $i < $string_length; $i++) { 
  $a = ($a + 1) % 256; 
  $j = ($j + $box[$a]) % 256; 
  $tmp = $box[$a]; 
  $box[$a] = $box[$j]; 
  $box[$j] = $tmp; 
  $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256])); 
 } 
 
 if($operation == 'DECODE') { 
  if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 
0) &amp;&amp; substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 
16)) { 
   return substr($result, 26); 
  } else { 
   return ''; 
  } 
 } else { 
  return $keyc.str_replace('=', '', base64_encode($result)); 
 } 
 
} 

以上代码主要用来加密或者解密用户信息,其参数的意义如下。

$ckey_length为随机密钥长度,取值范围0~32。加入随机密钥,可以使密文没有任何规律,即使原文和密钥完全相同,加密结果也每次都会不同,进而使破解难度大大提高。$ckey_length取值越大,密文变动越大,密文变化为16的$ckey_length次方。此值为0时,不产生随机密钥。

7.4.2 使用MySQL-Front管理MySQL数据库

下面讨论使用MySQL-Front管理MySQL数据库的相关内容。

1.设置MySQL-Front

MySQL-Front是一款MySQL客户端管理软件,可以对MySQL数据库实现图形界面管理,软件下载地址为http://www.mysqlfront.de/download.html。

安装MySQL-Front后直接运行,如图7-21所示。“信息”标签页主要用于显示名称,可以随意设置。主要的设置在“注册”标签页进行,“用户”和“密码”需要手工输入,“数据库”可以手工输入,也可以通过程序自动获取。设置完毕,单击“确定”按钮,保存数据库设置并回到MySQL的“打开登录信息”窗口。

0269-1

图7-21 设置MySQL-Front

说明

(1)管理MySQL数据库的软件很多,也可以通过phpMyAdmin进行在线管理,其下载地址为http://www.phpmyadmin.net。

(2)本例中使用客户端软件来管理MySQL数据库是因为其方便快捷。当然,熟悉MySQL命令的朋友也可以手工在命令提示符下执行数据库操作。

2.连接MySQL数据库

在“打开登录信息”窗口选择刚才设置的MySQL数据并打开,如图7-22所示,在MySQL-Front中常用的4个按钮为“对象浏览器”、“数据浏览器”、“SQL编辑器”和“图表”。“对象浏览器”按钮主要用来浏览有哪些表,“数据浏览器”按钮主要用来查看选中数据库的表中的数据,“SQL编辑器”按钮主要用来执行SQL语句,“图表”按钮主要用来与“对象浏览器”按钮进行切换。更多好用的功能和技巧需要读者自己揣摩,就不在此赘述了。

0270-1

图7-22 打开MySQL数据库

7.4.3 实施管理员复制

下面我们实施管理员复制。

1.注册网站用户

在实施管理员复制前,需要在网站注册一个用户名。在本例中,注册普通用户“cxb”,密码为“test”。注册成功后,使用该用户进行登录,如图7-23所示。

0270-2

图7-23 使用注册账号登录网站

2.通过MySQL-Front查看已注册用户信息

在MySQL-Front中查看已经注册的用户信息。选中Discuz!论坛的用户注册表“*_members”,其中“*”为安装时设置的名称。如图7-24所示,在本例中为“antian_ members”,该表中保存的是用户注册的信息,单击“数据浏览器”按钮,可以看到该用户的一些详细注册信息。

0271-1

图7-24 查看选定用户的详细注册信息

3.修改普通用户为管理员用户

在antian_members表中将用户“cxb”的“adminid”值由“0”修改为“1”,将“groupid”的值由“12”修改为“1”,然后单击发布按钮使修改生效,至此已经将普通用户“cxb”变成管理员用户。在登录的网页中刷新一下,再次查看用户个人信息,如图7-25所示,用户“cxb”的用户组已经升级为“Administrator”,可以行使管理员权限了。

0271-2

图7-25 普通用户已经升级为管理员

7.4.4 管理员密码丢失解决方案

如果管理员将密码丢失,会造成很多严重的问题,下面给出管理员密码丢失的解决方案。

1.修改管理员密码为已知用户密码

使用MySQL-Front打开myuc_members表后,单击工具条下面的“数据浏览器”按钮,查看myuc_members表中的数据,如图7-26所示,先将用户“admin”的“password”值复制到本地进行备份,以备出现错误后进行恢复。将已知用户的密码值(“password”中的值)复制到用户“admin”的数据中,以替代原来的值。

0272-1

图7-26 修改管理员密码为已知用户密码

2.修改salt

在Discuz! 论坛中,用户的密码不是普通的加密,而是经过变异的加密,因此还需要保证管理员的密码与已知用户的salt一致。如图7-27所示,将管理员与已知用户的salt修改成相同的值。

0272-2

图7-27 修改salt的值

3.修改安全问题答案

Discuz! 论坛的登录模块单独设置了安全提问,如图7-28所示。一共有7个安全提问,用户注册成功后可以在个人中心的“密码和安全问题”中进行设置,每一个安全提问根据答案生成一串8位的加密字符串,密码不同,安全字符串也不同。因此,如果要让管理员用户使用普通用户的安全提问,则需要将管理员的“secques”设置成普通用户的“secques”,反之,则需要将普通用户的“secques”设置成管理员的“secques”。如图7-29所示,将已知用户的“secques”替换管理员的“secques”,然后使用普通用户的安全提问代替管理员的安全提问进行登录。

0273-1

图7-28 安全提问

0273-2

图7-29 修改安全提问secques值

至此,有关Discuz! 论坛管理员与普通用户之间的身份转换已经完成,使用修改后的密码和问题答案即可登录。登录后,用户身份为管理员,如图7-30所示,可以对论坛系统进行管理。

0273-3

图7-30 登录后台进行管理

7.4.5 小结与探讨

本节探讨了Discuz!论坛的加密方法,通过实际案例讲解了如何通过操作MySQL数据库来更改用户身份,即通过修改普通用户的adminid、groupid、secques和password的值,可以使“普通用户”变成“管理员”,行使管理员权限。同时,该方法也适用于管理员丢失或者忘记了管理密码的情况。通过该方法可以重新设置密码,并行使管理员权限。

写完本节内容后,笔者又发现该管理员密码可以直接使用PasswordPro进行破解,由于篇幅关系就不在本节进行探讨了。

关于Discuz!论坛的安全问题还有很多话题,如通过脚本来嗅探或者记录用户名和密码。在Discuz!论坛数据库中,用户密码字段生成的是密文,网上也有一些脚本可以直接用来记录用户的登录密码。