在C# Dotnet Core控制台应用程序中保护密码输入

4

我是一个长期潜水的读者,终于有一个问题要问了。我正在使用dotnet core编写c#控制台应用程序,并尝试允许用户输入密码,但我担心安全性,特别是内存转储。

根据Password masking console application,我的理解是将密码存储为字符串变量可能会通过内存转储暴露 (参考链接)。

虽然SecureString通常是解决方法,但似乎不受dotnet core支持。

我试图修改代码以使用char数组,因为我有限的理解是它不是不可变的,所以不会全部存储在单个内存中。但是,由于安全性不是我的强项,所以我的问题是,下面的代码是否能够正确地保护我避免通过内存转储暴露密码?

        Console.WriteLine("Enter pass");
        char[] passwordArray = new char[256];
        int whileIndex = 0;

        while (true)
        {
            ConsoleKeyInfo key = Console.ReadKey(true);
            if (key.Key == ConsoleKey.Enter)
            {
                break;
            }
            else if (key.Key == ConsoleKey.Backspace)
            {
               if (whileIndex != 0) //so it doesn't explode if someone holds backspace
                {
                    whileIndex--;
                }
            }
            else
            {
                passwordArray[whileIndex] = key.KeyChar;
                whileIndex++;
            }
        }
        //Truncate array to length of password
        var endIndex = Array.IndexOf(passwordArray,'\0');
        char[] shortenedPasswordArray = new char[endIndex];
        Array.Copy(passwordArray, shortenedPasswordArray, endIndex);

        //Authentication code here

        //Wipe the characters when done
        foreach(var passChar in passwordArray)
        {
            passwordArray[passChar] = '\0';
        }

        foreach (var passChar in shortenedPasswordArray)
        {
            shortenedPasswordArray[passChar] = '\0';
        }

据我所知,一个数组仍然会被分配连续的内存空间。 - Vignesh.N
你的威胁模型是什么?谁在做什么? - Neil McGuigan
@NeilMcGuigan 不确定这个上下文会有多大帮助。这个应用程序的目的是运行LDAP查询以获取AD对象列表,并请求用户/密码来绑定连接。虽然我个人认为它比保存凭据/在设备之间传递凭据的风险要低,但可能会被具有有价值凭据的IT管理员执行,因此我想在这里尽职调查。 - Polymergraphy
谁会进行攻击?他们在哪里? - Neil McGuigan
@NeilMcGuigan 也许如果我从另一个方向开始表述会更容易理解。如果这是一个.NET标准应用程序,我会在这里使用SecureString并结束它,这样我们可以重新表述为:与使用SecureString相比,上面的代码引入了多少额外风险?据我所知,最大的区别是SecureString在内存中加密,这使得它更受保护,以防止内存转储。我错了吗?没有重新创建SecureString,这种风险是否不可避免? - Polymergraphy
1个回答

2

一些评论:

1)首先要记住,安全不是在一个应用程序中解决的。对于完全访问计算机的人来说,你几乎无法保护密码的真正安全。

(有趣的练习:如果完全不在内存中保留密码,你将如何验证密码?)

2)SecureString只是让你更加控制密码在内存中的生命周期,让你确定它何时消失。普通字符串可能会在内存中持续很长时间,甚至到程序退出,因为它在垃圾回收之前不会消失。SecureString允许你明确地擦除它,但它仍然存在于内存中,直到被清除。

3)使用自己的字符数组是个好主意,但我可能会使用List,因为它允许可变长度,或者甚至可能使用LinkedList,因为它将字符分散在内存中。耸肩。回顾#1并考虑你正在保护密码免受哪些攻击。


2
第一段是关键。作为程序员,您不应该担心攻击者需要完全物理访问运行程序的计算机才能识别出的任何漏洞。那不是代码或数据安全问题;那是物理安全问题。所谓的“白盒安全”,即攻击者可以观察计算机的所有操作,但仍无法破解安全性,已被证明很难,并被一些人认为是不可能的。 - KeithS
感谢您的回答和评论。我意识到我担心的情况可能涉及到一台被入侵的计算机,无法挽救。安全性是一个庞大的问题,我在其中非常新手,主要想要确认我没有在这里做一些类似于“密码贴在显示器上”的编码等价物。谢谢。 - Polymergraphy
我曾经为微软工作。他们有一项政策,只有安全团队的人才能从事安全工作,因为计算机安全中有很多“坑”,未经培训的人很容易创建灾难性的后门。如果您不了解这个领域,请不要感到难过,并且提问是非常好的。 - Ray Fischer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接