Discuz!官方免费开源建站系统

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索

[不是BUG] SS7.0 + DISCUZ 7.0 有漏洞??? 貌似这样会导致用户超出权限

[复制链接]
xbox1 发表于 2009-3-18 02:15:10 | 显示全部楼层 |阅读模式
来源是:http://blog.csdn.net/hu_zhenghui/archive/2008/12/22/3585540.aspx

貌似这样会导致用户超出权限,,,斑竹检查一下是不是哦。。。
紫琼 发表于 2009-3-18 11:25:41 | 显示全部楼层
提交问题不要上来就丢个地址,请把问题描述清楚了~
回复

使用道具 举报

 楼主| xbox1 发表于 2009-3-18 13:24:25 | 显示全部楼层
这个东西比较麻烦,其实就是通过一种特定设置可以让用户超出权限。。。
我只想知道解决这个问题没有
回复

使用道具 举报

 楼主| xbox1 发表于 2009-3-18 13:29:26 | 显示全部楼层
涉及安全漏洞的版本
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-Space UC的网站管理平台中“论坛相关设置”菜单的“论坛版块”菜单项的“是否允许导入”列。当选中“是否允许导入”复选框时,allowpost字段的值为 1,当取消“是否允许导入”复选框时,allowpost字段的值为0。

原因——Discuz!部分

Discuz!对于用户能否在版面发表主题主要涉及三个设置:

用户所在用户组是否允许发表主题
用户在该版面是否拥有发表主题特殊权限
版面是否允许用户所在的用户组发表主题
这三个设置的判断顺序如下:

用户所在的用户组不允许发表主题——不能发表主题
用户所在的用户组允许发表主题
用户在该版面拥有允许发表主题的特殊权限——能发表主题
用户在该版面拥有禁止发表主题的特殊权限——不能发表主题
用户在该版面不拥有发表主题的特殊权限
版面允许用户所在的用户组发表主题——能发表主题
版面不允许用户所在的用户组发表主题——不能发表主题
这三个设置在数据库中的来源如下:

用户所在用户组是否允许发表主题
数据库usergroups表的allowpost字段,值为1时代表允许发表主题,值为0时代表不允许发表主题。

用户在该版面是否拥有发表主题特殊权限
数据库members表的accessmasks字段,值为0时代表该用户在所有版面都不拥有发表主题特殊权限,值为1时代表该用户在某个版面拥有发表主题特殊权限。

数据库access表的allowpost字段,值为0时代表不拥有发表主题的特殊权限,值为1时代表拥有允许发表主题的特殊权发,值为-1时代表拥有不允许发表主题的特殊权限。
版面是否允许用户所在的用户组发表主题
数据库forumfields表的postperm字段,值以"\t"为分隔符号连接允许用户发表主题的用户组的ID。

这三个设置在程序中的来源如下:

用户所在用户组是否允许发表主题
在/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! - 官方网站]
回复

使用道具 举报

紫琼 发表于 2009-3-18 14:01:02 | 显示全部楼层
从 SupeSite 6.0.1 uc 版本开始这些字段前面都增加了 supe_ 前缀了,所以不会出现你说的问题了,你说的旧版本的就不会考虑改了,直接升级到 SupeSite 6.0.1 uc 就 ok 了。
回复

使用道具 举报

fhg007 发表于 2009-3-26 20:06:24 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

紫琼 发表于 2009-3-27 10:25:00 | 显示全部楼层
6# fhg007
从 SupeSite 6.0.1 uc 版本开始这些字段前面都增加了 supe_ 前缀
看上面的说明,只要你把 ss 升级到 SupeSite 6.0.1 uc 版本就没问题了。
回复

使用道具 举报

xyaoyule 发表于 2009-4-9 22:00:31 | 显示全部楼层
不行呀,

我的也出现那问题了

为什么编辑器会自动出现HTML代码
回复

使用道具 举报

 楼主| xbox1 发表于 2009-4-10 05:36:24 | 显示全部楼层
貌似把上面的方法改进一下,就完成官方说的升级OK了,其实不是。。。。

GOOGLE搜一下,方法已经很多了。。。哎。。。
回复

使用道具 举报

fhg007 发表于 2009-4-11 15:42:26 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|Discuz! 官方站 ( 皖ICP备16010102号 )star

GMT+8, 2024-11-15 21:46 , Processed in 0.028040 second(s), 4 queries , Gzip On, Redis On.

Powered by Discuz! X3.4

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表