对用户定义查询的限制

her*_*ans 2 security best-practices permissions sql-server-2008-r2 read-only-database

我有一个客户希望我实现一个网页,该网页允许用户在文本框中输入自定义查询,以便他们可以直接查询 SQL Server 数据库。我担心用户输入恶意查询*。有没有办法(通过语法检查或角色权限或其他方式)确保数据库在提供此功能时保持安全?

*忽略拒绝服务。我担心的主要是数据丢失

Sol*_*zky 6

我担心用户输入恶意查询。有没有办法(通过语法检查或角色权限或其他方式)确保数据库在提供此功能时保持安全?

这实际上是两个独立但相关的问题:一个关于“安全”,一个关于“恶意”。虽然安全违规是恶意的,但并非所有恶意查询都是安全违规。

您可以通过正确使用权限和视图来锁定对各种表的读写访问。但是,我认为您无法阻止他们执行诸如发出SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;然后使用XLOCKTABLOCK表提示之类的操作。或者将其与发布相结合,BEGIN TRAN;然后使用这些查询提示从表中进行选择,然后发布WAITFOR DELAY '10:00:00.000'; -- 10 hour delay, hee hee.

对用户数据库的只读访问不会禁止临时对象,对吗?那么他们仍然可以创建临时表和表变量吗?如果是这样,有人可能有意或“意外地”填充tempdb **,或者至少通过向 tempdb 及其日志文件添加大量争用来降低性能。

如果是动态的,则大量 CURSOR 将导致更多的锁定和争用(即阻塞),或者如果STATIC.

<sarcasm>而且我确信所有这些用户都接受过 T-SQL您的数据模型的培训,因此不会执行极其低效的查询,这些查询会不必要地填充缓冲池,从而减少页面预期寿命并降低整个应用程序的性能。</sarcasm>

这就是只读副本的用途,或者是通过日志传送等填充的辅助系统。不要向任何不会因滥用而被解雇的人(即员工)提供对 OLTP 系统的直接、临时查询访问权限或分包商)。

** @MartinSmith 指出,只需执行以下操作即可创建 100 亿个字符串:

SELECT DATALENGTH(REPLICATE(REPLICATE(CAST('X' AS VARCHAR(MAX)),100000),100000));
Run Code Online (Sandbox Code Playgroud)

这相当于需要 9.31 GB 的数据空间tempdb(使用sys.dm_db_task_space_usagesys.dm_db_session_space_usageDMV时显示)。或者,只需添加一个小字母来代替VARCHAR(MAX)an NVARCHAR(MAX),您将拥有一个 18.63 GB 的字符串 ;-)。呜呼!


由于问题被澄清主要集中在数据丢失而不是“拒绝服务”上,我可以想到两种需要注意的情况:

  1. 链接服务器:如果您有任何链接服务器,请确保本地只读登录名不会使用读写帐户的映射登录名/密码连接到远程服务器。

    或者您至少可以尝试从只读登录中隐藏链接服务器。有关详细信息,请参阅sys.servers的 MSDN 页面的“权限”部分。

  2. 由于所有权链EXECUTE AS、 和代码签名而提升的权限:彻底审查此只读登录可能EXECUTE有权访问的所有存储过程。通过所有权链EXECUTE AS、 和代码签名绕过直接对象权限真的很容易。如果您正在使用的任何“OLE自动化过程”或SQLCLR对象,那些有可能达到数据库之外,因此虽然你可能有CREATEALTERDROPINSERTUPDATEDELETEMERGETRUNCATE,等锁定,可以存储过程写入文件不会被其他限制禁止的系统、注册表等。您需要确保整个系统是只读的,而不仅仅是 SQL Server。


PS 虽然这不是安全问题,但在更实际的层面上,与赋予“用户”编写临时查询的能力有关:如何使用这些查询,以及您向“用户”通知更改的义务级别是什么到数据模型?为人们提供即席查询能力与提供 API 不同。随着时间的推移,数据模型将不可避免地发生变化。这些更改可能会破坏“用户”过去已成功执行(即使很痛苦)的查询。当您的客户抱怨查询中断时,您的客户会不会对您感到不满(是的,他们会抱怨,因为他们会将查询保存在文件或 wiki 页面中并构建业务流程以定期运行它们)?