Как замаскировать значения данных от группы пользователей?

Я (младший) разработчик DWH/BI и хочу удалить разрешение на просмотр немаскированных данных для всей нашей группы (но при этом иметь возможность отозвать его в любое время). Я создал таблицу с

MASKED WITH (FUNCTION   =  'partial(1,"xxxx",0)')

- как определенные столбцы, и теперь вы хотите настроить разрешение. Я пытался:

DENY UNMASK TO PCCZ\CZ_GBUS_ITD_BI
EXECUTE AS USER = 'PCCZ\CZ_GBUS_ITD_BI'
SELECT * FROM dim.MaskingTest
REVOKE UNMASK TO PCCZ\CZ_GBUS_ITD_BI;  

person Community    schedule 06.11.2017    source источник
comment
В чем проблема?   -  person gotqn    schedule 06.11.2017
comment
Но в чем проблема? Пользователь все еще может видеть данные без маски? В соответствии с документацией КОНТРОЛЬ разрешение подразумевает UNMASK. Поэтому, если пользователь является системным администратором и/или dbowner или ему предоставлен КОНТРОЛЬ над базой данных/схемой/объектом, вы не годитесь.   -  person kirchner    schedule 06.11.2017
comment
Проблема в том, что я в группе и все еще могу видеть данные.   -  person    schedule 06.11.2017
comment
Может ли пользователь sysadmin не видеть немаскированные данные?   -  person    schedule 06.11.2017
comment
Возможно, это слишком просто, но сработает ли создание VIEW для просмотра группой и отмена разрешения на базовую таблицу?   -  person lit    schedule 06.11.2017


Ответы (1)


Вы не можете DENY UNMASK на sysadmin и db_owner. Это встроенное ограничение. Кроме того, как отмечено в документации, это не функция безопасности, если пользователь может запрашивать таблицу.

введите здесь описание изображения

Как вы можете видеть, если вы можете запросить таблицу, вы можете lie систему. Фактически, вы не должны полагаться на все эти функции в контексте SQL Server. В основном это настройка client-side (и почти ничего не делается в контексте T-SQL).

Я присутствовал на субботнем сеансе SQL под названием "Hacking SQL Server", где Андре Мелансия показал, почему динамическое маскирование данных нельзя использовать для защиты данных (опять же, это не является функцией безопасности).

Здесь вы можете найти доступные хаки, которые он продемонстрировал. Я призываю вас проверить их. Кроме того, здесь вы можете найти другие функции безопасности Microsoft, которые он взломал.

/* 
    SQL Saturday #667 Oslo 2017
    Hacking SQL Server
    2017-09-02 (version 1.33)
    Demo - Dynamic Data Masking Hacking
    André Melancia
    http://Andy.PT

    (C) 2015-2017, André Melancia

    For more information on DDM please visit
    https://msdn.microsoft.com/library/mt130841.aspx

           ________   ________    _________  ____________;_
          - ______ \ - ______ \ / _____   //.  .  ._______/
         / /     / // /     / //_/     / // ___   /
        / /     / // /     / /       .-'//_/|_/,-'
       / /     / // /     / /     .-'.-'
      / /     / // /     / /     / /
     / /     / // /     / /     / /
    / /_____/ // /_____/ /     / /
    \________- \________-     /_/

*/

--  +----------------------------------------------------------------+
--  | MISSION BRIEFING                                               |
--  +----------------------------------------------------------------+

    -- WARNING: Run these scripts on an EMPTY database!

    -- INSTRUCTIONS: Run one statement at a time.


