在客户端和服务器之间保护用户名/密码的最佳实践

时间:2010-08-10 17:28:47

标签: c# .net sql-server xml encryption

有一个应用程序(C#WPF)需要“回家”并从家庭服务器获取更新的东西。从理论上讲,可能有成千上万的客户,需要通过公共互联网进行沟通。

每个用户将首先注册用户名和密码。然后,当应用程序运行时,它将不时地调用home,以获取有关新版本,新闻,注释,用户消息以及其他特定于应用程序的内容的信息。这不是“每个人”的应用程序,但如上所述,仍然可能有相当多的用户 - 因此安全性是一个优先事项。我希望它非常非常难以打破,但如果不可能是一个选项,我也会这样做。 :)

只需要支持一些基本操作;

  • 新用户的初次注册
  • 验证用户名和密码
  • A“[TIMESTAMP]以来有什么新东西?”操作
  • 客户发布评论,消息或其他允许的用户生成内容

服务器端的东西将在带有IIS7的Win2008服务器上。我没有几乎所需的WCF知识来实现​​这个项目的时间,所以我将来回使用XML文件做一些ASP.NET MVC 2魔术。如果你只拥有一把锤子......

我正在寻找的是如何在不使用它的情况下尽可能安全地做到这一点的建议。客户端的配置将保留在XML文件中。在服务器端,大多数东西都将存在于SQL服务器中。

我意识到这在某种程度上是一个意见问题,但我也相信它应该可以达到某种最佳实践,我可以在晚上睡觉而不用担心客户端< - >服务器通信和帐户被劫持的用户等。

  • 在客户端,密码应该存储为哈希我猜?或加密,有办法将其取回?
  • 我在考虑客户端和服务器之间的HTTPS,以获得一个很好的默认安全层。馊主意?否?
  • 是否有必要使用此模型实际“登录”?是否应该与每个请求一起发送用户名/密码组合?
  • 如果我选择https,那么那是否足够安全?或者我还应该加密一些身份验证的东西吗?
  • 是否有一点指向服务器提供某种加密“令牌”,可以用作盐(我不太熟悉这里的术语)来进一步加密用户名/密码?
  • 基本上,我如何保护这个系统到客户端或服务器机器外面没有人可以窃取帐户信息的程度?我当然意识到,如果坏人得到一个正确的配置文件,那么该帐户就会受到损害。当然,该系统绝不允许使用此通信进行任何关键操作,所有这些都将在服务器上发生;不过,我认为帐户黑客行为是一件非常非常糟糕的事情,我应该采取一切可能的措施来避免。

有什么好主意吗?

谢谢!

3 个答案:

答案 0 :(得分:5)

您有两个不同的问题:验证注册用户和配置新用户帐户。

验证用户

