Discuz - 6 1 7 0 - 安装SupeSite后导致安全漏洞

                 

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

涉及安全漏洞的版本

Discuz! 6.1
Discuz! 7.0
SupeSite 6.0 X-Space 4.0 UC
SupeSite 6.0.1 X-Space 4.0.1 UC

原因——SupeSite X-Space UC部分

Discuz!在安装SupeSite X-Space UC版之后,会在Discuz!的forums表中增加两个字段,Discuz! 6.1增加字段如下:
--- cdb_forums.6.1.discuz.sql
+++ cdb_forums.6.1.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 ;
Discuz! 7.0增加字段如下:
--- cdb_forums.7.0.supesite.sql
+++ cdb_forums.7.0.discuz.sql
@@ -32,17 +32,15 @@
   `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,
   `allowtag` tinyint(1) NOT NULL default '1',
   `modworks` tinyint(1) unsigned NOT NULL,
   `allowglobalstick` 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 COLLATE=utf8_bin AUTO_INCREMENT=35 ;
其中allowpost字段用于SupeSite X-SpaceUC的网站管理平台中“论坛相关设置”菜单的“论坛版块”菜单项的“是否允许导入”列。当选中“是否允许导入”复选框时,allowpost字段的值为1,当取消“是否允许导入”复选框时,allowpost字段的值为0。

原因——Discuz!部分

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

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

SupeSite X-Space 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,为解决该缺陷,同时不影响其他功能,Discuz! 6.1可以通过如下补丁解决。
--- common.inc.6.1.discuz.php
+++ common.inc.6.1.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) {

Discuz! 7.0可以通过如下补丁解决。

--- common.inc.7.0.supesite.php
+++ common.inc.7.0.discuz.php
@@ -276,28 +276,28 @@
 
 $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;
 
 $modthreadkey = isset($modthreadkey) && $modthreadkey == modthreadkey($tid) ? $modthreadkey : '';
 $auditstatuson = $modthreadkey ? true : false;
 
 if(!empty($tid) || !empty($fid)) {
        if(empty($tid)) {
-               $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.allowfeed, f.recyclebin,f.modnewposts, f.jammer, f.disablewatermark, f.inheritedmod,f.autoclose, f.forumcolumns, f.threadcaches, f.alloweditpost, f.simple,f.modworks, f.allowtag, f.allowglobalstick, ff.* $accessadd1 $modadd1,f.fid AS fid
+               $forum = $db->fetch_first("SELECT f.fid, f.*, 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.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.allowfeed, f.recyclebin, f.modnewposts, f.jammer, f.disablewatermark,f.inheritedmod, f.autoclose, f.forumcolumns, f.threadcaches,f.alloweditpost, f.simple, f.modworks, f.allowtag, f.allowglobalstick,ff.* $accessadd1 $modadd1, f.fid AS fid
+               $forum =$db->fetch_first("SELECT t.tid,t.closed,".(defined('SQL_ADD_THREAD') ? SQL_ADD_THREAD : '')." f.*,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', 'threadsorts', 'digestcredits', 'postattachcredits','getattachcredits') as $key) {

后记

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

[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~7.0 安装SupeSite后导致安全漏洞

Discuz! 6.1 不修改模板在贴子上增加收藏按钮

Discuz! 6.1 cpmsg函数在IE下和Firefox下表现不一致

           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

猜你喜欢

转载自blog.csdn.net/gdfjhc/article/details/87709484
今日推荐