MSSQL - 最佳實踐 - 如何打碼隱私數據列

摘要

在SQL Server安全系列專題月報分享中,咱們已經分享了:如何使用對稱密鑰實現SQL Server列加密技術、使用非對稱密鑰加密方式實現SQL Server列加密、使用混合密鑰實現SQL Server列加密技術、列加密技術帶來的查詢性能問題以及相應解決方案和行級別安全解決方案這五篇文章,文章詳情能夠參見往期月報。本期月報咱們分享使用SQL Server 2016 dynamic data masking實現隱私數據列的打碼技術最佳實踐。數據庫

問題引入

在平日的生活中,咱們或多或少都經歷過廣告推銷、電話詐騙,不厭其煩,甚至更爲嚴重到銀行卡號泄漏、身份證號泄漏等更爲嚴重的狀況。這個時候,因而咱們就在想有沒有技術手段來儘可能或最大限度的保護咱們隱私數據安全呢?答案是確定的,SQL Server 2016版本首次引入了dynamic data masking來實現隱私數據列的打碼技術,讓咱們一塊兒來看看如何實現相似於手機號、身份證號、駕照號等隱私數據打碼技術。安全

原理分析

數據列打碼技術的自己咱們並不陌生,就是將一些比較私密的數據信息隱藏起來,僅開放給有較高權限的用戶查看完整數據。打碼技術自己並不會對數據作任何的加密、解密等操做。嚴格意義上講,數據打碼不是一個完整的數據安全解決方案,可是它能夠做爲安全策略中重要的一環來有效避免用戶隱私數據列的泄漏。讓咱們一塊兒來看看在SQL Server 2016 dynamic data masking是如何實現的。函數

實現方法

建立測試數據庫性能

爲了測試方便,咱們專門建立了測試數據庫TestDb。測試

--Step 1 - Create MSSQL sample database
USE master
GO
IF DB_ID('TestDb') IS NULL
    CREATE DATABASE [TestDb];
GO

建立測試表加密

首先,咱們建立一張常規表CustomerInfo,來存放客戶信息,其中,CustomerPhone列爲用戶隱私數據,存放了用戶的手機號碼。spa

--Step 2 - Create Test Table, init records
USE [TestDb]
GO
IF OBJECT_ID('dbo.CustomerInfo', 'U') IS NOT NULL
    DROP TABLE dbo.CustomerInfo
CREATE TABLE dbo.CustomerInfo
(
CustomerId        INT IDENTITY(10000,1)    NOT NULL PRIMARY KEY,
CustomerName    VARCHAR(100)            NOT NULL,
CustomerPhone    CHAR(11)                NOT NULL
);

-- Init Table
INSERT INTO dbo.CustomerInfo 
VALUES ('CustomerA','13402872514')
,('CustomerB','13880674722')
,('CustomerC','13487759293')
GO

建立測試用戶code

爲了方便觀察和檢查測試效果,咱們建立一個測試帳號DemoUser。ci

-- Step3: Create a DemoUser to test
USE [TestDb]
GO
CREATE USER DemoUser WITHOUT LOGIN;
GRANT SELECT ON dbo.CustomerInfo TO DemoUser;
GO

EXECUTE AS USER = 'DemoUser';
-- Verify data
SELECT * 
FROM dbo.CustomerInfo

REVERT

常規狀況下,測試帳號,能夠清清楚楚,明明白白看到用戶全部數據,包含客戶手機號這種關鍵的隱私數據。若是,這個用戶有不軌之心是很是容易將這些信息泄漏、導出的,安全風險較大。rem

客戶手機號打碼

因而,咱們想,若是可以將客戶隱私數據,好比,電話號碼(身份證號碼、銀行卡號等)打碼的話,那麼測試帳號就沒法查看到用戶完整的數據信息了。打碼方法以下:

-- Step4: Alter phone column add data mask
USE [TestDb]
GO

ALTER TABLE dbo.CustomerInfo
ALTER COLUMN CustomerPhone ADD MASKED WITH(FUNCTION='partial(3, "****", 4)');

因爲CustomerPhone是11位數字,咱們使用partial方法打碼隱藏中間四位,打碼符號使用星號,保留前三位和後四位數數字便可。

查詢打碼列

打碼完畢,咱們使用系統試圖查看打碼列和打碼函數:

-- Step5\. Query system view to check data mask
SELECT
    db_name() as database_name, 
    SCHEMA_NAME(schema_id) AS schema_name, 
    tbl.name as table_name, 
    c.name as column_name, 
    c.is_masked, 
    c.masking_function  
FROM sys.masked_columns AS c  WITH (NOLOCK)
    INNER JOIN sys.tables AS tbl   WITH(NOLOCK)
    ON c.[object_id] = tbl.[object_id]  
