在C#应用程序中保护数据层

我正在考虑如何在C#应用程序中保护数据层,在这种情况下,该层可以是与应用程序本身一起存储的LINQ to SQL模型图,其中包含连接字符串到SQL Server数据库。

或者它可以是应用程序和Web服务之间的连接。

要么需要强制某种安全性,例如,应用程序中的连接字符串可以很容易地进行逆向工程,并且可以轻松地跟踪和使用Web服务,这是出于应用程序原始目的之外的其他原因。

所以我的问题是更简短的方法: 在处理Web服务和/或从Windows窗体应用程序直接连接到SQL Server时,如何解决安全问题?

在您的情况下,有两种主要的攻击可能性:

  • 窃取连接字符串,然后直接访问数据库
  • 不使用UI直接调用C#代码中的方法

对于连接字符串,您需要将其以加密forms存储在配置文件中。 问题是winforms应用程序中需要有足够的信息才能解密和使用它。

要直接访问代码,您可以使用代码访问安全性和模糊处理。

在您的情况下,我不会让Windows应用程序直接访问数据库。 让windows app调用WCF服务,WCF服务将访问数据库。

允许用户的用户帐户调用WCF服务,WCF服务在允许访问数据库的帐户下运行,用户的用户帐户对数据库没有权限。

具有3层的Windows应用程序:

  • UI
  • 业务(安全检查应向用户显示哪些UI)
  • 代理

具有2层的WCF服务:

  • Facade / Business Layer(允许用户使用此数据调用此方法的安全检查)
  • entity framework数据模型

两个层的常见dll

  • 合同/ WCF接口
  • 数据传输对象

有关代理,合同和DTO的信息,请参阅此video:

http://www.dnrtv.com/default.aspx?showNum=103

Shiraz Bhaiji走近了,但我认为他们错过了关键的一步。

是的,您希望访问数据库由中间层调解,通过WCF公开,这会强加您需要的任何业务逻辑,包括完全访问控制。 此服务确实具有您要保密的连接字符串,但WinForm客户端无法访问它。

关键步骤是客户端使用用户的身份validation来获得适当的访问级别,并且永远无法联系数据库甚至无法完全控制中间层。 中间层根据客户端用户所属的组授予对方法的访问权限。 这意味着具有低安全性的用户可以调用他们喜欢的任何方法,但是他们将获得访问被拒绝的exception,或数据过滤,或任何其他适合的故障模式。 用户帐户本身无法访问数据库,因此中间层可以执行任何操作。

绕过这种情况的明显方法是让客户使用具有完全访问权限的人的帐户。 当然,如果他们能做到这一点,他们已经拥有了他们想要的东西。

希望这种方法对解决您的问题很有用。

编辑

此解决方案不允许客户端中的LINQ-to-SQL,只允许中间层。 如果这是一个破坏者,那么这不适合你。 然后,当客户端可以直接访问数据库的那一刻,一个巨大的安全门被打开,而且很难关闭。 保护数据库本身涉及大量额外工作,因此它提供了一种基于用户的行级安全性,这种安全性自然来自三层解决方案。 我一般会建议反对它,虽然我确实认识到有时它是完全合适的。

一种方法是使用SQL Server的可信连接 ,这样就不会在代码中存储用户名/密码。

我不认为这个问题有任何一个解决方案,你需要分析并调整你的解决方案以解决你遇到的特定问题。

据我所知,没有已知的方法可以在客户端安全地存储您的连接信息,因为您的客户端是与服务器通信的“可信”部分。 无论您如何存储信息,客户端都必须能够将其反转或直接发送到服务器,这也意味着潜在的攻击者可以重复此过程。 此外,任何直接与您的数据库的外部通信都可能被拦截/入侵。

我可以想到保护数据的最佳方式是使用Web服务(通过安全连接)作为控制与数据库( 您需要保护 )的通信的中间件,并添加逻辑以强制执行您希望获得的任何级别的安全性。 如果需要,您可以基于帐户授予不同级别的访问权限。 但主要的是它只允许安全/隔离操作。

为了保护Web服务(中间件),有两个问题,即身份validation和隔离。

