sql 改写类的数据脱敏遇到的问题求助

2020-11-19 18:00:10 +08:00
 zczy

https://github.com/xylou/sqlMask

为了找工作写的一个开源项目,但是觉得有点问题了

是通过改写 sql 来做的数据脱敏

比如要查询 phoneNum,phoneNum 配置了策略是隐藏最后四位,mask(col,8,11,*)

select phoneNum from table

那改写 sql 的结果就是

select mask(phoneNum,8,11,*) phoneNum from table

如果是上面的这种普通 sql 还比较好处理

但是现在有这么个问题,比如下面这种类型的 sql

  1. select phoneNum from (select phoneNum from table) t where phoneNum = '13800001111';

如果改写成这种,这也是我现在的方案

select phoneNum from (select mask(phoneNum,8,11,*) phoneNum from table) t where t.phoneNum = '13800001111';

那其实就有问题了,where 语句是有问题的

如果改写成这种:

select mask(phoneNum,8,11,*) phoneNum from (select phoneNum from table) t where t.phoneNum = '13800001111';

那数据安全就不能保证,因为我可以写下面这种 sql 查到原始数据

select phoneNum from (select '12345678900' + phoneNum as phoneNum from table) t where phoneNum = '13800001111';

一定程度可以绕过了

应该怎么处理呢

2653 次点击
所在节点    程序员
27 条回复
annielong
2020-11-19 18:03:39 +08:00
习惯上最外层再套一个 select 进行处理
zczy
2020-11-19 18:08:50 +08:00
@annielong 啥意思
RRRoger
2020-11-19 18:29:10 +08:00
```sql

SELECT phoneNum_hide
FROM
(SELECT mask(phoneNum,8,11,*) AS phoneNum_hide,
phoneNum AS phoneNum
FROM TABLE) t
WHERE t.phoneNum = '13800001111';



```

这样呢
zczy
2020-11-19 18:39:56 +08:00
@RRRoger

不行,这样在最外层 select * 就全能看到了

不安全
xuanbg
2020-11-19 18:42:39 +08:00
脱敏函数只接受一个 phoneNum 不就好了吗?

select mask(phoneNum) phoneNum from table t where t.phoneNum = '13800001111';
zczy
2020-11-19 18:57:20 +08:00
@xuanbg

不行啊,我这个是封装了一个 rest 服务

不能规范用户行为的,要杜绝能够查出原始数据的行为
yangzh
2020-11-19 23:34:48 +08:00
数据库里面弄一个脱敏视图,然后所有 select 都只走脱敏视图,保证没有任何办法查到敏感数据
buliugu
2020-11-20 09:38:06 +08:00
釜底抽薪,直接写个 mask jbdc driver 吧,做一遍 sql parser 自动改写所有涉及字段的 sql
zczy
2020-11-20 09:52:29 +08:00
@yangzh 你这个叫静态脱敏,我这个接口也是支持 create table/view as select 操作的

@buliugu 这个就是用 calcite 做的 sql parse
zczy
2020-11-20 10:15:57 +08:00
@RRRoger

但是这个思路估计是可以的

需要再写一个执行查询的接口,不让看到中间 sql 就行

原来只有 loadPolicy 和 loadMetadata 接口
buliugu
2020-11-20 13:50:39 +08:00
@zczy 那就是 hook 的不到位啊,遍历 AST 理论上可以拿到 sq 所有 l 的信息
zczy
2020-11-20 13:59:41 +08:00
@buliugu

没明白什么意思,现在查到原始列了啊

问题是 where 语句里的列啊
buliugu
2020-11-20 14:42:11 +08:00
@zczy 不仅仅是原始列,虚拟表也要 hook 处理。所有可能查询的地方都要 hook 的
zczy
2020-11-20 14:49:07 +08:00
@buliugu
那这种就不是改写 sql 了
dayeye2006199
2020-11-20 15:11:22 +08:00
select phoneNum from (select mask(phoneNum,8,11,*) from table where t.phoneNum = '13800001111');

where 放在里面可不可以呢?
zczy
2020-11-20 16:02:58 +08:00
@dayeye2006199
当然不可以啦

with t1 as (select name from emps union select name from depts) select name from t1

你看一下这种类型的 sql

```
@Test
public void sqlTest4() throws Exception {
String originSql = "with t1 as (select name from emps union select name from depts) select name from t1";
String expectSql = "with t1 as (select hash_fun(1, 5, emps.name, '*') as name\n" +
"from sales.emps as emps\n" +
"union\n" +
"select hash_fun3(1, 7, depts.name, '*') as name\n" +
"from sales.depts as depts) (select t1.name\n" +
"from t1 as t1)";
String maskSql = qs3.getMaskSql(originSql);
compareSql(maskSql, expectSql);
}
```

如果后面有 where 语句的话
gengzi
2020-11-20 17:21:52 +08:00
你这个是查询 sql,返回脱敏的 sql ?
zczy
2020-11-20 17:48:48 +08:00
@gengzi
对,只是对 sql 语句的改写

分了三个模块,policy,metadata,rewriteSql 部分

https://github.com/xylou/sqlMask
zczy
2020-11-20 17:59:26 +08:00
@buliugu
还有啥好的思路吗,大佬
buliugu
2020-11-21 12:17:26 +08:00
@zczy 一样啊,subquery factoring 语法也是可以通过 ast 发现的,说白了使用这种模式做 data masking,就是苦力活,sql 所有可能查询到数据的语法都得 hook 掉。。更要命的是不同数据库语法不一样(逃

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/727240

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX