您如何从桌面应用程序处理数据库安全性?


12

大约十年来,我一直在使用SQL Server数据存储来处理各种内部桌面客户端应用程序。我很少启动这些项目-大多数是接管工作。

似乎到处都是的一件事是,该应用程序使用了一个单一的全局SQL Server用户帐户,该帐户向普通数据库授予了该帐户的权限,是的,在某些幼稚的情况下,它使用了该sa用户帐户,我通常尝试在可能的情况下进行修复。

您不能真正有效地隐藏应用程序用来访问数据库的用户名和密码。它们通常存储在iniconfig文件中,或者可能烘焙到可执行文件本身中。在所有情况下,如果进行一点挖掘,它们对于用户都是可见的。在一种情况下,我们实际上使用了一个config文件但对其进行了加密,但是当然加密密钥必须存储在可执行文件中(我们并非天真地限制了它的局限性,但是它确实有效地阻止了人们回避那些精明的人查看config文件)。

所有这些系统都在应用程序中内置了一个用户身份验证系统,但是当然它们都是通过应用程序本身进行管理的,这意味着用户信息存储在数据库中。该应用程序根据访问级别限制了您可以执行的操作,但是如果您仅可以连接到数据库并运行即席查询,那就太麻烦了。

我很想知道其他系统可以解决这个问题。这是我所知道的选项:

  1. 使用SQL Server的安全性机制维护用户和角色列表,并使桌面应用程序通过T-SQL查询添加和删除用户。
  2. 创建直接在服务器上运行的某种Web服务并将身份验证逻辑放在其中,而不是直接连接到数据库。使每个请求都进行安全验证。

第一个选项有些丑陋,因为您要将用户与数据库分开,因此用户不再是一流的实体,并且不能使用外键关系等来引用它们。

第二个似乎是一个主要的性能问题,需要大量额外的工作,而且您不能像NHibernate(我认为)那样容易地使用ORM映射器。

这个事情谁有经验?最佳做法?

编辑

再想想,SQL Server身份验证能否真正解决此问题?例如,如果您的用户必须能够插入和更新时间表记录,以便您可以编辑时间表,则SQL Server无法禁止访问时间表明细表中的其他行,这意味着您也可以读写其他人的时间表。


关于装订的话题;(我认为)不像NHibernate那样使用ORM是一个非问题。如果以Web服务为例,则会发现许多方法可以有效地将数据绑定到XML。
贾森克2012年

无论如何,您都不应该将ORM用作业务对象和DB实体之间的直接映射,这是使界面脆弱的一种较差的方法。向获取原始数据库实体并仅将所需数据返回给客户端的业务层发出请求。
gbjbaanb 2015年

@gbjbaanb-当然,今天下午我将更改整个体系结构。:)
斯科特·惠特洛克

我想您可以等到有人对您进行修改之前将其砍死,但是从好的方面来说,至少从那时起,您就可以毫无问题地让老板为重新架构提供资金:-)
gbjbaanb 2015年

通过使用存储过程作为更新记录的唯一方法,并使用运行proc的用户作为查询的一部分,可以防止用户更新其他人的记录。看到CURRENT_USER
gbjbaanb

Answers:


9

恐怕添加Web服务层可能是解决您的问题的正确方法。

从长远来看,将客户端与基础数据库实现分开可能也会对您有所帮助。

添加Web服务层不一定会影响性能...

确实,有了适当的API,Web服务实际上可以通过在数据中心LAN内批量处理多个数据库查询来提高性能,而不需要通过WAN进行多次往返。

当然,Web服务层通常可以水平扩展,并为数据库查询添加适当的缓存,甚至可能添加变更通知机制。

服务器层增加了在远程客户端上运行的应用程序可能无法确保的安全性。在客户端上运行的任何内容都可能被“黑客入侵”,因此不应以任何方式被认为是可信的。您应该只将展示逻辑真正放在客户端中,并在您可以完全控制的硬件上托管任何重要的东西。