认证

您可以像Steven建议的那样使用标准.NET身份validation。 我通常喜欢滚动我自己的解决方案,原因有两个。 首先,到目前为止,我主要是处理更复杂的用户/角色。 例如,使用基于权限的角色,以便您可以检查权限而不是特定角色。

其次,它为您提供更多控制权。 您可以避免基于会话的身份validation ,也可以使用质询 – 响应 ,例如使用时间戳进行质询,并期望时间戳+密码的哈希值(用户必须在应用程序启动时输入)或其他一些创意组合作为答案,I我确定有更好的哈希组合来回应。 这也应该是双向的,以确保客户端validation从服务器获得的任何内容。

此外,还有一些关于WCF授权的SO主题可能很有趣: WCF服务授权模式 使用WCF授权和身份validation WCF授权 – 通过声明访问操作以及书籍和论文 (非免费)

隔离

无论您的身份validation有多安全,总有可能有人能够访问您的Web服务以获取恶意意图。 据我所知,这个问题没有一个解决方案,但它取决于具体的应用程序以及如何在用户之间构建和共享数据。

您需要识别隔离层,以便用户不会相互影响或一般地影响系统,以及应用程序的使用方式。 客户是需要写数据还是只读? 如果他们写,是以任何方式共享的书面数据,以什么方式隔离/validation数据? 如果他们阅读,那么该信息是私有的,对于系统是私有的还是用户之间共享的?

例如,用于存储医疗日志或个人任务列表的系统将具有非常孤立的数据,您可以仅限制访问您的私人信息(可能还有您的医生/老板,具体取决于用户组)。 在这种情况下,您可以隔离对特定用户的所有数据读/写,因此攻击者只能影响他自己的数据,保证其他人的安全。

如果数据在用户之间共享,则需要某种方式来validation用户提供的输入。 优选地,您还应该为用户提供某种信任级别,例如SO的声誉,以防止任何一次性用户尝试黑客攻击。 这真的太具体了,无法给出任何好的建议。

您还需要validation您收到的输入,以防止诸如缓冲区溢出攻击和SQL注入之类的 攻击 。 尽管我不知道缓冲区溢出是否是.NET的问题,但使用LINQ-to-SQL可以轻松地防止SQL注入。


总而言之,没有100%保证数据保护的方式,您应该保持定期备份(与数据库分开),以防您受到损害,并可能还有事务日志。

作为最后的建议,如果你真的认真对待安全问题,你应该雇用一名安全顾问,并查看银行如何建立他们的安全基础设施。

你还可以通过LINQ到ADO.NET使用LINQ和webservices,虽然我自己没有尝试过。

这个链接可能更多解释如何从LINQ迁移到SQL到“LINQ to WCF”?

在安全性非常重要的情况下,例如,当您存储信用卡信息时,您通常会希望数据存储库和Web服务器位于单独的盒子上,防火墙之间以及两者都被IP安全锁定。

这样,只有Web服务器才会暴露给外部世界。 您的数据库服务器正好位于防火墙后面,并且只能由Web服务器通过某个端口访问。

您还可以考虑对Web服务进行SSL加密,并仅公开HTTPS端点。

我在这里并不完全清楚。 如果winforms应用程序调用webservice,则使用适当的模型进行相互信任的身份validation。 这可以基于客户端和服务器证书或SSL与客户端证书,甚至Net.Tcp,如果你们都是.Net。 然而,只有受信任的客户端可以进行通信,才会公开Web服务。 然后,web服务可以留在DMZ和DB后面的另一个DMZ。 使用适当的防火墙规则和webservice和SQL之间的IPSec连接是一种选择。

为了直接连接到SQL服务器到许多winforms应用程序,挑战很多。与数据库的连接必须经过身份validation和加密。 在任何情况下,您的SQL服务器都将被公开,我不会推荐这样的模型。

你没有保护它,因为你无法保护它。 首先,你无法正确隐藏凭据,即使你弄清楚如何做到这一点,然后攻击者可以嗅闻( 是的,即使它是加密的,你可以在本地嗅探 )或直接在线上进行SQL注入。

