BBSMAX 4.x 论坛程序登陆任意用户,取得用户密码信息漏洞

来源:岁月联盟 编辑:老鹰 时间:2010-05-19

影响版本:
BBSMAX 4.x

程序介绍:

BBSMAX 是国内发展最早的基于.net技术构建的bbs,在leobbs独步天下、微软.net刚刚诞生的时 候,BBSMAX就开始发展了(当时名为 nowboard),历经多年发展,从个人开发到团队开发,从业余开发到全职开发,BBSMAX经历了质的蜕变。

漏洞分析:

在文件 register.aspx.cs 中

protected void Page_Load(object sender, EventArgs e)
{
    string str = string.Empty;
    str = base._Request.Get("active", Method.Get);
    if (!string.IsNullOrEmpty(str))
    {
        if (BOBase<UserBO>.Instance.ActivingUser(str))    //激活用户
        {
            base.ShowSuccess("恭喜!您的账号" + base.My.Username + "已成功激活。", BbsRouter.GetUrl("default"));
        }

在激活用户的过程代码如下:

public bool ActivingUser(string activeSerial)
{
    int userID = 0;
    userID = this.GetUserIdByActiveSerial(activeSerial);
    User user = null;
    if (userID > 0)
    {
        user = BOBase<UserBO>.Instance.GetUser(userID);
    }
    if (user != null)
    {
        DaoBase<UserDao>.Instance.ActivingUsers(new int[] { userID }, true);
        DaoBase<UserDao>.Instance.ValidateUserEmail(userID, user.Email);
        user.EmailValidated = true;
        this.SetUserLogin(user, null, user.Password, false);
        return true;
    }
    return false;
}

对传入的字符串进行解密,取得用户ID,然后根据ID直接登陆。
解密代码如下:

public int GetUserIdByActiveSerial(string serial)
{
    Regex regex = new EmailActiveCodeRegex();
    string s = "";
    if (!string.IsNullOrEmpty(serial))
    {
        try
        {
            serial = SecurityUtil.DesDecode(serial);
        }
        catch
        {
            return 0;
        }
        if (!string.IsNullOrEmpty(serial) && regex.IsMatch(serial))
        {
            DateTime time;
            int num;
            GroupCollection groups = regex.Match(serial).Groups;
            string str = groups[1].Value;
            s = groups[2].Value;
            if (!DateTime.TryParse(s, out time))
            {
                return 0;
            }
            TimeSpan span = (TimeSpan) (DateTimeUtil.Now - time);
            double totalHours = span.TotalHours;
            int.TryParse(str, out num);
            return num;
        }
    }
    return 0;
}

是先通过SecurityUtil.DesDecode 解密我们传入的str后,再用正则取得用户ID。问题主要出在解密代码那里。我们来看一下:

public static string DesDecode(string data)
{
    byte[] buffer3;
    byte[] bytes = Encoding.ASCII.GetBytes("!bbsmax!");
    byte[] rgbIV = Encoding.ASCII.GetBytes("!zzbird!");
    try
    {
        buffer3 = Convert.FromBase64String(data);
    }
    catch
    {
        return null;
    }
    DESCryptoServiceProvider provider = new DESCryptoServiceProvider();
    MemoryStream stream = new MemoryStream(buffer3);
    CryptoStream stream2 = new CryptoStream(stream, provider.CreateDecryptor(bytes, rgbIV), CryptoStreamMode.Read);
    StreamReader reader = new StreamReader(stream2);
    return reader.ReadToEnd();
}

通过FromBase64String 转换,然后对转换后的字符串进行3DES解密,但问题就是出在这里。3DES的密码居然是固定在程序里的。
因此,我们可直接复制他的解密程序来构造我们的 active 字符串,从而达到登陆任意用户账号的目的。
取得用户密码信息的原理也是一样,BBSMAX的Cookie信息也是通过那个函数进入加解密,我们通过解密用户登陆后的Cookie后,取得用户密码。

解决方案:
厂商补丁:
BBSMAX
-----------
目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:
http://bbs.bbsmax.com/products_release/list-1.html