Discuz! 6.1 - 安装SupeSite后导致安全漏洞

 

Discuz! 6.1 - 安装SupeSite后导致安全漏洞

原因——SupeSite 6.0 X-Space 4.0 UC部分

Discuz! 6.1在安装SupeSite 6.0 X-Space 4.0 UC版之后,会在Discuz! 6.1的forums表中增加两个字段
--- cdb_forums.discuz.sql
+++ cdb_forums.supesite.sql
@@ -30,15 +30,17 @@
   `modnewposts` tinyint(1) NOT NULL default '0',
   `jammer` tinyint(1) NOT NULL default '0',
   `disablewatermark` tinyint(1) NOT NULL default '0',
   `inheritedmod` tinyint(1) NOT NULL default '0',
   `autoclose` smallint(6) NOT NULL default '0',
   `forumcolumns` tinyint(3) unsigned NOT NULL default '0',
   `threadcaches` tinyint(1) NOT NULL default '0',
   `alloweditpost` tinyint(1) unsigned NOT NULL default '1',
   `simple` tinyint(1) unsigned NOT NULL,
   `modworks` tinyint(1) unsigned NOT NULL,
   `allowtag` tinyint(1) NOT NULL default '1',
+  `updateline` int(10) NOT NULL default '0',
+  `allowpost` tinyint(1) NOT NULL default '0',
   PRIMARY KEY  (`fid`),
   KEY `forum` (`status`,`type`,`displayorder`),
   KEY `fup` (`fup`)
 ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
其中allowpost字段用于SupeSite 6.0 X-Space 4.0 UC的网站管理平台中“论坛相关设置”菜单的“论坛版块”菜单项的“是否允许导入”列。当选中“是否允许导入”复选框时,allowpost字段的值为 1,当取消“是否允许导入”复选框时,allowpost字段的值为0。

原因——Discuz! 6.1部分

Discuz! 6.1对于用户能否在版面发表主题主要涉及三个设置:
  1. 用户所在用户组是否允许发表主题
  2. 用户在该版面是否拥有发表主题特殊权限
  3. 版面是否允许用户所在的用户组发表主题
这三个设置的判断顺序如下:
  • 用户所在的用户组不允许发表主题——不能发表主题
  • 用户所在的用户组允许发表主题
    • 用户在该版面拥有允许发表主题的特殊权限——能发表主题
    • 用户在该版面拥有禁止发表主题的特殊权限——不能发表主题
    • 用户在该版面拥有发表主题的特殊权限
      • 版面允许用户所在的用户组发表主题——能发表主题
      • 版面不允许用户所在的用户组发表主题——不能发表主题
这三个设置在数据库中的来源如下:
  1. 用户所在用户组是否允许发表主题
    • 数据库usergroups表的allowpost字段,值为1时代表允许发表主题,值为0时代表不允许发表主题。
  2. 用户在该版面是否拥有发表主题特殊权限
    • 数据库members表的accessmasks字段,值为0时代表该用户在所有版面都不拥有发表主题特殊权限,值为1时代表该用户在某个版面拥有发表主题特殊权限。
    • 数据库access表的allowpost字段,值为0时代表不拥有发表主题的特殊权限,值为1时代表拥有允许发表主题的特殊权发,值为-1时代表拥有不允许发表主题的特殊权限。
  3. 版面是否允许用户所在的用户组发表主题
    • 数据库forumfields表的postperm字段,值以"/t"为分隔符号连接允许用户发表主题的用户组的ID。
这三个设置在程序中的来源如下:
  1. 用户所在用户组是否允许发表主题
    • 在/forumdata/cache/usergroup_[usergroup id].php缓存文件中的$allowpost变量。其中[usergroup id]代表用户所在用户组的编号,值为'1'时代表允许发表主题,值为'0'时代表不允许发表主题。
  2. 用户在该版面是否拥有发表主题特殊权限
    • 在common.inc.php文件的131行~179行,赋值给$accessmasks变量,值为'0'时代表该用户在所有版面都不拥有发表主题特殊权限,值为'1'时代表该用户在某个版面拥有发表主题特殊权限。
    • 在common.inc.php文件的201行~204行,依据$accessmasks变量SQL语句相关段落赋值给$accessadd1和$accessadd2变量。
    • 在common.inc.php文件的271行~283行,使用$accessadd1和$accessadd2变量生成SQL语句查询出$forum数 组,其中$forum['allowpost']代表用户在该版面是否拥有发表主题特殊权限,值为NULL时代表用户在该版面不拥有任何特殊权限,也就不 拥有发表主题的特殊权限,值为0时代表不拥有发表主题的特殊权限,值为1时代表拥有允许发表主题的特殊权发,值为-1时代表拥有不允许发表主题的特殊权 限。
  3. 版面是否允许用户所在的用户组发表主题
    • 在viewthread.php文件的206行,当用户在该版面不拥有发表主题的特殊权限时,使用forumperm($forum['postperm']))分解允许用户发表主题的用户组的ID,然后在用户的用户组ID以及扩展组ID列表中查找是否包含。