WHERE c.is_masked = 1
    AND tbl.name = 'CustomerInfo';

從結果能夠看到咱們已經將表TestDb.dbo.CustomerInfo中字段CustomerPhone打碼,打碼函數爲partial(3, "**", 4),結果展現以下所示:

測試用戶查看數據

打碼完畢後,再次使用DemoUser測試帳號查看打碼後的數據:

-- Step6: Demo user to query and verify data
USE [TestDb]
GO
EXECUTE AS USER = 'DemoUser';
-- Verify data
SELECT * 
FROM dbo.CustomerInfo

REVERT

從查詢結果展現來看,客戶手機號碼列中間四位已經成功打碼了,測試帳號已經沒法獲取到完整的客戶電話號碼了。

修改打碼符號

有時候,有的人會說,我不喜歡星號,可否換個打碼姿式,我更喜歡使用字母X。只要你喜歡,隨便切換,方法以下:

-- Step7: What if I want to change the mask sign from * to X
USE [TestDb]
GO

ALTER TABLE dbo.CustomerInfo
ALTER COLUMN CustomerPhone CHAR(11) MASKED WITH(FUNCTION='partial(3, "XXXX", 4)');

如今打碼符號變成了X,展現以下:

新增隱私打碼列

如今咱們須要增長一個新的列,用來存放用戶email地址,也請同時打碼。很是簡單,新增列的時候使用email打碼函數便可,以下所示:

-- Step8: and I want to add a new email mask column
ALTER TABLE dbo.CustomerInfo
ADD Email varchar(100) MASKED WITH (FUNCTION = 'email()')  NOT NULL DEFAULT('demo.user@test.com')

查詢打碼列特定值

有的人可能會問,手機號碼被打碼了,這個列會影響個人WHERE語句查詢嗎?固然不會,由於data mask技術自己並無對數據作任何修改,只是在展現的時候,打碼隱藏掉部分信息而已。

-- Step9: Demo user to query the specified phone customer info
USE [TestDb]
GO
EXECUTE AS USER = 'DemoUser';
-- Verify data
SELECT * 
FROM dbo.CustomerInfo
WHERE CustomerPhone = '13880674722'

REVERT

查詢結果展現,手機號碼和email地址始終被打碼。

拷貝存在打碼列的表

咱們說data mask技術並無加密、修改數據自己。到目前爲止,測試帳號DemoUser已經沒法獲取到客人的關鍵隱私數據了,那麼他可以將用戶數據Copy、導出嗎?讓咱們作一個簡單的測試,DemoUser將表CustomerInfo複製到一個新表CustomerInfo_copied中:

-- Step10: Ops, if I copy a new table from the data masked table, I can't get the unmasked data now.
USE [TestDb]
GO
GRANT CREATE TABLE TO DemoUser;
GRANT ALTER ON SCHEMA::dbo TO DemoUser;
EXECUTE AS USER = 'DemoUser';
-- Verify data
SELECT * 
    INTO dbo.CustomerInfo_copied
FROM dbo.CustomerInfo

REVERT

GRANT SELECT ON dbo.CustomerInfo_copied TO DemoUser;
EXECUTE AS USER = 'DemoUser';
SELECT * FROM dbo.CustomerInfo_copied
REVERT

DemoUser複製了客戶信息數據到新表後,查看新表中的數據,依然是被打碼的,測試用戶沒法導出、複製客人的隱私數據。達到了安全策略保護客戶隱私數據的目的,展現結果以下:

我想要在無碼的世界

若是有一天DemoUser成了高權限用戶,確實須要查看客戶隱私數據列,這個時候,咱們能夠給予測試帳號unmask的權限,他就能夠看到完整的客戶數據了。方法以下:

-- Step 11: But, how can demo user to query the unmasked data?
USE TestDB
GO

GRANT UNMASK TO DemoUser;  
EXECUTE AS USER = 'DemoUser';  
SELECT * FROM dbo.CustomerInfo;  
REVERT;   

-- Removing the UNMASK permission  
REVOKE UNMASK TO DemoUser;

此時,DemoUser查詢到的數據,是很是完整的客人數據。

刪掉打碼

刪除打碼,讓全部用戶迴歸無碼的世界。

-- Step 12: all the demos have been done, it's time to drop the mask.
USE TestDB
GO
ALTER TABLE dbo.CustomerInfo   
ALTER COLUMN CustomerPhone DROP MASKED;

最後總結

本期月報咱們分享了使用SQL Server 2016引入的新特性dynamic data masking實現客戶數據打碼技術,防止未受權用戶查看、導出用戶關鍵隱私數據,最大限度保證用戶數據安全性。



本文做者:風移

閱讀原文

本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索