【问题标题】:Using C# to authenticate against a vBulletin database使用 C# 对 vBulletin 数据库进行身份验证
【发布时间】:2013-06-27 09:41:07
【问题描述】:

我花了一整天的时间寻找解决问题的方法,最后决定发帖寻求帮助。 我真的不知道这是否是发布此内容的最佳地点,但也许有人可以帮助我。

所以我试图在 C# 中创建一个简单的登录表单 从数据库中获取用户名、MD5(密码)和盐时一切正常。现在我的问题是如何从我的表单输入的密码+盐进行比较。我不知道当用户在论坛上创建帐户时 vbulleting 如何存储密码,也不知道他如何生成盐,如果它是随机的,或者用户名基础,以及他进行了多少次迭代。

谁能帮帮我?

编辑:-

$vbulletin->userinfo['password'] != iif($password AND !$md5password, md5(md5($password) . $vbulletin->userinfo['salt']), '') AND
            $vbulletin->userinfo['password'] != iif($md5password, md5($md5password . $vbulletin->userinfo['salt']), '') AND
            $vbulletin->userinfo['password'] != iif($md5password_utf, md5($md5password_utf . $vbulletin->userinfo['salt']), '')

找到了,但仍然不知道他们是如何做到的,所以我可以尝试在 c# 中重现它

最好的问候, 玛格

【问题讨论】:

  • 密码的 MD5 已经被破坏了 .. 无论如何,也许 vbulletin 基础架构已记录在案?如果没有,也许可以查看源代码(PHP?)?记得验证哈希+盐密码,使用算法:hash(combine(salt, input)) == hashed。在这种情况下,我想hash 等同于md5(如前所述),但是将盐与输入结合的方法可能会有所不同,尽管通常它只是在前面。
  • 另外,与数据库无关,因为“从数据库中获取 .. 工作正常”。
  • 哦,嗯,好像我把vBulletin 与常见的 PHP 板之一混淆了......但同样的想法也成立。必须知道(或确定)哈希算法、盐组合策略和任何其他详细信息(如 HMAC,如果使用)。
  • 是的,问题不是从数据库中检索值,而是比较密码,因为无论我尝试什么方法,它们都不会匹配。
  • 即使使用此link 并提供正确的密码 + 正确的盐 + 正确的用户名,也没有任何结果有效。

标签: c# login passwords salt vbulletin


【解决方案1】:

给定代码,格式化(忽略这可能会破坏语法):

    $vbulletin->userinfo['password'] != iif($password AND !$md5password,
        md5(md5($password) . $vbulletin->userinfo['salt']), '')
AND $vbulletin->userinfo['password'] != iif($md5password,
        md5($md5password . $vbulletin->userinfo['salt']), '')
AND $vbulletin->userinfo['password'] != iif($md5password_utf,
        md5($md5password_utf . $vbulletin->userinfo['salt']), '')

这个表达式检测到“所有方法的失败”,但是因为我觉得这很难阅读,让我们通过应用 De Morgan 的隐式外部否定,将它重写为“任何方法的成功”的正匹配:

    $vbulletin->userinfo['password'] == iif($password AND !$md5password,
        md5(md5($password) . $vbulletin->userinfo['salt']), '')
OR  $vbulletin->userinfo['password'] == iif($md5password,
        md5($md5password . $vbulletin->userinfo['salt']), '')
OR  $vbulletin->userinfo['password'] == iif($md5password_utf,
        md5($md5password_utf . $vbulletin->userinfo['salt']), '')

现在,应用简化并注意 iff(x,y,z) 的工作方式与 x?y:z 类似,我们最终在 C# 中得到类似以下内容:

   storedPW == password && !md5password ? md5(md5(password) + salt) : ''
|| storedPW == md5password ? md5(md5password + salt) : ''
|| storedPw == md5password_utf ? md5(md5password_utf + salt) : ''

检查有点难看,但..不是我的代码。要实现的重要一点是模式是:

 md5(md5(password) + salt) -> storedPw

不幸的是,这个应该与 insidepro 链接中的 md5(md5($pass).$salt) 匹配 - 使用该工具时,请确保您提供的是 纯文本密码 而不是哈希来自数据库。

YMMV.

【讨论】:

  • 感谢您向我解释,它确实帮助我更好地理解它,但它仍然不起作用。就像我在 insidepro 中所说的,我从数据库中提供了纯文本密码 + 盐,但它仍然不匹配。现在这真的让我很紧张。大声笑
【解决方案2】:

所以这是我的问题的解决方案,最后我设法让它工作。

问题是C#使用所有字符串作为unicode,而vbulletin使用所有字符串作为UTF8

为了测试,我创建了一个新表单,添加了一个新文本框和一个按钮。 这无论如何都不会连接到数据库,我提供了直接从数据库中获取的盐。(为了测试)

由于已经声明 vbulleting 登录如下: md5(md5(密码)+salt)

所以要在 C# 中重现相同但使用 UTF8 的解决方案:

static public string GetMd5Sum(string str)
    {
        //vBulletin uses UTF8 as strings, so you need to pass the user input string as UTF8 also
        Encoder enc = System.Text.Encoding.UTF8.GetEncoder();

        //Create a byte[] array to store the new UTF8 string
        byte[] utf8text = new byte[str.Length];

        //Pass the string to the byte[] array
        enc.GetBytes(str.ToCharArray(), 0, str.Length, utf8text , 0, true);

        //Hash the byte[] array with our UTF8 string inside
        MD5 md5 = new MD5CryptoServiceProvider();
        byte[] result = md5.ComputeHash(utf8text);

        //Build the final string by converting each byte
        //into hex and appending it to a StringBuilder
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < result.Length; i++)
        {
            sb.Append(result[i].ToString("x2")); //x2 here so the outcome result is all in lowercase, couse vbulleting also stores all in lowercase
        }

        //And return it
        return sb.ToString();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        //Get the user input password as plain text
        string pass = textBox1.Text;

        //Here i provided the salt explicit that i took from the database
        string salt = "N1GOt=>8sdO@E54)PH2@NCm5yI#]3u";

        //Here we convert the plain text password into the first hash
        string p1 = GetMd5Sum(pass);

        //Here we add the salt to the previous hashed password
        string p2 = p1 + salt;

        //Here we hash again the previous hashed password + the salt string
        string final = GetMd5Sum(p2);

        //this was just to the test to see if it all works as intended
        MessageBox.Show(final);
    }

这将输出存储在数据库中的完全相同的哈希作为密码。

感谢 user2246647 在我遇到的这个问题上提供的所有帮助。

【讨论】:

  • 甜蜜,很高兴你能正常工作:D 转换可以简化一些:byte[] bytes = Encoding.UTF8.GetBytes(str); 对于大小写问题,我会考虑 ToLower(最后)或不变的不区分大小写的比较.还要确保 Dispose 哈希服务提供者养成良好的习惯 - using 对此很有用。还有一个漂亮的技巧可以帮助转换为可以在 SO 上找到的十六进制字符串(我认为使用 SOAP 转换..) - 好吧,接受您的回答以结束问题:D
猜你喜欢
  • 2012-10-05
  • 1970-01-01
  • 1970-01-01
  • 2016-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-28
  • 2012-12-26
相关资源
最近更新 更多