--  +----------------------------------------------------------------+
--  | MISSION PREPARATION                                            |
--  +----------------------------------------------------------------+

    USE SQLSatOslo;         -- Or whatever database you created!
                            -- Please don't run this on the Master, that's
                            -- just ugly!
    GO

    -- Things an MI6 agent with Licence to KILL has to do
    -- Note: "IF EXISTS" are ugly. First time these will generate errors
    --       Just accept the errors as part of an agent's life ;)
    DROP USER M;
    DROP USER Q;
    DROP USER Sean;
    DROP USER David;
    DROP USER George;
    DROP USER Roger;
    DROP USER Timothy;
    DROP USER Pierce;
    DROP USER Daniel;
    GO

    DROP SECURITY POLICY AgentValidationPolicy
    GO
    DROP FUNCTION MI6_Access.FN_MI6_AgentValidationPredicate;
    GO
    DROP SCHEMA   MI6_Access;
    GO

    DROP VIEW     dbo.VIEW_BondFilms;
    GO
    DROP TABLE    dbo.BondFilms;
    GO
    DROP TABLE    dbo.Agents;
    GO
    DROP TABLE    dbo.Letters;
    GO


--  +----------------------------------------------------------------+
--  | CREATE USERS                                                   |
--  +----------------------------------------------------------------+

    CREATE USER M       WITHOUT LOGIN;
    CREATE USER Q       WITHOUT LOGIN;
    CREATE USER Sean    WITHOUT LOGIN;
    CREATE USER David   WITHOUT LOGIN;
    CREATE USER George  WITHOUT LOGIN;
    CREATE USER Roger   WITHOUT LOGIN;
    CREATE USER Timothy WITHOUT LOGIN;
    CREATE USER Pierce  WITHOUT LOGIN;
    CREATE USER Daniel  WITHOUT LOGIN;


--  +----------------------------------------------------------------+
--  | CREATE TABLE dbo.BondFilms                                     |
--  +----------------------------------------------------------------+

    CREATE TABLE dbo.BondFilms
    (
        FilmID       INT           NOT NULL,
        FilmTitle_EN NVARCHAR(64)  NOT NULL,
        FilmTitle_NO NVARCHAR(64)  NOT NULL,
        FilmYear     INT           NOT NULL, 
        BondActor    NVARCHAR(64)  NOT NULL,
        Agent        SYSNAME       NOT NULL,
        Payment      INT           NOT NULL,
        CONSTRAINT PK_BondFilms PRIMARY KEY CLUSTERED  ( FilmID ASC ) 
    );


    -- Insert some REAL top secret for-your-eyes-only information
    -- Leaked from here: https://en.wikipedia.org/wiki/List_of_James_Bond_films
    -- And fom here:     https://no.wikipedia.org/wiki/James_Bond
    INSERT INTO dbo.BondFilms
    (FilmID, FilmTitle_EN, FilmTitle_NO, FilmYear, BondActor, Agent, Payment) 
    VALUES 
    ( 1, 'Dr.No',                            'Dr.No',                          1962, 'Sean Connery',   'Sean',      10000),
    ( 2, 'From Russia with Love',            'Med hilsen fra Russland',        1963, 'Sean Connery',   'Sean',      10000),
    ( 3, 'Goldfinger',                       'Goldfinger',                     1964, 'Sean Connery',   'Sean',      10000),
    ( 4, 'Thunderball',                      'Operasjon Tordensky',            1965, 'Sean Connery',   'Sean',      10000),
    ( 5, 'Casino Royale',                    'Casino Royale',                  1967, 'David Niven',    'David',     10000),
    ( 6, 'You Only Live Twice',              'James Bond i Japan',             1967, 'Sean Connery',   'Sean',      10000),
    ( 7, 'On Her Majesty''s Secret Service', 'James Bond i hemmelig tjeneste', 1969, 'George Lazenby', 'George',    10000),
    ( 8, 'Diamonds Are Forever',             'Diamanter varer evig',           1971, 'Sean Connery',   'Sean',      10000),
    ( 9, 'Live and Let Die',                 'Å leve og la dø',                1973, 'Roger Moore',    'Roger',     10000),
    (10, 'The Man with the Golden Gun',      'Mannen med den gyldne pistol',   1974, 'Roger Moore',    'Roger',     10000),
    (11, 'The Spy Who Loved Me',             'Spionen som elsket meg',         1977, 'Roger Moore',    'Roger',     10000),
    (12, 'Moonraker',                        'Måneraketten',                   1979, 'Roger Moore',    'Roger',     10000),
    (13, 'For Your Eyes Only',               'Kun for dine øyne',              1981, 'Roger Moore',    'Roger',     10000),
    (14, 'Octopussy',                        'Octopussy',                      1983, 'Roger Moore',    'Roger',     10000),
    (15, 'Never Say Never Again',            'Aldri si aldri',                 1983, 'Sean Connery',   'Sean',    3552822), /* 3552822 = 0x363636 = "36 36 36 00" little endian */
    (16, 'A View to a Kill',                 'Med døden i sikte',              1985, 'Roger Moore',    'Roger',     10000),
    (17, 'The Living Daylights',             'I skuddlinjen',                  1987, 'Timothy Dalton', 'Timothy',   10000),
    (18, 'Licence to Kill',                  'Med rett til å drepe',           1989, 'Timothy Dalton', 'Timothy',   10000),
    (19, 'GoldenEye',                        'GoldenEye',                      1995, 'Pierce Brosnan', 'Pierce',    10000),
    (20, 'Tomorrow Never Dies',              'Tomorrow Never Dies',            1997, 'Pierce Brosnan', 'Pierce',    10000),
    (21, 'The World Is Not Enough',          'The World Is Not Enough',        1999, 'Pierce Brosnan', 'Pierce',    10000),
    (22, 'Die Another Day',                  'Die Another Day',                2002, 'Pierce Brosnan', 'Pierce',    10000),
    (23, 'Casino Royale',                    'Casino Royale',                  2006, 'Daniel Craig',   'Daniel',  3552822), /* 3552822 = 0x363636 = "36 36 36 00" little endian */
    (24, 'Quantum of Solace',                'Quantum of Solace',              2008, 'Daniel Craig',   'Daniel',    10000),
    (25, 'Skyfall',                          'Skyfall',                        2012, 'Daniel Craig',   'Daniel',    10000),
    (26, 'Spectre',                          'Spectre',                        2015, 'Daniel Craig',   'Daniel',    10000);


    -- Super advanced top secret spying technique
    SELECT * FROM dbo.BondFilms;

    GO


