构建安全的数据访问-设计注意事项(二)

 

在开始编写代码之前,需要在设计时考虑许多重要的问题。主要的注意事项包括:

•使用 Windows 身份验证。

•使用最小特权帐户。

•使用存储过程。

•保护所存储的敏感数据。

•使用单独的数据访问程序集。

使用 Windows 身份验证

理想情况下,在设计中应该使用 Windows 身份验证,以增加安全性好处。使用 Windows 身份验证,您不必存储具有嵌入凭据的数据库连接字符串,凭据不通过网络传递,而且您可以受益于安全帐户和密码管理策略。但是,您需要认真考虑在使用 Windows 身份验证时,将使用哪个帐户连接到 SQL Server。

使用最小特权帐户

您的应用程序应该使用在数据库中具有有限权限的最小特权帐户。请确保对应用程序的数据库登录进行了适当的授权和限制。

使用最小特权帐户可以降低风险,并在您的帐户发生泄漏或者注入了恶意代码时限制潜在的损害。对于 SQL 注入,该命令将在由应用程序登录定义的安全上下文中执行,并遵守该登录在数据库中拥有的相关权限。如果您使用特权过高的帐户(例如,作为 SQL Server sysadmin 角色的成员)进行连接,攻击者能够在服务器上的任何数据库中执行任意操作。这包括插入、更新和删除数据;删除表;执行操作系统命令。

要点 不要使用 sa 帐户或者 SQL Server sysadmin db_owner 角色的任何成员帐户连接到 SQL Server。

使用存储过程

存储过程提供性能、维护和安全性好处。应尽可能使用参数化存储过程进行数据访问。安全性好处包括:

•可以限制应用程序数据库登录,以便它只具有执行指定存储过程的权限。没有必要授予直接的表格访问权限。这有助于降低由 SQL 注入攻击造成的风险。

•针对传递到存储过程的所有输入数据执行长度和类型检查。同样,不能将参数视为可执行代码。这也会降低 SQL 注入风险。

如果由于某种原因,您无法使用参数化存储过程,但是您需要动态构造 SQL 语句,请使用类型化参数和参数占位符来构造这样的语句,以确保检查输入数据的长度和类型。

保护所存储的敏感数据

标识需要保证私密性和完整性的存储数据。如果您只是为了验证而将密码存储到数据库中,请考虑使用单向哈希。如果密码表发生泄漏,则不能使用哈希来获取明文密码。

如果您存储用户提供的敏感数据(如信用卡号),请使用强对称加密算法(如三重 DES (3DES))来加密数据。使用 Win32 数据保护 API (DPAPI) 加密 3DES 密钥,然后将已加密的密钥存储在具有受限 ACL 的注册表项中,只有管理员和应用程序进程帐户才能使用该注册表项。

 

为什么不使用 DPAPI?

尽管建议使用 DPAPI 来加密连接字符串和其他可在计算机出现故障时手动恢复和重新构造的机密(如帐户凭据),但仍不太适合存储信用卡号之类的数据。这是由于可恢复性问题(如果密钥丢失,则无法恢复加密数据)和 Web 场问题。相反,应该使用对称加密算法(如 3DES)并使用 DPAPI 加密密钥。

下面概述了造成 DPAPI 不太适合在数据库中存储敏感数据的主要问题:

•如果 DPAPI 与计算机密钥一起使用,而且您将 CRYPTPROTECT_LOCAL_MACHINE 传递到 CryptProtectData CryptUnprotectData 函数,则计算机帐户会生成加密密钥。这意味着 Web 场中的每台服务器都有一个不同的密钥,这会禁止一台服务器访问由另一台服务器加密的数据。同样,如果该 Web 服务器计算机被破坏,则密钥会丢失,而且加密的数据无法从数据库进行恢复。

•如果使用计算机密钥方法,则该计算机上的任何用户都可以对数据进行解密(除非您使用其他加密机制)。

•如果您将 DPAPI 与用户密钥一起使用,而且您使用的是本地用户帐户,就会为每台 Web 服务器上的每个本地帐户生成一个不同的安全标识符 (SID) 和一个不同的密钥,这会禁止一台服务器访问由另一台服务器加密的数据。

•如果您将 DPAPI 与用户密钥一起使用,而且您在 Web 场中的计算机之间使用漫游用户配置文件,则所有数据都将共享相同的加密/解密密钥。但是,如果负责漫游用户配置文件帐户的域控制器被损害或被破坏,则无法重新创建具有相同 SID 的用户帐户,而且不能从数据库中恢复加密的数据。

另外,对于漫游用户配置文件,如果某人设法检索该数据,则只要攻击者能够在特定的用户帐户下运行代码,就可以在网络中的任何计算机上解密该数据。这会增加潜在攻击的范围,因此不建议这样做。

使用单独的数据访问程序集

如果您可以进行选择,请避免将数据访问逻辑直接放在 ASP.NET 页或代码隐藏文件中。如果将数据访问逻辑放在一个单独的程序集中,并实现一个与应用程序的业务和表示逻辑分开的逻辑数据访问层,就会带来安全性、重复使用和维护好处。

从安全的角度看,您可以:

对程序集使用强名称以提供可防篡改功能。

使用沙盒技术来隔离数据访问代码,如果您的代码需要支持部分信任调用方(例如,部分信任 Web 应用程序),这一点十分重要。

使用那些按照代码标识权限需求向调用代码授权的数据访问方法和类。

对于深层防御,请按照业务组件中的主体权限需求来执行基于主体的授权,并按照代码标识权限需求来为调用数据访问逻辑的代码授权,如图 14.2 所示。

分开表示层、业务层和数据访问层

图 14.2
表示层、业务层和数据访问层的分离

posted @ 2010-08-03 16:50  远大 光明  阅读(305)  评论(0编辑  收藏  举报