Динамическое маскирование данных
Область применения: SQL Server 2016 (13.x) и более поздних версий База данных SQL Azure Управляемый экземпляр SQL Azure Azure Synapse Analytics
Динамическое маскирование данных (DDM) ограничивает уязвимость конфиденциальных данных путем маскирования ее непривилегированных пользователей. Оно позволяет значительно упростить проектирование и написание кода для системы безопасности в приложении.
Это содержимое относится к понятиям динамического маскирования данных, как правило, и к SQL Server. Контент, характерный для других платформ, доступен:
- Сведения о динамическом маскировке данных в База данных SQL Azure, Управляемый экземпляр SQL Azure и Azure Synapse Analytics см. в статье "Начало работы с База данных SQL динамической маскированием данных".
- Сведения о динамическом маскировке данных в Microsoft Fabric см. в статье "Динамическое маскирование данных" в хранилище данных Fabric.
Обзор динамического маскирования данных
Динамическое маскирование данных помогает предотвратить несанкционированный доступ к конфиденциальным данным, позволяя клиентам указать, сколько конфиденциальных данных можно выявить с минимальным воздействием на уровень приложений. DDM можно настроить для отдельных полей базы данных, чтобы скрыть конфиденциальные данные в результирующих наборах запросов. При использовании DDM данные в базе данных не изменяются. DDM легко использовать с существующими приложениями, так как правила маскирования применяются к результатам запроса. Многие приложения могут маскировать конфиденциальные данные без изменения существующих запросов.
- Центральная политика маскирования данных применяется непосредственно к конфиденциальным полям в базе данных.
- Вы можете назначать привилегированных пользователей или роли, которые имеют доступ к конфиденциальным данным.
- DDM включает функции полного и частичного маскирования, а также возможность использования случайной маски для числовых данных.
- Назначение и использование масок осуществляется простыми командами Transact-SQL.
Назначение динамического маскирования данных — ограничение раскрытия конфиденциальных данных, при котором пользователи, у которых нет доступа к данным, не смогут их просматривать. Динамическое маскирование данных не сможет помешать пользователям подключиться к базе данных напрямую и выполнить запросы для получения фрагментов конфиденциальных данных. Динамическое маскирование данных дополняет другие функции безопасности SQL Server (аудит, шифрование, безопасность на уровне строк и т. д.). Настоятельно рекомендуется использовать эту возможность с этими функциями для лучшей защиты конфиденциальных данных в базе данных.
Динамическое маскирование данных доступно в SQL Server 2016 (13.x) и Базе данных SQL Azure и настраивается с помощью команд Transact-SQL. Дополнительные сведения о настройке динамического маскирования данных с помощью портала Azure см. в разделе Приступая к работе с динамическим маскированием данных в базах данных SQL (портал Azure).
Примечание.
Идентификатор Microsoft Entra ранее был известен как Azure Active Directory (Azure AD).
Определение динамической маски данных
Правило маскирования можно определить в столбце таблицы, чтобы скрыть данные в этом столбце. Доступны пять типов маск.
Function | Description | Примеры |
---|---|---|
По умолчанию. | Полное маскирование в соответствии с типами данных назначенных полей. Для строковых типов данных используйте XXXX (или меньше), если размер поля меньше 4 символов (char, nchar, varchar, nvarchar, text, ntext).Для числовых данных типов используйте нулевое значение (bigint, bit, decimal, int, money, numeric, smallint, smallmoney, tinyint, float, real). Для типов данных даты и времени используйте 1900-01-01 00:00:00.0000000 (date, datetime2, datetime, datetimeoffset, smalldatetime, time).Для двоичных типов данных используйте однобайтовое значение 0 ASCII (binary, varbinary, image). |
Пример синтаксиса для определения столбца: Phone# varchar(12) MASKED WITH (FUNCTION = 'default()') NULL Пример синтаксиса для изменения: ALTER COLUMN Gender ADD MASKED WITH (FUNCTION = 'default()') |
Эл. почта | Метод маскирования, который раскрывает первую букву адреса электронной почты и постоянный суффикс .com, в формате адреса электронной почты. aXXX@XXXX.com . |
Пример определения синтаксиса: Email varchar(100) MASKED WITH (FUNCTION = 'email()') NULL Пример синтаксиса для изменения: ALTER COLUMN Email ADD MASKED WITH (FUNCTION = 'email()') |
Случайные | Функция случайного маскирования для использования с любым числовым типом, которая маскирует исходное значение случайным значением в указанном диапазоне. | Пример определения синтаксиса: Account_Number bigint MASKED WITH (FUNCTION = 'random([start range], [end range])') Пример синтаксиса для изменения: ALTER COLUMN [Month] ADD MASKED WITH (FUNCTION = 'random(1, 12)') |
Пользовательская строка | Метод маскирования, который раскрывает первую и последнюю буквы и добавляет пользовательскую строку заполнения в середине. prefix,[padding],suffix Если исходное значение слишком коротко, чтобы завершить всю маску, часть префикса или суффикса не предоставляется. |
Пример определения синтаксиса: FirstName varchar(100) MASKED WITH (FUNCTION = 'partial(prefix,[padding],suffix)') NULL Пример синтаксиса для изменения: ALTER COLUMN [Phone Number] ADD MASKED WITH (FUNCTION = 'partial(1,"XXXXXXX",0)') Это превращает номер телефона, как 555.123.1234 в 5XXXXXXX . Дополнительный пример: ALTER COLUMN [Phone Number] ADD MASKED WITH (FUNCTION = 'partial(5,"XXXXXXX",0)') Это превращает номер телефона, как 555.123.1234 в 555.1XXXXXXX . |
Datetime | Область применения: SQL Server 2022 (16.x) Метод маскирования для столбца, определенного с типом данных datetime, datetime2, date, time, datetimeoffset, smalldatetime. Это помогает маскировать часть дня year => datetime("Y") , month=> datetime("M") , day=>datetime("D") , hour=>datetime("h") , minute=>datetime("m") или seconds=>datetime("s") . |
Пример маскирования года значения datetime :ALTER COLUMN BirthDay ADD MASKED WITH (FUNCTION = 'datetime("Y")') Пример маскирования месяца значения даты и времени : ALTER COLUMN BirthDay ADD MASKED WITH (FUNCTION = 'datetime("M")') Пример маскирования минуты значения даты и времени : ALTER COLUMN BirthDay ADD MASKED WITH (FUNCTION = 'datetime("m")') |
Разрешения
Пользователи с разрешением SELECT для таблицы могут просматривать данные таблицы. В столбцах, определенных как маскированные, будут отображаться маскированные данные. Предоставьте пользователю разрешение UNMASK, чтобы разрешить им получать незамеченные данные из столбцов, для которых определена маскировка.
Администраторы и роли всегда могут просматривать незамеченные данные с помощью разрешения CONTROL, включая разрешение ALTER ANY MASK и UNMASK. Администраторы или роли, такие как sysadmin или db_owner имеют разрешения CONTROL для базы данных путем разработки и могут просматривать незамеченные данные.
Для создания таблицы с динамическим маскированием данных не требуется специальных разрешений — только стандартные разрешения CREATE TABLE и ALTER для схемы.
Для добавления, замены или удаления маски столбца требуется разрешение ALTER ANY MASK и разрешение ALTER для таблицы. Разрешение ALTER ANY MASK может быть выдано директору по безопасности.
Примечание.
Разрешение UNMASK не влияет на видимость метаданных: предоставление UNMASK только не раскрывает метаданные. Разрешение UNMASK будет действовать только совместно с разрешением SELECT. Пример. Если предоставить разрешение UNMASK для области базы данных, а разрешение SELECT — для отдельной таблицы, то в результате пользователь сможет просматривать только метаданные конкретной таблицы, в которой ему разрешено выполнять SELECT, и никаких других таблиц. Дополнительные сведения: Настройка видимости метаданных.
Рекомендации и распространенные примеры
Создание маски для столбца не запрещает его изменение. Поэтому хотя при опросе маскированного столбца пользователи получают маскированные данные, те же пользователи могут обновлять данные, если у них есть разрешения на запись. Поэтому необходимо применить подходящую политику контроля доступа для ограничения разрешений на обновление.
Использование
SELECT INTO
илиINSERT INTO
копирование данных из маскированного столбца в другую таблицу приводит к маскировке данных в целевой таблице (если она экспортируется пользователем без привилегий UNMASK ).Динамическое маскирование данных применяется при выполнении импорта и экспорта SQL Server. База данных, содержащая маскированные столбцы, приводит к экспортированному файлу данных с маскированными данными (при условии, что он экспортирован пользователем без привилегий UNMASK ), а импортированная база данных будет содержать статически маскированные данные.
Запрос маскированных столбцов
sys.masked_columns
Используйте представление для запроса к табличным столбцам с функцией маскирования, примененной к ним. Это представление наследует от sys.columns
представления. Он возвращает все столбцы в sys.columns
представлении, а также masking_function
is_masked
столбцы, указывающие, маскируется ли столбец, а если да, то какая функция маскирования определена. В этом представлении отображаются только столбцы, к которым применена функция маскирования.
SELECT c.name, tbl.name as table_name, c.is_masked, c.masking_function
FROM sys.masked_columns AS c
JOIN sys.tables AS tbl
ON c.[object_id] = tbl.[object_id]
WHERE is_masked = 1;
ограничения
Пользователи с CONTROL SERVER или CONTROL на уровне базы данных могут просматривать маскированные данные в исходной форме. К ним относятся пользователи или роли администратора, такие как sysadmin, db_owner и т. д.
Правило маскирования невозможно определить для следующих типов столбцов:
Зашифрованные столбцы (постоянное шифрование)
FILESTREAM
Набор столбцов (COLUMN_SET) или разреженный столбец, который является частью набора столбцов.
Маску нельзя настроить в вычисляемом столбце, но если вычисляемый столбец зависит от столбца с маской, вычисляемый столбец возвращает маскированные данные.
Столбец с маскированием данных не может использоваться в качестве ключа для полнотекстового (FULLTEXT) индекса.
Столбец во внешней таблице PolyBase.
Для пользователей без разрешения UNMASK устаревшие инструкции READTEXT, UPDATETEXTи WRITETEXT будут работать неправильно для столбца, для которого настроено динамическое маскирование данных.
Добавление динамической маски данных реализуется как изменение схемы в базовой таблице, поэтому невозможно выполнить для столбца с зависимостями (например, столбец, на который ссылается вычисляемый столбец). Попытка добавить динамическую маску данных для столбцов с зависимостью приведет к ошибке ALTER TABLE ALTER COLUMN _columnname_ failed because one or more objects access this column
. Чтобы обойти это ограничение, можно сначала удалить зависимость, далее добавить маску динамических данных и затем повторно создать зависимость. Например, если зависимость обусловлена индексом, зависимым от этого столбца, можно удалить индекс, добавить маску и затем повторно создать зависимый индекс.
При проецирование выражения, ссылающегося на столбец, для которого определена функция маскирования данных, выражение также маскируется. Независимо от функции (по умолчанию, для электронной почты, случайная, пользовательская строка), используемой для маскирования указанного столбца, результирующее выражение всегда будет маскироваться функцией по умолчанию.
Межбазовые запросы, охватывающие две разные базы данных SQL Azure или базы данных, размещенные в разных экземплярах SQL Server, и включают любую операцию сравнения или соединения с столбцами MASKED не предоставляют правильные результаты. Результаты, возвращаемые удаленным сервером, уже находятся в маскированной форме и не подходят ни для какой локальной операции сравнения или объединения.
Примечание.
Динамическое маскирование данных не поддерживается, если базовая таблица ссылается в индексированном представлении.
Примечание о безопасности. Обход маскировки с помощью статистической атака или атаки путем подбора
Динамическое маскирование данных предназначено для упрощения разработки приложений путем ограничения воздействия данных в наборе предопределенных запросов, используемых приложением. Хотя динамическое маскирование данных также может быть полезно, чтобы предотвратить случайное воздействие конфиденциальных данных при доступе к рабочей базе данных напрямую, важно отметить, что непривилегированные пользователи с разрешениями нерегламентированного запроса могут применять методы для получения доступа к фактическим данным. Если необходимо предоставить такой нерегламентированный доступ, аудит следует использовать для мониторинга всех действий базы данных и устранения этого сценария.
Например, рассмотрим субъект базы данных, имеющий достаточные привилегии для выполнения нерегламентированных запросов в базе данных, и пытается "угадать" базовые данные и в конечном итоге вывести фактические значения. Предположим, что у нас есть маска, определенная в [Employee].[Salary]
столбце, и этот пользователь подключается непосредственно к базе данных и начинает угадывать значения, в конечном итоге вычисляя [Salary]
значение в Employees
таблице:
SELECT ID, Name, Salary FROM Employees
WHERE Salary > 99999 and Salary < 100001;
Идентификатор Имя. Зарплата 62543 Jane Doe 0 91245 Dmitry Gornozhenko 0
В этом примере показано, что динамическое маскирование данных не следует использовать только для полной защиты конфиденциальных данных от пользователей, выполняющих нерегламентированные запросы в базе данных. Это подходит для предотвращения случайного воздействия конфиденциальных данных, но не защищает от злонамеренного намерения выводить базовые данные.
Очень важно правильно управлять разрешениями для базы данных и всегда следовать принципу минимально достаточных разрешений. Кроме того, не забывайте включать аудит, чтобы отслеживать все действия в базе данных.
Детализированные разрешения, появившиеся в SQL Server 2022
Начиная с SQL Server 2022 (16.x), вы можете предотвратить несанкционированный доступ к конфиденциальным данным и получить контроль, маскируя его несанкционированному пользователю на разных уровнях базы данных. Вы можете предоставить или отозвать разрешение UNMASK на уровне базы данных, на уровне схемы, на уровне таблицы или на уровне столбцов пользователю, роли базы данных, удостоверению Microsoft Entra или группе Microsoft Entra. Это улучшение предоставляет более точный контроль над доступом к данным в базе данных и улучшает управление безопасностью данных.
Примеры
Создание динамической маски данных
В следующем примере создается таблица, в которой используется три различных типа динамического маскирования данных. В примере заполняется таблица, затем выполняется запрос выборки для отображения результатов.
-- schema to contain user tables
CREATE SCHEMA Data;
GO
-- table with masked columns
CREATE TABLE Data.Membership (
MemberID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY CLUSTERED,
FirstName VARCHAR(100) MASKED WITH (FUNCTION = 'partial(1, "xxxxx", 1)') NULL,
LastName VARCHAR(100) NOT NULL,
Phone VARCHAR(12) MASKED WITH (FUNCTION = 'default()') NULL,
Email VARCHAR(100) MASKED WITH (FUNCTION = 'email()') NOT NULL,
DiscountCode SMALLINT MASKED WITH (FUNCTION = 'random(1, 100)') NULL
);
-- inserting sample data
INSERT INTO Data.Membership (FirstName, LastName, Phone, Email, DiscountCode)
VALUES
('Roberto', 'Tamburello', '555.123.4567', 'RTamburello@contoso.com', 10),
('Janice', 'Galvin', '555.123.4568', 'JGalvin@contoso.com.co', 5),
('Shakti', 'Menon', '555.123.4570', 'SMenon@contoso.net', 50),
('Zheng', 'Mu', '555.123.4569', 'ZMu@contoso.net', 40);
GO
Создается новый пользователь, которому предоставляется разрешение SELECT для схемы, содержащей таблицу. Запросы, выполняемые как MaskingTestUser
, возвращают маскированные данные.
CREATE USER MaskingTestUser WITHOUT LOGIN;
GRANT SELECT ON SCHEMA::Data TO MaskingTestUser;
-- impersonate for testing:
EXECUTE AS USER = 'MaskingTestUser';
SELECT * FROM Data.Membership;
REVERT;
Результат демонстрирует маски, изменяя данные из следующих значений:
1 Roberto Tamburello 555.123.4567 RTamburello@contoso.com 10
в:
1 Rxxxxxo Tamburello xxxx RXXX@XXXX.com 91
где число в DiscountCode
случайном порядке для каждого результата запроса.
Добавление или изменение маски в существующем столбце
ALTER TABLE
Используйте инструкцию, чтобы добавить маску в существующий столбец в таблице или изменить маску в этом столбце.
В следующем примере функция маскирования добавляется к столбцу LastName
:
ALTER TABLE Data.Membership
ALTER COLUMN LastName ADD MASKED WITH (FUNCTION = 'partial(2,"xxxx",0)');
В следующем примере функция маскирования для столбца LastName
изменяется:
ALTER TABLE Data.Membership
ALTER COLUMN LastName VARCHAR(100) MASKED WITH (FUNCTION = 'default()');
Предоставление разрешений для просмотра незамеченных данных
Предоставление разрешения UNMASK позволяет MaskingTestUser
просматривать немаскированные данные.
GRANT UNMASK TO MaskingTestUser;
EXECUTE AS USER = 'MaskingTestUser';
SELECT * FROM Data.Membership;
REVERT;
-- Removing the UNMASK permission
REVOKE UNMASK TO MaskingTestUser;
Удаление динамической маски данных
Следующая инструкция удаляет маску для столбца LastName
, созданного в предыдущем примере:
ALTER TABLE Data.Membership
ALTER COLUMN LastName DROP MASKED;
Пример детализированного разрешения
Создайте схему для хранения пользовательских таблиц:
CREATE SCHEMA Data; GO
Создайте таблицу с маскированных столбцов:
CREATE TABLE Data.Membership ( MemberID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY CLUSTERED, FirstName VARCHAR(100) MASKED WITH (FUNCTION = 'partial(1, "xxxxx", 1)') NULL, LastName VARCHAR(100) NOT NULL, Phone VARCHAR(12) MASKED WITH (FUNCTION = 'default()') NULL, Email VARCHAR(100) MASKED WITH (FUNCTION = 'email()') NOT NULL, DiscountCode SMALLINT MASKED WITH (FUNCTION = 'random(1, 100)') NULL, BirthDay DATETIME MASKED WITH (FUNCTION = 'default()') NULL );
Вставка примеров данных:
INSERT INTO Data.Membership (FirstName, LastName, Phone, Email, DiscountCode, BirthDay) VALUES ('Roberto', 'Tamburello', '555.123.4567', 'RTamburello@contoso.com', 10, '1985-01-25 03:25:05'), ('Janice', 'Galvin', '555.123.4568', 'JGalvin@contoso.com.co', 5, '1990-05-14 11:30:00'), ('Shakti', 'Menon', '555.123.4570', 'SMenon@contoso.net', 50, '2004-02-29 14:20:10'), ('Zheng', 'Mu', '555.123.4569', 'ZMu@contoso.net', 40, '1990-03-01 06:00:00');
Создайте схему для хранения таблиц служб:
CREATE SCHEMA Service; GO
Создайте таблицу служб с маскированных столбцов:
CREATE TABLE Service.Feedback ( MemberID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY CLUSTERED, Feedback VARCHAR(100) MASKED WITH (FUNCTION = 'default()') NULL, Rating INT MASKED WITH (FUNCTION = 'default()'), Received_On DATETIME );
Вставка примеров данных:
INSERT INTO Service.Feedback(Feedback, Rating, Received_On) VALUES ('Good', 4, '2022-01-25 11:25:05'), ('Excellent', 5, '2021-12-22 08:10:07'), ('Average', 3, '2021-09-15 09:00:00');
Создайте разных пользователей в базе данных:
CREATE USER ServiceAttendant WITHOUT LOGIN; GO CREATE USER ServiceLead WITHOUT LOGIN; GO CREATE USER ServiceManager WITHOUT LOGIN; GO CREATE USER ServiceHead WITHOUT LOGIN; GO
Предоставьте пользователям в базе данных разрешения на чтение:
ALTER ROLE db_datareader ADD MEMBER ServiceAttendant; ALTER ROLE db_datareader ADD MEMBER ServiceLead; ALTER ROLE db_datareader ADD MEMBER ServiceManager; ALTER ROLE db_datareader ADD MEMBER ServiceHead;
Предоставьте пользователям разные разрешения UNMASK:
--Grant column level UNMASK permission to ServiceAttendant GRANT UNMASK ON Data.Membership(FirstName) TO ServiceAttendant; -- Grant table level UNMASK permission to ServiceLead GRANT UNMASK ON Data.Membership TO ServiceLead; -- Grant schema level UNMASK permission to ServiceManager GRANT UNMASK ON SCHEMA::Data TO ServiceManager; GRANT UNMASK ON SCHEMA::Service TO ServiceManager; --Grant database level UNMASK permission to ServiceHead; GRANT UNMASK TO ServiceHead;
Запрос данных в контексте пользователя
ServiceAttendant
:EXECUTE AS USER = 'ServiceAttendant'; SELECT MemberID, FirstName, LastName, Phone, Email, BirthDay FROM Data.Membership; SELECT MemberID, Feedback, Rating FROM Service.Feedback; REVERT;
Запрос данных в контексте пользователя
ServiceLead
:EXECUTE AS USER = 'ServiceLead'; SELECT MemberID, FirstName, LastName, Phone, Email, BirthDay FROM Data.Membership; SELECT MemberID, Feedback, Rating FROM Service.Feedback; REVERT;
Запрос данных в контексте пользователя
ServiceManager
:EXECUTE AS USER = 'ServiceManager'; SELECT MemberID, FirstName, LastName, Phone, Email, BirthDay FROM Data.Membership; SELECT MemberID, Feedback, Rating FROM Service.Feedback; REVERT;
Отправка запроса к данным в контексте пользователя
ServiceHead
EXECUTE AS USER = 'ServiceHead'; SELECT MemberID, FirstName, LastName, Phone, Email, BirthDay FROM Data.Membership; SELECT MemberID, Feedback, Rating FROM Service.Feedback; REVERT;
Чтобы отозвать разрешения UNMASK, используйте следующие инструкции T-SQL:
REVOKE UNMASK ON Data.Membership(FirstName) FROM ServiceAttendant; REVOKE UNMASK ON Data.Membership FROM ServiceLead; REVOKE UNMASK ON SCHEMA::Data FROM ServiceManager; REVOKE UNMASK ON SCHEMA::Service FROM ServiceManager; REVOKE UNMASK FROM ServiceHead;