防止在应用程序外部进行数据库访问

Paw*_*iya 2 database sql-server asp.net-mvc authorization access

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

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

我们还具有登录名和访问权限,也可以SEUser分组到我们的数据库。

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

因此,我正在进行大量搜索,以找到任何方法可以限制用户组仅在请求通过我们的应用程序而不是外部请求时才访问数据库。

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

但是问题在于,我们还使用诸如SYSTEM_USERIS_MEMBER这样的方法访问存储过程中的当前登录用户信息,并且该方法仅考虑当前登录用户,因此我们不能使用辅助进程方法。

有什么方法可以针对我的特定情况实现这一目标吗?请帮忙

小智 5

简短的答案是,没有能力允许授权用户从一个程序(即您的中间层)进行连接,而不能从另一个程序(即诸如SSMS之类的交互式查询程序)进行连接。

我能给您的最佳建议是在用户将找到直接连接到数据库的方法的假设下设计系统,因此,在决定这样做时,尽可能地限制其权限以避免任何问题。

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

我也强烈建议使用审核来检测用户特权的任何滥用。假设您希望所有用户都通过您的中间层应用程序进行连接,则检测异常活动应该相对容易。

作为解决方法,您可能会发现有趣的一种技巧是使用登录触发器来尝试避免通过未经授权的程序进行意外访问(AKA。请避免使用“我不知道”的借口)。但请注意:这不是安全边界,很容易绕开,但是它将帮助您使诚实的人保持诚实。

例如:

我授予对系统上特定组的访问权限,但我想将此组尽可能限制为我的应用程序:

CREATE LOGIN [myDomain\myGroup] FROM WINDOWS
Run Code Online (Sandbox Code Playgroud)

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

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;  
Run Code Online (Sandbox Code Playgroud)

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

我有一个我批准的非常简单的应用程序(请参见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();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当该组的用户尝试连接到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..
Run Code Online (Sandbox Code Playgroud)

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

我希望这个信息帮助。

有关更多详细信息,我建议以下文章:

-劳尔