阻止在应用程序外部访问数据库

时间:2016-09-29 16:40:00

标签: sql-server asp.net-mvc database authorization access

我们有一个运行SQL Server数据库的MVC应用程序。

我们正在使用Windows身份验证,当我们想要授予用户访问我们网站的权限时,我们会将其添加到活动目录组SEUser中。

我们已将SEUser组的登录和访问权限也授予我们的数据库。

但问题是由于AD组具有数据库权限,因此属于该组的用户不仅可以访问网站,还可以从应用程序外部连接到数据库,也可以对其进行更改。

因此,我正在寻找能够限制用户组访问数据库的任何方式,只有当请求来自我们的应用程序而不是来自外部时。

为此,我想到的第一种方法是使用模拟/连接作为方法,并且只允许工作进程帐户连接到数据库,

但问题是我们还使用SYSTEM_USERIS_MEMBER这样的方法来访问存储过程中当前登录的用户信息,这些方法仅考虑当前登录用户,因此我们无法使用工作进程方法。

我能以任何方式为我的特定情况实现这一目标吗?请帮忙

1 个答案:

答案 0 :(得分:4)

简短的回答是,没有任何功能允许授权用户从一个程序(即您的中间层)连接,而不能从另一个程序(即SSMS等交互式查询程序)连接。

我能给你的最好的建议是假设用户会找到一种直接连接到数据库的方法来设计你的系统,因此尽可能地限制他们的权限,以避免在他们决定做任何问题时如此。

限制用户在直接连接到数据库时可以对系统执行的操作的一种策略是使用存储过程来限制他们应该在数据库上执行的操作(即,他们有权运行SP,而不是其他任何操作),仅通过签名来执行SP授权。

我还强烈建议您使用审核来检测是否滥用用户权限。鉴于您希望所有用户都通过中间层应用程序进行连接,因此检测异常活动应该相对容易。

您可能会发现一个有趣的解决方法是使用登录触发器来避免通过非授权程序意外访问(AKA。避免使用“我不知道”的借口)。但要注意:这不是一个安全边界,它很容易绕过,但它会帮助你保持诚实的人诚实。

例如:

我授予对系统中特定群组的访问权限,但我希望尽可能将此群组限制在我的应用中:

CREATE LOGIN [myDomain\myGroup] FROM WINDOWS

因此,我将创建一个登录触发器,用于检查会话中的应用程序名称,并阻止我未批准用于这些用户的任何应用程序。

CREATE TRIGGER connection_limit_trigger
ON ALL SERVER 
FOR LOGON  
AS  
BEGIN
IF( IS_SRVROLEMEMBER('sysadmin') != 1 )
BEGIN
    IF( IS_MEMBER('myDomain\myGroup') = 1 )
    BEGIN
        DECLARE @appName nvarchar(256)
        SELECT  @appName = program_name FROM sys.dm_exec_sessions where session_id = @@SPID
        IF( @appName != 'My approved app' )
            ROLLBACK;
    END
END
END;  

请注意,此触发器会影响我的所有用户,因此我添加了检查以避免对某些用户造成不必要的限制。

我有一个我批准的非常简单的应用程序(请参阅连接字符串上的ApplicationName属性):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;

namespace SampleAppSql
{
    class Program
    {
        static void Main(string[] args)
        {
            SqlConnectionStringBuilder cnnstrbldr = new SqlConnectionStringBuilder();
            cnnstrbldr.ApplicationName = @"My approved app";
            cnnstrbldr.DataSource = @"."; //local machine
            cnnstrbldr.IntegratedSecurity = true;

            using (SqlConnection conn = new SqlConnection(cnnstrbldr.ConnectionString))
            {
                conn.Open();
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = @"SELECT @@version;";
                    string vers = (string)cmd.ExecuteScalar();
                    System.Console.WriteLine(@"SQL Server version: {0}", vers);
                }
                conn.Close();
            }
        }
    }
}

当该组的用户尝试连接到SQL Server时,触发器将检查应用程序名称,如果它不匹配,则登录触发器将导致连接失败:

C:\>g:\temp\SampleAppSql.exe
SQL Server version: Microsoft SQL Server 2016 (RTM) …

C:\>sqlcmd -E -S .
Sqlcmd: Error: Microsoft ODBC Driver 13 for SQL Server : Logon failed for login 'myDomain\toto' due to trigger execution..

请注意,此技术不是安全边界,因为授权用户可以简单地操纵应用程序名称并绕过触发器;但违规用户将无法否认她/他故意绕过您的保单。

我希望这些信息有所帮助。

有关详细信息,我建议使用以下文章:

-Raul