当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2012-05440

漏洞标题:DZ升级/DX转换程序考虑不当导致用户遗留信息被黑客利用

相关厂商:Discuz!

漏洞作者: horseluke

提交时间:2012-03-21 14:06

修复时间:2012-03-26 14:07

公开时间:2012-03-26 14:07

漏洞类型:设计缺陷/逻辑错误

危害等级:低

自评Rank:3

漏洞状态:漏洞已经通知厂商但是厂商忽略漏洞

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2012-03-21: 细节已通知厂商并且等待厂商处理中
2012-03-26: 厂商已经主动忽略漏洞,细节向公众公开

简要描述:

(名词解析:DZ=Discuz!;DX=Discuz! X;UC=UCenter;PW=phpwind)
众所周知的是,DZ <= 6.0,PW <= 8.7的用户密码都是简单的md5,存在被拖库后被轻易暴力破解的问题。于是乎康盛在开发UC的时候,就加了salt以防止这个问题。
但是在针对DZ升级和DX转换程序中,对原有信息处理不当,会导致仍然在某些表内遗留简单md5信息。其结果就是一旦网站被攻破拖库,这些历史信息就会被黑客利用。
个人原本都不认为是什么问题的,但是以下这个链接表明,很可能已在黑产界流传:
http://weibo.com/1933769763/eDKax2duHJa (请看转发和评论)
@Hxai11 所提交的一个漏洞(http://www.wooyun.org/bugs/wooyun-2010-04146 )在这部分的细节上说明有误,商量了一下,还是独立提交一次好了。
希望DX 2.5和PW 9这两个重写代码的程序发布之前,能够妥善处理好升级脚本的问题。

详细说明:

(1)DZ <= 6.0的用户信息是存储在cdb_members表中,其password字段是简单的md5;
DZ >= 6.1后,password字段仅作为cookie的登录凭据校验,用户在每次密码修改时,均会重新生成一个无关密码的登录凭据校验;
真实的password相关信息存在UCenter cdb_uc_members表中,并且salt过;
(2)然而在升级到需要UC的DZ(比如DZ 7.0)时候,针对将cdb_members导入到UCenter cdb_uc_members的升级脚本只是顾着往cdb_uc_members的password加salt,并没有对cdb_members的password进行无害化处理;
这样的结果是,升级过后,如果老用户没有修改密码,这个遗留的md5会一直存在cdb_members中。
(3)更严重的是,DX的转换脚本会原封不动地将DZ的cdb_members password搬动过来,同样没有进行无害化处理,结果导致DZ的问题延伸到DX。
(4)此问题主要影响的是升级到UC后一直没有修改过密码的老用户。这批用户一般对论坛早期的贡献不小,所以出现问题的话,他们也会感到很不解的......

漏洞证明:

以uid为1,密码为123(md5:202cb962ac59075b964b07152d234b70)说明。升级步骤为:
Discuz! 6.0 -> Discuz! 7.0 -> Discuz! 7.2 ->Discuz! X2
(1)安装DZ 6,此时查表

mysql> use test_dz6
Database changed
mysql> SELECT `password` FROM `cdb_members` WHERE `uid` = '1';
+----------------------------------+
| password |
+----------------------------------+
| 202cb962ac59075b964b07152d234b70 |
+----------------------------------+
1 row in set (0.00 sec)


(2)DZ 6升级到DZ 7
此时根据升级脚本,会自动安装UC。
然而在接下来的DZ cdb_members->UC cdb_uc_members过程中,没有对DZ cdb_members的password进行无害化处理。只是对UC cdb_uc_members之前的password进行了salt然后执行了插入:

120321 11:46:00	     30 Connect     root@localhost on 
......
30 Init DB test_dz6
31 Init DB test_dz6
30 Query SELECT COUNT(*) FROM cdb_members
30 Query SELECT * FROM cdb_members LIMIT 0, 5000
31 Query SELECT uid, salt, password FROM `test_dz6`.cdb_uc_members WHERE username='admin'
31 Query INSERT LOW_PRIORITY INTO `test_dz6`.cdb_uc_members SET uid='1', username='admin', password='0487ba3a48962bac0faefbf0f7274604', secques='',
email='name@domain.com', regip='hidden', regdate='1332300551', salt='882693'
31 Query INSERT LOW_PRIORITY INTO `test_dz6`.cdb_uc_memberfields SET uid='1'
30 Quit
31 Quit


结果:

mysql> SELECT `password` FROM `cdb_members` WHERE `uid` = '1';
+----------------------------------+
| password |
+----------------------------------+
| 202cb962ac59075b964b07152d234b70 |
+----------------------------------+
1 row in set (0.00 sec)
mysql> SELECT `password`, `salt` FROM `cdb_uc_members` WHERE `uid` = '1';
+----------------------------------+--------+
| password | salt |
+----------------------------------+--------+
| 0487ba3a48962bac0faefbf0f7274604 | 882693 |
+----------------------------------+--------+
1 row in set (0.00 sec)


(3)DZ 7升级到DZ 7.2
没有什么变化
(4)安装DX 2

234 Query       REPLACE INTO pre_common_member (uid, username, password, adminid, groupid, email, regdate) VALUES ('1', 'admin', '9503092fc99906246aa57a7b189c982c', '1', '1', 'admin@admin.com', '1332303242')


此时uid为1的值,已经进行了一次无害化处理:

mysql> SELECT `password` FROM `pre_common_member` WHERE `uid` = '1';
+----------------------------------+
| password |
+----------------------------------+
| 9503092fc99906246aa57a7b189c982c |
+----------------------------------+
1 row in set (0.00 sec)


(5)DZ 7.2数据导入到DX 2中
转换脚本在执行DZ cdb_members->DX pre_common_member导入过程中,由于没有对password进行无害化处理,结果md5(123)又回来了。

120321 12:22:40	    240 Query       ......
240 Query use `test_dz6`
......
240 Query use `test_dx2utf8`
240 Query TRUNCATE `test_dx2utf8`.pre_common_member
240 Query SELECT * FROM `test_dz6`.cdb_members WHERE uid>'' ORDER BY uid LIMIT 1000
......
240 Query INSERT INTO `test_dx2utf8`.pre_common_member SET `uid`='1',`username`='admin',`password`='202cb962ac59075b964b07152d234b70',`adminid`='1',`groupid`='1',`groupexpiry`='0',`extgroupids`='',`regdate`='1332300551',`credits`='0',`email`='name@domain.com',`timeoffset`='9999',`accessmasks`='0',`allowadmincp`='1',`notifysound`='0'
......


mysql> SELECT `password` FROM `pre_common_member` WHERE `uid` = '1';
+----------------------------------+
| password |
+----------------------------------+
| 202cb962ac59075b964b07152d234b70 |
+----------------------------------+
1 row in set (0.00 sec)

修复方案:

历史问题应该得到妥善解决。包括升级脚本制作的时候,需要考虑各种历史数据、特别是敏感信息相关的处理。
就这个问题,个人曾经的临时解决方案,是:

UPDATE pre_common_member SET `password` = md5(rand());


但似乎可能存在串cookie的问题。由于时间关系,就没深入了......

版权声明:转载请注明来源 horseluke@乌云


漏洞回应

厂商回应:

危害等级:无影响厂商忽略

忽略时间:2012-03-26 14:07

厂商回复:

最新状态:

2012-03-27:感谢,此问题我们已经关注,以前的机制中,升级程序随同程序版本发布,鉴于某些老版本已经不在维护,所以我们在未来新版本中将会采用其他方案进行修正