--  +----------------------------------------------------------------+
--  | CREATE TABLE dbo.BondActors                                    |
--  +----------------------------------------------------------------+

    CREATE TABLE dbo.Agents
    (
        Agent      SYSNAME       NOT NULL,
        BondActor  NVARCHAR(64)  NOT NULL,
        CONSTRAINT PK_Agents PRIMARY KEY CLUSTERED  ( Agent ASC ) 
    );


    -- Insert some REAL top secret for-your-eyes-only information
    -- Leaked from here: https://en.wikipedia.org/wiki/List_of_James_Bond_films
    INSERT INTO dbo.Agents 
    (Agent, BondActor) 
    SELECT DISTINCT Agent, BondActor
    FROM dbo.BondFilms;


    -- Super advanced top secret spying technique
    SELECT * FROM dbo.Agents;

    GO


--  +----------------------------------------------------------------+
--  | MASK COLUMN WITH DYNAMIC DATA MASKING                          |
--  +----------------------------------------------------------------+

    -- Mask the Agent column with DDM.
    ALTER TABLE dbo.BondFilms
    ALTER COLUMN BondActor ADD MASKED WITH (FUNCTION = 'Partial(2, "▪▪▪", 1)');
    GO

    -- We are so confident in our security that we're assigning read permissions
    --     to everyone.
    --     /!\ Please don't do this in a production environment, assign 
    --     permissions to the group(s) or role(s) the users belong
    GRANT SELECT ON dbo.BondFilms TO Public;
    GRANT SELECT ON dbo.Agents    TO Public;

    GRANT UNMASK TO M; -- M is allowed to see masked fields

    -- Super advanced top secret spying technique
    SELECT *, 'Seen as DBO using DDM'  AS Who FROM dbo.BondFilms; -- Returns unmasked

    EXECUTE AS USER = 'M';
    SELECT *, 'Seen as M using DDM'    AS Who FROM dbo.BondFilms; -- Returns unmasked 
    REVERT; -- Go back to connection default user

    EXECUTE AS USER = 'Sean';
    SELECT *, 'Seen as Sean using DDM' AS Who FROM dbo.BondFilms; -- Returns masked  
    REVERT;

    GO