我对您的应用程序一无所知,但是我的Web应用程序自然分为几层,表示代码与持久性层之间至少通过一层业务逻辑将两者分开。我发现这使我的应用程序推理变得容易得多,添加或修改功能也快得多。如果无论如何将各层分开,则将表示层保留在客户端中相对容易,而其余部分则由我控制在服务器上。

因此,尽管无需引入“ Web服务”层就可以解决问题,但是当您编写了填补标准数据库安全性实施中的漏洞所必需的所有存储过程(或等效方法)时,最好写一些您可以为其编写适当的单元测试的服务器端应用程序。


我承认它不一定是性能瓶颈,但是它无疑为体系结构增加了一层,这意味着要进行更多的维护。
Scott Whitlock

3
它增加了一层,但不一定要维护。考虑到所有逻辑都放置在服务(而不是客户端)中,可以“推出”更改,而无需用户更新其客户端应用程序。
GrandmasterB 2012年

5

与jmoreno的答案类似,您可以拒绝用户访问存储过程的EXECUTE权限之外的所有内容,然后利用所有权链接使存储过程对表执行所需的操作。

有关详细信息,请参见此处https://msdn.microsoft.com/zh-cn/library/bb669058(v=vs.110).aspx

当用户输入其用户名/密码客户端时,我将它们存储并作为参数发送到每个存储过程调用。然后,可以在执行所需操作之前,对照表中存储的值来验证它们。

绝对不是安全的硬道理,但如果您的PC具有通用登录名,从而限制了使用AD组获得权限的能力,或者您对AD本身的访问权限有限,则可能是必不可少的。


2

一种方法是使用AD组和存储过程来限制用户可以执行的操作-例如,时间表DB可以允许用户小时的插入,更新和删除,但不允许其他人的小时更新。用户的ID将由数据库引擎提供,用户将无法直接访问数据库表,而只是基于登录ID运行查询的sp。

当然,这并不总是可行的,但是可以。最佳方法取决于您的要求和资源。


这是我没有考虑过的。我不确定这是否合适,但是否可行。
Scott Whitlock

1

您所谓的“ Web服务”被称为n层体系结构。在可能发生安全性或配置问题的情况下(例如,跨多个办公室分发应用程序),通常采用这种方法。但是,它不必是“基于网络的”。许多使用其他协议。

您创建一个应用程序服务器以充当客户端与数据库(和其他资源)之间的中介。应用程序服务器处理基于应用程序的身份验证,并代表客户端执行操作。实际上,理想情况下,您不会在客户端中执行任何SQL-而是在应用服务器上调用方法。应用服务器将处理所有数据操作。

这种方法有很多好处。您不需要在客户端上配置数据库连接和驱动程序。您不存储数据库用户,密码和服务器。甚至不需要配置客户端-只需在代码中将其指向正确的url或地址即可。同样,通过应用程序服务器中的“逻辑”,您在开发其他应用程序时也不必重复自己的工作-相同的应用程序服务器可以由不同类型的客户端重用。


更好的是,如果(或何时)有人入侵您的台式机(或基于Web的等效网络服务器),则攻击者可能拥有对OS的完全访问权限,但他们仍无权访问数据库。这样一来,他们就无法运行通过管道传输到他们带走的文件中的“从用户中选择*”,随意破解,让您的CEO向媒体解释为什么您的安全系统遭到破坏。如果您还在只允许执行访问的数据库上使用存储过程,那么攻击者也可以将您的应用程序服务器黑客化,他们仍然无法获取您的整个用户数据库。
gbjbaanb 2015年

1

技术发生了一些变化。如果您向数据库本身验证每个用户并使用数据库角色,则现在至少在SQL Server中,可以使用所谓的可更新视图来解决此问题。

这是一个名为表的可更新视图,表SomeTable中的每一行都链接到一个雇员。员工应该可以看到链接到它们的行,而HR角色的成员应该可以看到所有行,例如:

