在平日的生活中,我们或多或少都经历过广告推销、电话诈骗,不厌其烦,甚至更为严重到银行卡号泄漏、身份证号泄漏等更为严重的情况。这个时候,于是我们就在想有没有技术手段来尽量或最大限度的保护我们隐私数据安全呢?答案是肯定的,SQL Server 2016版本首次引入了dynamic data masking来实现隐私数据列的打码技术,让我们一起来看看如何实现类似于手机号、身份证号、驾照号等隐私数据打码技术。

数据列打码技术的本身我们并不陌生,就是将一些比较私密的数据信息隐藏起来,仅开放给有较高权限的用户查看完整数据。打码技术本身并不会对数据做任何的加密、解密等操作。严格意义上讲,数据打码不是一个完整的数据安全解决方案,但是它可以作为安全策略中重要的一环来有效避免用户隐私数据列的泄漏。让我们一起来看看在SQL Server 2016 dynamic data masking是如何实现的。

为了测试方便,我们专门创建了测试数据库TestDb。

创建测试表

首先,我们创建一张常规表CustomerInfo,来存放客户信息,其中,CustomerPhone列为用户隐私数据,存放了用户的手机号码。

  1. USE [TestDb]
  2. GO
  3. IF OBJECT_ID('dbo.CustomerInfo', 'U') IS NOT NULL
  4. DROP TABLE dbo.CustomerInfo
  5. CREATE TABLE dbo.CustomerInfo
  6. (
  7. CustomerId INT IDENTITY(10000,1) NOT NULL PRIMARY KEY,
  8. CustomerName VARCHAR(100) NOT NULL,
  9. CustomerPhone CHAR(11) NOT NULL
  10. );
  11. -- Init Table
  12. INSERT INTO dbo.CustomerInfo
  13. VALUES ('CustomerA','13402872514')
  14. ,('CustomerB','13880674722')
  15. ,('CustomerC','13487759293')
  16. GO

创建测试用户

为了方便观察和检查测试效果,我们创建一个测试账号DemoUser。

  1. USE [TestDb]
  2. GO
  3. CREATE USER DemoUser WITHOUT LOGIN;
  4. GRANT SELECT ON dbo.CustomerInfo TO DemoUser;
  5. GO
  6. EXECUTE AS USER = 'DemoUser';
  7. -- Verify data
  8. SELECT *
  9. FROM dbo.CustomerInfo
  10. REVERT

常规情况下,测试账号,可以清清楚楚,明明白白看到用户所有数据,包含客户手机号这种关键的隐私数据。如果,这个用户有不轨之心是非常容易将这些信息泄漏、导出的,安全风险较大。

客户手机号打码

于是,我们想,如果能够将客户隐私数据,比如,电话号码(身份证号码、银行卡号等)打码的话,那么测试账号就无法查看到用户完整的数据信息了。打码方法如下:

  1. -- Step4: Alter phone column add data mask
  2. USE [TestDb]
  3. GO
  4. ALTER TABLE dbo.CustomerInfo
  5. ALTER COLUMN CustomerPhone ADD MASKED WITH(FUNCTION='partial(3, "****", 4)');

由于CustomerPhone是11位数字,我们使用partial方法打码隐藏中间四位,打码符号使用星号,保留前三位和后四位数数字即可。

从结果可以看到我们已经将表TestDb.dbo.CustomerInfo中字段CustomerPhone打码,打码函数为partial(3, “\**”, 4),结果展示如下所示:

02.png

测试用户查看数据

打码完毕后,再次使用DemoUser测试账号查看打码后的数据:

  1. -- Step6: Demo user to query and verify data
  2. USE [TestDb]
  3. GO
  4. EXECUTE AS USER = 'DemoUser';
  5. -- Verify data
  6. SELECT *
  7. FROM dbo.CustomerInfo
  8. REVERT

从查询结果展示来看,客户手机号码列中间四位已经成功打码了,测试账号已经无法获取到完整的客户电话号码了。

修改打码符号

有时候,有的人会说,我不喜欢星号,能否换个打码姿势,我更喜欢使用字母X。只要你喜欢,随便切换,方法如下:

  1. -- Step7: What if I want to change the mask sign from * to X
  2. USE [TestDb]
  3. GO
  4. ALTER TABLE dbo.CustomerInfo
  5. ALTER COLUMN CustomerPhone CHAR(11) MASKED WITH(FUNCTION='partial(3, "XXXX", 4)');

现在打码符号变成了X,展示如下:

04.png

新增隐私打码列

现在我们需要增加一个新的列,用来存放用户email地址,也请同时打码。非常简单,新增列的时候使用email打码函数即可,如下所示:

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

查询结果展示,手机号码和email地址始终被打码。

拷贝存在打码列的表

我们说data mask技术并没有加密、修改数据本身。到目前为止,测试账号DemoUser已经无法获取到客人的关键隐私数据了,那么他能够将用户数据Copy、导出吗?让我们做一个简单的测试,DemoUser将表CustomerInfo复制到一个新表CustomerInfo_copied中:

  1. -- Step10: Ops, if I copy a new table from the data masked table, I can't get the unmasked data now.
  2. USE [TestDb]
  3. GO
  4. GRANT ALTER ON SCHEMA::dbo TO DemoUser;
  5. EXECUTE AS USER = 'DemoUser';
  6. -- Verify data
  7. SELECT *
  8. INTO dbo.CustomerInfo_copied
  9. FROM dbo.CustomerInfo
  10. REVERT
  11. GRANT SELECT ON dbo.CustomerInfo_copied TO DemoUser;
  12. EXECUTE AS USER = 'DemoUser';
  13. SELECT * FROM dbo.CustomerInfo_copied
  14. REVERT

DemoUser复制了客户信息数据到新表后,查看新表中的数据,依然是被打码的,测试用户无法导出、复制客人的隐私数据。达到了安全策略保护客户隐私数据的目的,展示结果如下:

06.png

我想要在无码的世界

如果有一天DemoUser成了高权限用户,确实需要查看客户隐私数据列,这个时候,我们可以给予测试账号unmask的权限,他就可以看到完整的客户数据了。方法如下:

  1. -- Step 11: But, how can demo user to query the unmasked data?
  2. USE TestDB
  3. GO
  4. GRANT UNMASK TO DemoUser;
  5. EXECUTE AS USER = 'DemoUser';
  6. SELECT * FROM dbo.CustomerInfo;
  7. REVERT;
  8. -- Removing the UNMASK permission
  9. REVOKE UNMASK TO DemoUser;

此时,DemoUser查询到的数据,是非常完整的客人数据。

删掉打码

删除打码,让所有用户回归无码的世界。

  1. -- Step 12: all the demos have been done, it's time to drop the mask.
  2. USE TestDB
  3. GO
  4. ALTER TABLE dbo.CustomerInfo