结果——互相作用导致的漏洞

SupeSite 6.0 X-Space 4.0 UC在forums表中增加的allowpost字段与access表中的allowpost字段在查询时同时影响查询结果的$forum['allowpost']变量,情况如下:
  • 用户在该版面拥有特殊权限,但是用户在该版面不拥有发表主题的特殊权限,$forum['allowpost']不变为'0',不受影响
  • 用户在该版面拥有特殊权限,但是用户在该版面拥有允许发表主题的特殊权限,$forum['allowpost']不变为'1',不受影响
  • 用户在该版面拥有特殊权限,但是用户在该版面拥有禁止发表主题的特殊权限,$forum['allowpost']不变为'-1',不受影响
  • 用户在该版面不拥有任何特殊权限
    • forums表中allowpost字段的值为0,$forum['allowpost']从NULL变为'0'
      • /include/newthread.inc.php第31行,empty($forum['allowpost']),值不变为true,不受影响
      • /include/newthread.inc.php第37行,$forum['allowpost'] == -1,值不变为false,不受影响
      • /include/newtrade.inc.php第30行,empty($forum['allowpost']),值不变为true,不受影响
      • /include/newtrade.inc.php第36行,$forum['allowpost'] == -1,值不变为false,不受影响
      • /wap/include/post.inc.php第50行,empty($forum['allowpost']),值不变为true,不受影响
      • /forumdisplay.php第421行,$forum['allowpost'] == 1,值不变为false,不受影响
      • /forumdisplay.php第423行,$forum['allowpost'] != -1,值不变为true,不受影响
      • /post.php第276行,$forum['allowpost'] == -1,值不变为false,不受影响
      • /post.php第282行,$forum['allowpost'] == -1,值不变为false,不受影响
      • /post.php第285行,$forum['allowpost'] == -1,值不变为false,不受影响
      • /viewthread.php第206行第1处,$forum['allowpost'] != -1,值不变为true,不受影响
      • /viewthread.php第206行第2处,|| $forum['allowpost'],值不变为false,不受影响
    • forums表中allowpost字段的值为1,$forum['allowpost']从NULL变为'1'
      • /include/newthread.inc.php第31行,empty($forum['allowpost']),值从true变为false,受影响
      • /include/newthread.inc.php第37行,$forum['allowpost'] == -1,值不变为false,不受影响
      • /include/newtrade.inc.php第30行,empty($forum['allowpost']),值从true变为false,受影响
      • /include/newtrade.inc.php第36行,$forum['allowpost'] == -1,值不变为false,不受影响
      • /wap/include/post.inc.php第50行,empty($forum['allowpost']),值从true变为false,受影响
      • /forumdisplay.php第421行,$forum['allowpost'] == 1,值从false变为true,受影响
      • /forumdisplay.php第423行,$forum['allowpost'] != -1,值不变为true,不受影响
      • /post.php第276行,$forum['allowpost'] == -1,值不变为false,不受影响
      • /post.php第282行,$forum['allowpost'] == -1,值不变为false,不受影响
      • /post.php第285行,$forum['allowpost'] == -1,值不变为false,不受影响
      • /viewthread.php第206行第1处,$forum['allowpost'] != -1,值不变为true,不受影响
      • /viewthread.php第206行第2处,|| $forum['allowpost'],值从false变为true,受影响
受影响处会导致的安全漏洞如下:
  • /include/newthread.inc.php第31行,当用户所在的用户组允许发表主题,用户在该版面拥有发表主题的特殊权限,版面不允许用户所在的用户组发表主题时,应该不能发表主题。但是forums表中allowpost字段的值为1时,此处程序认为用户在该版面拥有允许发表主题的特殊权限,因此能发表主题
  • /include/newtrade.inc.php第30行,当用户所在的用户组允许发表主题,用户在该版面拥有发表主题的特殊权限,版面不允许用户所在的用户组发表主题时,应该不能发表主题。但是forums表中allowpost字段的值为1时,此处程序认为用户在该版面拥有允许发表主题的特殊权限,因此能发表主题
  • /wap/include/post.inc.php第50行,当用户所在的用户组允许发表主题,用户在该版面拥有发表主题的特殊权限,版面不允许用户所在的用户组发表主题时,应该不能发表主题。但是forums表中allowpost字段的值为1时,此处程序认为用户在该版面拥有允许发表主题的特殊权限,因此能发表主题
  • /forumdisplay.php第421行,当用户所在的用户组允许发表主题,用户在该版面拥有发表主题的特殊权限,版面不允许用户所在的用户组发表主题时,应该不能发表主题,所以不显示“新贴”以及特殊主题链接。但是forums表中allowpost字段的值为1时,此处程序认为用户在该版面拥有允许发表主题的特殊权限,因此能发表主题,所以显示“新贴”以及特殊主题链接。
  • /viewthread.php第206行第2处,当用户所在的用户组允许发表主题,用户在该版面拥有发表主题的特殊权限,版面不允许用户所在的用户组发表主题时,应该不能发表主题,所以不显示“新贴”以及特殊主题链接。但是forums表中allowpost字段的值为1时,此处程序认为用户在该版面拥有允许发表主题的特殊权限,因此能发表主题,所以显示“新贴”以及特殊主题链接。