--  +----------------------------------------------------------------+
--  | DYNAMIC DATA MASKING EXPLOIT - "0. Mission preparation"        |
--  +----------------------------------------------------------------+

    REVERT; REVERT; REVERT; REVERT; REVERT; REVERT; 

    -- Turn on viewing of Execution Plan (Ctrl-M)

    -- Allow everyone to see Execution Plan
    GRANT SHOWPLAN TO Public; -- NEVER do this in production!!!


--  +----------------------------------------------------------------+
--  | DYNAMIC DATA MASKING EXPLOIT - "1. WHERE HACK"                 |
--  +----------------------------------------------------------------+

    EXECUTE AS USER = 'Sean';
    SELECT *, 'Seen as Sean using DDM with WHERE hack' AS Who 
    FROM dbo.BondFilms
    WHERE BondActor Like '%Roger%' -- Hack: infer the content of the field
    REVERT;


--  +----------------------------------------------------------------+
--  | DYNAMIC DATA MASKING EXPLOIT - "2. EXACT JOIN HACK"            |
--  +----------------------------------------------------------------+

    EXECUTE AS USER = 'Sean';
    SELECT b.*, a.BondActor AS AGENTS_BondActor, 'Seen as Sean using DDM with EXACT JOIN hack' AS Who 
    FROM dbo.BondFilms b
         INNER JOIN
         dbo.Agents a
         ON b.BondActor = a.BondActor -- Hack: infer the content with JOIN
    REVERT;


