数据库安全之数据掩码:SQL 2016新功能之动态数据掩码(SQL 2016 & AZURE SQL 数据库)

Max Shen 沈云

技术解决方案专家

我们在开发上都有这样的需求:对部分敏感数据进行屏蔽,如身份证信息,名字的一部分等
显示如:
3701

在开发上,一般是取出相应的文字后进行替换,如可以用下面的方法。

function plusXing (str,StartLen,endLen) {
var len = str.length- StartLen -endLen;
var xing = '';
for (var i=0;i<len;i++) {
xing+='*';
}
return str.substr(0, StartLen)+xing+str.substr(str.length-endLen);
}

如输入 plusXing(“18023456789”,3,4)

返回结果:180****6789

但是这样的方法存在安全隐患,因为读取出来的源数据是明文。因此在SQL 2016和Azure SQL 数据库中有了一个数据掩码(Azure SQL 数据库翻译为动态数据掩码,Technet上面翻译为动态数据屏蔽)的新功能帮助解决这样的问题。

下面我们来看看能实现什么样的功能:

先在本地做个测试:

创建一张表

create TABLE Membership
(MemberID int IDENTITY PRIMARY KEY,
FirstName varchar(100) MASKED WITH (FUNCTION = 'default()') NULL, ----启用默认掩码
LastName varchar(100) NOT NULL,
Phone# varchar(13) MASKED WITH (FUNCTION = 'partial(1,"XXXXXXX",0)') NULL, ---启动动态屏蔽,从第一个字符开始使用XXXXX替换,最后不显示
Email varchar(100) MASKED WITH (FUNCTION = 'email()') NULL); ----启用email掩码
插入数据:
INSERT Membership (FirstName, LastName, Phone#, Email) VALUES
('张', '三丰', '13980040000', 'zhangsanfeng@contoso.com'),
('王', '一箭', '13698000000', 'wangyijian@contoso.com.co'),
('独孤', '九剑', '13599999999', 'dugujiujian@contoso.net');
SELECT * FROM Membership;

分配一个testuser用户赋予查询权限

CREATE USER TestUser WITHOUT LOGIN;
GRANT SELECT ON Membership TO TestUser;

使用testuser身份进行查询

EXECUTE AS USER = 'TestUser';
SELECT * FROM Membership;
REVERT;

结果如下:

3702

更改掩码

ALTER TABLE Membership
ALTER COLUMN Phone# varchar(13) MASKED WITH (FUNCTION = 'partial(3,"****",4)'); ---更改为从第三位开始,使用*来做掩码,最后显示4位

3703

ALTER TABLE Membership
ALTER COLUMN Phone# varchar(13) MASKED WITH (FUNCTION = 'partial(3,"****",5)'); ---更改为从第三位开始,使用*来做掩码,,最后显示5位

3704

授权查看未经屏蔽数据的权限 

授予 UNMASK 权限即可让 TestUser 查看未经屏蔽的数据

GRANT UNMASK TO TestUser;
EXECUTE AS USER = 'TestUser';
SELECT * FROM Membership;
REVERT;

3705

删除未屏蔽权限

-- Removing the UNMASK permission
REVOKE UNMASK TO TestUser;

3706

删除动态数据屏蔽

以下语句将删除上述示例中创建的针对 FirstName列的屏蔽:

ALTER TABLE Membership
ALTER COLUMN FirstName DROP MASKED;

3707

查询屏蔽列

通过以下语句可以查询到那些列使用了屏蔽

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;

3708

以上是在SQL 2016上完成的,再来看看Azure SQL 数据库上怎么实现

第一种方法也使用上面的代码,用SQL management studio 连接Azure SQL 数据库,如图

3709 3710

一样执行之前的代码,看看结果

create TABLE Membership
(MemberID int IDENTITY PRIMARY KEY,
FirstName varchar(100) MASKED WITH (FUNCTION = 'default()') NULL, ----启用默认掩码
LastName varchar(100) NOT NULL,
Phone# varchar(13) MASKED WITH (FUNCTION = 'partial(3,"****",4)') NULL, ---启动动态屏蔽,
Email varchar(100) MASKED WITH (FUNCTION = 'email()') NULL); ----启用email掩码

INSERT Membership (FirstName, LastName, Phone#, Email) VALUES
('张', '三丰', '13980040000', 'zhangsanfeng@contoso.com'),
('王', '一箭', '13698000000', 'wangyijian@contoso.com.co'),
('独孤', '九剑', '13599999999', 'dugujiujian@contoso.net');
SELECT * FROM Membership;

CREATE USER TestUser WITHOUT LOGIN;
GRANT SELECT ON Membership TO TestUser;

EXECUTE AS USER = 'TestUser';
SELECT * FROM Membership;
REVERT;

3711

查看掩码情况

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

3712

第二种方法,在 Azure  资源管理器 (ARM) 界面下,选择Azure SQL 数据库,数据的选项里面就有动态数据掩码选项。

3713

点击后

已经展示了使用个掩码的情况,也可以在此界面进行添加,更加简单。

3714 3715

也可以在这个界面进行修改

3716

SQL 数据库动态数据掩码通过对非特权用户模糊化敏感数据来限制此类数据的泄露。

  • 不对其进行屏蔽的 SQL 用户 - 一组可以在 SQL 查询结果中获取非屏蔽数据的 SQL 用户或 AAD 标识。 请注意,始终不会对拥有管理员权限的用户进行屏蔽,这些用户可以查看没有任何屏蔽的原始数据。
  • 屏蔽规则 - 一组规则,定义将要屏蔽的指定字段,以及要使用的屏蔽函数。 可以使用数据库架构名称、表名称和列名称定义指定的字段。
  • 屏蔽函数 - 一组方法,用于控制不同情况下的数据透露。

18

权限

不需任何特殊权限即可使用动态数据屏蔽来创建表,只需标准的 CREATE TABLE 权限以及对架构的 ALTER 权限。

添加、替换或删除对列的屏蔽,需要 ALTER ANY MASK 权限以及对表的 ALTER 权限。 可以将 ALTER ANY MASK 权限授予安全负责人。

具有表的 SELECT 权限的用户可以查看表数据。 列在被定义为“已屏蔽”后,将显示屏蔽后的数据。 对于需要从定义了屏蔽的列中检索非屏蔽数据的用户,可授予其 UNMASK 权限。

针对数据库的 CONTROL 权限包括 ALTER ANY MASKUNMASK 权限。

安全说明:可使用推断或暴力技术绕过屏蔽

上面的例子中,可以这样进行暴力推断  3719

也就是说动态掩码是一个障眼法,不能阻止你去窥探数据的本身。上面的例子就是testuser看到数据,但是他可以推测出了姓“张”的数据。

总结:

动态数据屏蔽 (DDM) 通过对非特权用户屏蔽敏感数据来限制敏感数据的公开。 它可以用于显著简化应用程序中安全性的设计和编码。

动态数据屏蔽允许用户在尽量减少对应用程序层的影响的情况下,指定需要披露的敏感数据,从而防止对敏感数据的非授权访问。 DDM 可以在数据库上进行配置,以隐藏对指定数据库字段进行查询时获得的结果集中的敏感数据,同时不会更改数据库中的数据。 可以轻松地对现有应用程序使用动态数据屏蔽,因为屏蔽规则是应用于查询结果。 许多应用程序可以屏蔽敏感数据,而无需修改现有查询。

  • 一个中央数据屏蔽策略直接对数据库中的敏感字段起作用。
  • 指定有权访问敏感数据的特权用户或角色。
  • DDM 采用完全屏蔽和部分屏蔽功能,以及用于数值数据的随机屏蔽。
  • 简单 Transact-SQL 命令定义和管理掩码。

例如,呼叫中心支持人员通过身份证号或信用卡号的几个数字就可以辨识呼叫者,但系统不会将这些数据内容完全公开给该支持人员。 可以通过定义屏蔽规则来屏蔽查询结果集中身份证号或信用卡号最后四位数字以外的所有数字。 另一个例子就是,在需要进行故障排除时,开发人员可以通过对数据进行适当的数据屏蔽来保护个人身份信息 (PII) 数据,因此可以在不违反遵从性法规的情况下,对生产环境进行查询。

动态数据屏蔽旨在限制敏感数据的公开,防止没有访问权限的用户查看敏感数据。 动态数据屏蔽并不是要防止数据库用户直接连接到数据库并运行可以公开敏感数据的详尽查询。 动态数据屏蔽是对其他 SQL Server 安全功能(审核、加密、行级别安全性…)的补充,因此,建议你将此功能与上述功能一起使用,以便更好地保护数据库中的敏感数据。