这很容易。你有几个选择:

  • HTTP身份验证(basicdigest)。基本是一个笑话,所以它真的只留下Digest作为一个严肃的选择。
  • HTTP NTLM / Kerberos身份验证(又称Windows集成身份验证)是防弹的,只要您的客户端加入NT域(不太可能)。
  • SSL / TLS相互身份验证
  • HTTP“表单”身份验证。不值一提。
  • 通过安全通道进行基本或表单身份验证( HTTPS

因此,剩下的实际选项是Digest,SSL mutual或Basic / Forms over encrypted channel。

HTTP Digest 在客户端非常容易实现,只需将用户名/密码添加到CredentialCache使用的WebRequest即可。在调用之间重用CredentialCache实例以从预身份验证中受益。不幸的是,服务器端的情况并不乐观:只有在与AD集成时才能正确支持摘要式身份验证,请参阅Configure Digest Authentication

客户端和服务器都支持

SSL / TLS相互身份验证,但是,只有在与AD集成时,服务器端才真正支持它,而不是真正的选项(请参阅Configure Client Certificate Mapping Authentication

这就是为什么我认为在公司环境中不打算在VPN上使用的应用程序的唯一现实选项是通过安全通道(HTTPS)使用基本或表单身份验证。对于Basic,您必须提供密码din明文,并且对于Forms(在其通用的,未修改的版本中)必须提供密码,因此客户端必须能够访问明文密码,服务器也是如此。一种方式散列不起作用,您需要适当的加密安全存储。

现在确实,你可以'增强'表单身份验证方案来做相当复杂的事情,基本上在HTTP表单交换中设计一个Digest等价物,但我相信这超出了本讨论的范围。如果你冒险走这条路,你应该真的知道你在做什么,或者使用一个完善的解决方案(我不知道)。

存储密码:对于Basic / Digest / Forms,客户端不存储密码,因为密码实际上是由用户提供的。最多可以保存密码以避免重新键入,这应该像存储在客户端上的任何用户特定秘密一样,通过ProtectedData类使用DPAPI加密。在服务器端,如果使用用户表,则密码应存储为单向散列。对于Basic和Form,任何哈希方案都可以使用(最好是盐腌)。但是对于Digest,哈希必须是摘要方案中的HA1哈希:md5(username:realm:password),以便服务器可以完成身份验证握手。虽然这样做需要对ASP附带的开箱即用成员资格提供程序进行一些非常有侵略性的重写,但仍然是我的推荐方式。

配置用户

这有点棘手,因为它涉及建立初始信任。如果您查看上面提到的所有方案,您将看到除了基本/表格通过HTTPS之外的任何方案都可以在带内执行此操作:任何其他解决方案都需要通过带外方式初始部署用户帐户(带外指的是使用的方案)。相互SSL需要证书配置,NTLM / Kerberos需要AD用户配置,Digest需要配置用户密码。对于Basic / Forms和Digest,有一个方便的“带外”解决方案:提交帐户创建表单的安全HTTPS通道。对于SSL / TLS证书和AD,事情要复杂得多。

的OpenID / OAuth的

完全不同的方法是委派身份验证。将OpenID与Google或Yahoo和OAuth等提供商与Facebook或Twitter等提供商一起使用。这对于web应用程序非常有效(StackOverflow本身使用这样的方案,您可能已经注意到OpenID, One Year Later)。有些库和集成提供商可以轻松实现3次点击和一行代码,例如JanRain

OpenID和OpenAuth的唯一问题是交互式方案。它仅在用户积极参与登录/身份验证过程时才有效,从而消除所有自动化解决方案。如果您的应用程序正在进行任何类型的后台操作(例如,作为服务运行),或者如果在没有用户参与的情况下使用应用程序ID进行“电话回家”,则OpenID / OAuth不起作用。

答案 1 :(得分:2)

对于像这样的广泛问题,没有简单的答案。您的应用程序可能遇到许多不同类型的威胁 - 通常需要做的事情称为 threat modeling ,包括:

  • 识别漏洞
  • 识别攻击媒介
  • 确定可能的对策

在决定是否使用SSL,HTTPS,加密或任何其他技术之前,您需要了解每种威胁可以减轻哪些威胁以及如何对其进行攻击。

虽然有最佳安全实践,但您不能只遵循配方来保护系统。

虽然一般来说,您提到了一些保护应用程序(密码哈希,HTTPS)的合理对策,但是细节中存在恶魔。您有时必须考虑以下情况:

  • 重播攻击(记录并重播邮件流量)
  • 拒绝服务攻击(在服务器受到格式错误或无效邮件轰炸时试图超载)
  • man-in-the-middle (攻击者拦截或改变路线中的邮件的攻击)

还有许多其他攻击媒介(和可能的对策)需要考虑。您需要花费多少精力取决于受保护资源的重要性,受到影响的后果,以及您将运营的技能水平和对安全环境的理解。

Microsoft发布了一些名为Security Development Lifecycle (SDL)的内容,您可能需要查看。 MSDN上还有一个完整的Security Engineering部分,该部分有很多关于此主题的背景和指导。

答案 2 :(得分:1)

我认为这只会回答你问题的“加密”部分,但我今天早上刚读了一篇关于Silverlight和.NET加密的文章,可以用来保护敏感信息:

以下是文章中的一些内容:

  

当然,第一步是找到足够强大的加密协议,可以在Silverlight和.NET中实现,并在两个运行时间之间完全兼容。我打算去加密AES。 AES代表“高级加密标准”。该标准被美国政府和标准机构广泛使用和批准。