sql-server - 防止应用程序外部访问数据库

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

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

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

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

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

因此,我进行了很多搜索,以找到任何方法来限制用户组仅在请求来 self 们的应用程序而不是来自外部时访问数据库。

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

但问题是我们也通过使用 SYSTEM_USERIS_MEMBER 等方法访问存储过程中的当前登录用户信息,它们仅考虑当前登录用户,因此我们不能使用工作进程方法。

有什么方法可以针对我的特定场景实现这一点?请帮忙

最佳答案

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

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

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

我还强烈建议使用审计来检测任何滥用用户权限的行为。鉴于您希望所有用户都通过您的中间层应用程序进行连接,检测异常事件应该相对容易。

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

例如:

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

CREATE LOGIN [myDomain\myGroup] FROM WINDOWS

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

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..

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

希望这些信息对您有所帮助。

更多细节,推荐以下文章:

-劳尔

关于sql-server - 防止应用程序外部访问数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39775737/

相关文章:

c# - 可以从编辑器模板中调用显示模板吗?

asp.net mvc 和 web api 哪个更好 Http POST 或 PUT

objective-c - 当数据不是静态时,我应该如何保存大量数据。 iOS、 cocoa touch 、Obj-C

sql-server - 无法在 SQL Server 中创建名为 State 的表?

c# - asp.net:如何将两个模型组合在一起才能创建父实体及其所有子实体?

php - 图像(SQL Server)和longblob(MySQL)有什么区别?

php - 在 PHP 中处理数据库错误

python - Mssql外键

sql - 嵌套 SELECT 语句

sql - 如何找到潜在的非空列?