您需要以安全的方式编写所有Web服务调用,而不需要传输原始SQL查询或直接SQL Server连接。

此外,如果代码没有运行您的系统,那么对它进行多少混淆或加密并不重要,这不再是您的代码。 通过逆向工程,调试,修改代码,潜在的攻击者可以将您的应用程序更改为其他内容并执行他们想要的任何操作。

此外,正如其他人所写,您的网络服务将开放直接访问。 有人可以直接拨打您的Web服务,完全忽略GUI。

一种安全的方法是:

将数据层放在物理上独立的Application Server上的(WCF)服务后面,让WinForms客户端使用其Windows凭据连接到该服务。 然后,该服务validation用户是否可以基于授权存储(例如Active Directory)和数据库或其组合来访问服务中的各种方法。

然后,数据服务可以使用单个池标识来连接到数据库。

Web服务的一种常见方法是通过Web方法签名传递加密的用户名和密码,以validation尝试调用Web方法的用户确实有权这样做。

就配置文件而言,可以加密文件本身或使用集成安全性作为另一张提到的海报。

很难提供准确的答案,因为我不确定您要解决的具体问题是什么,以及哪些是确保系统安全的关键驱动因素。
但是,在过去,我使用WSE来使用WinForms – > WebService安全通信
我们使用了X509证书和WS-Security。 这具有提供端到端安全性的独特优势,而不是依赖于标准SSL传输。
然而,这本身并不能解决用户身份validation本身等问题,在这种情况下, Mitch Wheat的答案似乎是一个很好的解决方案。
但是,您的用户身份validation模型将取决于这是一个公共分布式应用程序,该工具的用户数量是大还是小等。
对于少量用户或成本不成问题,您可以通过设置RADIUS服务器等实现RSA SecurID身份validation。 这样做的优点在于每个RSA密钥都是唯一的并且与该用户相关联(尽管您永远不会阻止用户提供其凭据和PIN)

HTH

答案很简单,保护sql字符串很简单。 永远不要在客户端直接连接SQL。

在经过散列的公共私钥对( http://msdn.microsoft.com/en-us/library/6f05ezxy.aspx )中进行身份validation后,才接受格式良好,模式validation的xml序列化对象作为程序的入口,作为您的程序中提供的公钥证书,所以有人窃听不会发现密码。

另外,请注意DDOS攻击。 测量为每个客户端公开的每个Web服务的使用,如果使用超过给定限制,则阻止来自用户和用户ip的所有传入连接。

如果我正确理解OP,不可变的设计特性是直接连接到可公开访问的SQL Server的WinForms客户端?

几乎每个回复的人都基本上说“不要这样做,而是使用网络服务”。 这是一个很好的建议。 即使ws被黑客入侵,它也只能做它设计的事情。 因此,RPC WS只能执行已编写的方法,而黑客SQL Server连接则允许任意SQL执行。 此外,我认为您会发现设计良好的Web服务会更高效。

但是,如果要执行此操作,则必须通过SSL保护SQL连接(请参阅technet )作为开始。 与安全Web服务(也将使用SSL)一样,这将隐藏来自中间人的流量内容。

您不能依赖连接字符串的身份validation(但使用它会为黑客添加另一层以便通过),因此您必须拥有一个您最有可能自行滚动的应用程序级别身份validation层。

不要让WinForms应用程序连接到您的操作数据库。 改为创建另一个数据库,并允许基于连接字符串的auth连接到它。 不要使用此设计执行动态SQL,而是使用存储过程。 在公共数据库中创建存储过程,作为“rpc Web服务”来隐藏真实的SQL(它将查询您的操作数据库并返回结果)。 这将隐藏模式的操作细节并减少攻击的表面区域。

如果由于必须使用动态SQL而无法执行过程,则仍保留公共/可操作数据库结构并使用视图尽可能少地公开数据。 利用用户ID和数据库中的任何多租户function来预过滤视图中的数据。 如果可以这样做,则可以将攻击的表面区域减少到连接用户的数据。

如果不理解为什么必须允许直接的SQL连接,我只能再次说你不应该这样做。 您在短期内获得的收益是以系统的长期安全为代价的。