补丁

由于该问题涉及Discuz!的全局包含文件/include/common.inc.php,为解决该缺陷,同时不影响其他功能,可以通过如下补丁解决。
--- common.inc.discuz.php
+++ common.inc.supesite.php
@@ -261,28 +261,28 @@
 }
 
 $auditstatuson = !empty($mod) && $mod == 'edit' && in_array($adminid, array(1, 2, 3)) && $allowmodpost ? true : false;
 
 $page = isset($page) ? max(1, intval($page)) : 1;
 $tid = isset($tid) && is_numeric($tid) ? $tid : 0;
 $fid = isset($fid) && is_numeric($fid) ? $fid : 0;
 $typeid = isset($typeid) ? intval($typeid) : 0;
 
 if(!empty($tid) || !empty($fid)) {
        if(empty($tid)) {
-               $forum = $db->fetch_first("SELECT f.fid, f.*, ff.* $accessadd1 $modadd1, f.fid AS fid
+               $forum = $db->fetch_first("SELECT f.fid, f.fup, f.type, f.name, f.status, f.displayorder, f.styleid, f.threads, f.posts, f.todayposts, f.lastpost, f.allowsmilies, f.allowhtml, f.allowbbcode, f.allowimgcode, f.allowmediacode, f.allowanonymous, f.allowshare, f.allowpostspecial, f.allowspecialonly, f.alloweditrules, f.recyclebin, f.modnewposts, f.jammer, f.disablewatermark, f.inheritedmod, f.autoclose, f.forumcolumns, f.threadcaches, f.alloweditpost, f.simple, f.modworks, f.allowtag, ff.* $accessadd1 $modadd1, f.fid AS fid
                        FROM {$tablepre}forums f
                        LEFT JOIN {$tablepre}forumfields ff ON ff.fid=f.fid $accessadd2 $modadd2
                        WHERE f.fid='$fid'");
        } else {
-               $forum = $db->fetch_first("SELECT t.tid, t.closed,".(defined('SQL_ADD_THREAD') ? SQL_ADD_THREAD : '')." f.*, ff.* $accessadd1 $modadd1, f.fid AS fid
+               $forum = $db->fetch_first("SELECT t.tid, t.closed,".(defined('SQL_ADD_THREAD') ? SQL_ADD_THREAD : '')." f.fid, f.fup, f.type, f.name, f.status, f.displayorder, f.styleid, f.threads, f.posts, f.todayposts, f.lastpost, f.allowsmilies, f.allowhtml, f.allowbbcode, f.allowimgcode, f.allowmediacode, f.allowanonymous, f.allowshare, f.allowpostspecial, f.allowspecialonly, f.alloweditrules, f.recyclebin, f.modnewposts, f.jammer, f.disablewatermark, f.inheritedmod, f.autoclose, f.forumcolumns, f.threadcaches, f.alloweditpost, f.simple, f.modworks, f.allowtag, ff.* $accessadd1 $modadd1, f.fid AS fid
                        FROM {$tablepre}threads t
                        INNER JOIN {$tablepre}forums f ON f.fid=t.fid
                        LEFT JOIN {$tablepre}forumfields ff ON ff.fid=f.fid $accessadd2 $modadd2
                        WHERE t.tid='$tid'".($auditstatuson ? '' : " AND t.displayorder>='0'")." LIMIT 1");
                $tid = $forum['tid'];
        }
 
        if($forum) {
                $fid = $forum['fid'];
                $forum['ismoderator'] = !empty($forum['ismoderator']) || $adminid == 1 || $adminid == 2 ? 1 : 0;
                foreach(array('postcredits', 'replycredits', 'threadtypes', 'digestcredits', 'postattachcredits', 'getattachcredits') as $key) {

后记

开源有助于程序接受更广泛的代码复审,及时发现安全隐患并改进,本bug源于SupeSite 6.0 X-Space 4.0 UC,由于SupeSite 6.0 X-Space 4.0 UC是闭源软件,因此补丁从Discuz! 6.1入手,并非治本之策。

[Discuz! - 官方网站]

http://www.discuz.net/

[Discuz! - 常见问题]

Discuz! 6.1 从GBK编码转为UTF-8编码
Discuz! 6.1 多语言翻译工作范围
Discuz! 6.1 兼容问题

Discuz! 6.1 发送HTML格式电子邮件

Discuz! 6.1 安装SupeSite后导致安全漏洞


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值