--  +----------------------------------------------------------------+
--  | DYNAMIC DATA MASKING EXPLOIT - "3. PARTIAL JOIN HACK"          |
--  +----------------------------------------------------------------+

    -- Special thanks to 
    --     Dmitri V. Korotkevitch
    --     http://aboutsqlserver.com
    --     [email protected]  


    -- Create a table with single letters 
    -- (let's assume it's case INsensitive)
    CREATE TABLE dbo.Letters
    (
        Letter NVARCHAR(1)  NOT NULL,
        CONSTRAINT PK_Letters PRIMARY KEY CLUSTERED  ( Letter ASC ) 
    );

    INSERT INTO dbo.Letters (Letter)
    VALUES ('A'), ('B'), ('C'), ('D'), ('E'), ('F'), ('G'), ('H'), ('I'), 
           ('J'), ('K'), ('L'), ('M'), ('N'), ('O'), ('P'), ('Q'), ('R'),
           ('S'), ('T'), ('U'), ('V'), ('W'), ('X'), ('Y'), ('Z'), (' ');

    GRANT SELECT ON dbo.Letters TO Public; -- Very safe!

    -- Spies don't call it stalking...
    SELECT * FROM dbo.Letters;


    -- Get letter by letter (here using subqueries)...
    EXECUTE AS USER = 'Sean';
    SELECT b.*, 
           k01.Letter AS L01,
           k02.Letter AS L02,
           k03.Letter AS L03,
           k04.Letter AS L04,
           k05.Letter AS L05,
           k06.Letter AS L06,
           k07.Letter AS L07,
           k08.Letter AS L08,
           k09.Letter AS L09,
           k10.Letter AS L10,
           k11.Letter AS L11,
           k12.Letter AS L12,
           k13.Letter AS L13,
           k14.Letter AS L14,
           'Seen as Sean using DDM with PARTIAL JOIN hack' AS Who 
    FROM dbo.BondFilms b
         INNER JOIN dbo.Letters AS k01 ON (k01.Letter = SUBSTRING(b.BondActor,01,1))
         INNER JOIN dbo.Letters AS k02 ON (k02.Letter = SUBSTRING(b.BondActor,02,1))
         INNER JOIN dbo.Letters AS k03 ON (k03.Letter = SUBSTRING(b.BondActor,03,1))
         INNER JOIN dbo.Letters AS k04 ON (k04.Letter = SUBSTRING(b.BondActor,04,1))
         INNER JOIN dbo.Letters AS k05 ON (k05.Letter = SUBSTRING(b.BondActor,05,1))
         INNER JOIN dbo.Letters AS k06 ON (k06.Letter = SUBSTRING(b.BondActor,06,1))
         INNER JOIN dbo.Letters AS k07 ON (k07.Letter = SUBSTRING(b.BondActor,07,1))
         INNER JOIN dbo.Letters AS k08 ON (k08.Letter = SUBSTRING(b.BondActor,08,1))
         INNER JOIN dbo.Letters AS k09 ON (k09.Letter = SUBSTRING(b.BondActor,09,1))
         INNER JOIN dbo.Letters AS k10 ON (k10.Letter = SUBSTRING(b.BondActor,10,1))
         INNER JOIN dbo.Letters AS k11 ON (k11.Letter = SUBSTRING(b.BondActor,11,1))
         INNER JOIN dbo.Letters AS k12 ON (k12.Letter = SUBSTRING(b.BondActor,12,1))
         INNER JOIN dbo.Letters AS k13 ON (k13.Letter = SUBSTRING(b.BondActor,13,1))
         INNER JOIN dbo.Letters AS k14 ON (k14.Letter = SUBSTRING(b.BondActor,14,1))
    REVERT;

    -- Missing some characters? Create a bigger Unicode table...


--  +----------------------------------------------------------------+
--  | DYNAMIC DATA MASKING EXPLOIT - "4. PARTIAL SUBQUERY HACK"      |
--  +----------------------------------------------------------------+

    -- This WILL NOT WORK. Why? 
    -- Because you are getting the "BondActor" column at the SELECT
    -- stage, not the FROM or WHERE stages! 

    -- Get letter by letter (here using subqueries)...
    EXECUTE AS USER = 'Sean';
    SELECT b.*, 
           (SELECT Letter FROM dbo.Letters AS k01 WHERE k01.Letter = SUBSTRING(b.BondActor,1,1)) AS L01,
           (SELECT Letter FROM dbo.Letters AS k02 WHERE k02.Letter = SUBSTRING(b.BondActor,2,1)) AS L02,
           (SELECT Letter FROM dbo.Letters AS k03 WHERE k03.Letter = SUBSTRING(b.BondActor,3,1)) AS L03,
           'Seen as Sean using DDM with PARTIAL FIND hack' AS Who 
    FROM dbo.BondFilms b
    REVERT;


--  +----------------------------------------------------------------+
--  | DYNAMIC DATA MASKING EXPLOIT - "..."                           |
--  +----------------------------------------------------------------+

    -- (Your exploit here)
    -- Found more exploits? Let me know!


--  +----------------------------------------------------------------+
--  | Mission is now over.                                           |
--  | You can't run away with the Bond Girl because you're an NSA    |
--  | agent, not an MI6 agent.                                       |
--  | Consider changing sides: MI6 has better... eh... cars...       |
--  +----------------------------------------------------------------+
person gotqn    schedule 06.11.2017
comment
Эй, я знаю, что это старый вопрос, но что бы вы порекомендовали, чтобы скрыть данные от общедоступных пользователей (мне нужно сделать это в тестовой среде и скрыть конфиденциальные данные для разработчиков. - person Racer SQL; 17.03.2021