CREATE VIEW [dbo].[vwSomeTable]
AS
    SELECT SomeTable.*
    FROM SomeTable
        INNER JOIN Employee ON SomeTable.Employee_ID = Employee.Employee_ID
    WHERE Employee.Username = USER_NAME() OR IS_MEMBER('HR_Role')=1

GO

然后,您要做的就是将视图vwSomeTable)的读(可能是写)权限授予所有用户,而不授予SomeTable)的权限。

您可以像这样测试:

EXECUTE AS USER = 'Some_Regular_Username'
SELECT * FROM vwSomeTable

...仅应返回其行。要么:

EXECUTE AS USER = 'Some_HR_Username'
SELECT * FROM vwSomeTable

...这将返回所有行。请注意,您将需要执行身份(模拟)权限才能执行此测试。

视图是可更新的,因此只要该行链接到他们的Employee行,即使是普通用户也可以执行此操作:

UPDATE vwSomeTable
SET SomeColumn = 5
WHERE SomeTable_ID = 'TheID'

0

使用基于证书的身份验证是实现共享sql帐户的“正确”方法。目的是消除这种事情的密码使用。

更新:

我想这个问题被误解了。我认为这与尝试找到将db用户名和密码放在应用程序配置中或备份到应用程序本身中的方法有关。

您可以通过使用客户端证书来消除在应用程序中管理密码的问题。证书本身还不够,您必须拥有一个能够执行诸如证书撤销之类的操作的分发和管理系统。

参考:http//en.wikipedia.org/wiki/Public-key_infrastructure


您能否提供更多有关此的信息?听起来可能与我最初提出的问题的意图正交,但这很有趣。
Scott Whitlock,2012年

0

构建新的桌面安全解决方案后,我们选择了下面将介绍的Web服务解决方案。

我们在与开发人员不同的环境中编译桌面应用程序可执行文件。然后从记录到数据库的可执行文件中计算哈希值。

一种Web服务,为运行该应用程序提供所有必需的信息,数据库密码,连接字符串信息,用户权限等。

我们对每个应用程序使用单个数据库登录,并将用户详细信息记录在会话变量中的数据库中,以便能够审核记录。

DLL处理从桌面应用程序到Web服务的所有通信,该通信只能通过DLL中内置的令牌来访问。

为了能够从Web服务获取应用程序数据库密码,DLL将在运行时计算DLL调用者HASH,并将其作为参数传递给Web服务,以验证DLL令牌并将可执行的运行时计算的HASH传递给部署时记录的那个(该应用程序仅在单个网络共享安装中可用)。

这样一来,我们就可以解决我们最关心的安全问题并很好地意识到一些设计缺陷,这是一个很好的解决方案。即将完成此实现,到目前为止,我们对结果感到满意。

编辑:您可以通过使用数字签名和X.509证书来取代哈希概念。


1
明显的安全漏洞在哪里似乎很明显。您所说的DLL在客户端系统上,并且服务器代码无法验证它是否在与DLL的合法副本或被黑/恶意/伪造的DLL进行通信。您只是为自己创建了很多工作,而没有添加太多(如果有的话)额外的安全性。恶意程序只需要令牌和算法,这两个令牌和算法都在DLL中供任何想看的人使用。
斯科特·惠特洛克

@ScottWhitlock,是的,我同意。我们正在研究混淆DLL和HTTPS上的流量。我们正在努力对此进行改进,我真的很喜欢在改进方面的任何投入。但是该解决方案已经解决了当前系统存在的许多问题,包括存储在网络文件中的纯文本密码。此外,Web服务还允许重用我们在此使用的任何客户端语言(包括Delphi和Clipper(Harbor)客户端)都可以使用的大量代码!
Vitor Arbex 2014年

在您的系统中,用户登录并由Web服务验证。假设使用HTTPS,还不够吗?您不必信任客户端软件,因为您知道用户就是他们所说的用户,并且可以控制Web服务,因此请确保Web服务仅分发给定用户有权查看的信息。即使他们对客户进行了反向工程并编写了自己的文件,他们仍会造成什么损失?只有您的Web服务知道数据库密码,这应该是安全的。
斯科特·惠特洛克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.