DLP数据泄露防护系统设计

本文最后更新于 2025年11月25日 晚上

项目链接:https://github.com/J-0k3r/JJDLP

前期思考

  • 开发基于正常业务考虑,只做关键识别与处理流程。去除繁杂另类功能。如正常业务上传文件类型与肯定与后缀一致,故不做文件类型分析校验,所以只做一个统一文件上传入口只根据后缀进入不同识别分支,如果上传文件类型与后缀不一致则只输出识别失败,而不会根据文件头尾纠错。
  • api封装:路由请求和返回值统一用json格式并将系统封装为api,可作为识别模块方便外部服务调用。
  • 只考虑了中国大陆条件下的敏感信息(港澳台国外身份证/银行卡/手机号等不考虑)。
  • 只记录,不存储:出于安全考虑不存储所有上传识别/脱敏的文件,仅作记录。
  • 模块化设计:不同的识别/脱敏等功能分别作为单独模块(如pdf单独一个.py,json单独一个.py),方便维护。
  • 扩展性:提供自定义敏感数据类型和识别/脱敏规则扩展接口,方便扩展新的敏感数据。

识别模块

https://github.com/J-0k3r/JJDLP/tree/master/processors

csv识别

由于CSV结构化数据特性,基于正常业务考虑,同一列下的数据是同类的,对于敏感数据来说,如身份证号列下的数据肯定都是身份证号。

故在识别csv敏感数据的时候,只要识别到一条验证为敏感数据则将该列归类为同类型敏感数据并统计数量,然后进行后续流程,省去每一条数据验证的重复任务,在数据量大的情况下大大节省时间开支。

1
2
3
4
5
姓名,证件号码,手机号码,电子邮箱
张三,310101199003072316,13812345678,zhangsan@example.com #仅识别第一行数据
李四,310101198512124512,13987654321,lisi@example.com
王五,310101199206187890,15011112222,wangwu@example.com
赵六,310101198811113210,18666668888,zhaoliu@example.com

json识别

json同为结构化数据类型,在处理时同CSV考虑。对于同一键名,只要识别到一条敏感数据,则该键名的键值全视为同类型的敏感数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
"people": [
{
"name": "张三",
"id": "310101199003072316", // 身份证号码
"phone": "13812345678", // 手机号码
"email": "zhangsan@example.com"
},
{
"name": "李四",
"id": "310101198512124512", // 身份证号码
"phone": "13987654321", // 手机号码
"email": "lisi@example.com"
},
{
"name": "王五",
"id": "310101199206187890", // 身份证号码
"phone": "15011112222", // 手机号码
"email": "wangwu@example.com"
},
{
"name": "赵六",
"id": "310101198811113210", // 身份证号码
"phone": "18666668888", // 手机号码
"email": "zhaoliu@example.com"
}
]
}

取键名为id的所有键值当作身份证号码。

docx 识别

docx文件本质是压缩包,其内容在xml里,通过xml标签可以定位其数据。在业务中,以docx存储的文件通常是技术文档/方案,身份证/银行卡等扫描件、图片,包含身份证、地址等敏感信息的申请表(如入职表含个人信息身份证/电话号码等)。根据xml标签来做不同的识别,如果识别到图片标签则调用图片识别的方法,表格标签则编写对应的方法来识别。

由于技术文档/方案等敏感数据的特征不明显,识别起来较难(通过检测盲水印或者机器学习等来识别),所以如果是这种类型的文件通过手动导入进行标注即可。

PDF识别

PDF的本质是二进制数据流,内容通常以文本对象、图像对象、矢量图形、表格(伪表格/真实表格)等形式存储。在业务中,PDF与docx的内容数据大致相同,所以识别规则同docx。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
┌──────────────────────────────────────┐
│ PDF 文件头部 │ ← %PDF-1.x(如 %PDF-1.7
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
│ 主体部分(Body) │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 对象 1 │ │ 对象 2 │ │
│ │ (文本内容) │ │ (图像流) │ │
│ └─────────────┘ └─────────────┘ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 对象 3 │ │ 对象 4 │ │
│ │ (页面树) │ │ (字体资源) │ │
│ └─────────────┘ └─────────────┘ │
│ ...(多个间接对象,编号唯一) │
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
│ 交叉引用表(xref table) │
0 0000000000 65535 f │
1 0000000123 00000 n │ ← 指向对象1在文件中的字节偏移
2 0000000456 00000 n │ ← 指向对象2...
│ ... │
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
│ 文件尾(Trailer) │
│ << │
│ /Size 5 │ ← 对象总数
│ /Root 1 0 R │ ← 根对象(Catalog)
│ /Info 2 0 R │ ← 文档信息
│ >> │
│ startxref │
9876 │ ← xref 表起始位置
│ %%EOF │ ← 文件结束标志
└──────────────────────────────────────┘

图片识别

正常业务中以图片形式存储的敏感数据大多以单条形式存在,比如某一张身份证扫描图片/学信网截图/营业执照图片。对于图像数据来说这些图片大部分是相同的(如身份证布局&字段都是一样的只有值不同),可以考虑引入机器学习的分类思想来识别(这里重点是识别是否是敏感数据而不提取敏感数据本身)。

这个功能大多数情况是供docx、PDF格式出现图片的情况下调用识别(这里不输出具体的敏感数据内容,只输出类型,如“包含身份证图片/银行卡图片”,主要是做一个分类区分)。

具体模型训练见模型训练说明。训练图片数据来源于互联网。

1
2
3
4
5
6
7
- **模型**: MobileNetV2(14MB)
- **方法**: 迁移学习 + 深度学习
- **准确率**: 通常在90%以上(取决于数据质量)
- **速度**: CPU 100ms/张,GPU 20ms/张
- **部署**: 支持Windows/Linux,Python 3.9+

通过将通用特征提取(MobileNetV2)和特定任务分类(身份证/银行卡)相结合,实现了在少量数据上的高效训练和准确识别。

文本识别

文本识别作为识别基础,提供给文件识别功能进行调用识别。在业务中,纯文本格式的数据如txt的类型比较少,更多可能是处于日志、聊天记录等中的文本。如某hr系统在操作中会生成日志包含身份证等敏感信息。这个模块主要是给json、csv确定某键/某列属于哪种敏感数据,以及docx、pdf等含有到非结构化表格/文本时调用识别提取敏感信息。在webui中保留这个功能,通过文本框输入文本然后识别输出敏感信息类型和敏感等级以及处置建议,以方便对少量的文本数据进行识别(与文件识别的分开入库,只有通过这个ui来识别的才单独记录)

敏感数据识别引擎

https://github.com/J-0k3r/JJDLP/tree/master/core

匹配互斥,即不可能同时识别为身份证和银行卡(数字类)、姓名和地址(中文类)

地址

对于太宽泛的地址,不具有现实意义,即无法定位到一个极小的范围。即至少到某个小区或者某路的xx号或者某村的xx号)并且至少包含x市x区x镇/路(同名市的情况很少并且有区佐证)。基于考虑正常业务不会存储无意义的地址,并且地址更多可能会出现在docx、pdf中,所以匹配到x省x市x区或者x市x区就算做敏感数据。

1
匹配“XX省XX市XX区…”或“XX市XX区…”型。进一步识别详细为:省市区+任意若干(大于一的汉字+1-6数字+大于一的汉字),如“建国路88号”、“中山大道21805”等。

姓名

匹配2-4个中文字符(要姓氏开头),姓氏列表可能不全,但可以遇到再加。少数民族可能名字更长(少数情况先不考虑)、公司内部区分同名可能会在名字后加数字,这里也不作考虑(因为业务中更可能是通过结构化数据格式存储的,同一列/键名都当作了是同一种敏感数据)。

身份证

判断输入是否身份证号,含长度、校验位。只考虑中国大陆18位身份证。

1
pattern = r'^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])\d{3}[\dXx]$'

身份证校验码(即中国居民身份证号码的第18位)是根据前17位数字,通过特定算法计算得出的,用于验证身份证号码的有效性。其计算过程遵循国家标准 GB 11643-1999

银行卡

判断是否为银行卡号(16、17或19位,纯数字,Luhn算法校验;18位直接排除)

电话号码

   只识别中国大陆11位手机号+常见号段,不匹配固话。

邮箱

xx@xx

1
email_pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b'

IP

 IPv4、IPv6

数据脱敏

https://github.com/J-0k3r/JJDLP/tree/master/core

分为文本脱敏和文件脱敏。文本就调用文本识别然后对结果脱敏然后渲染到页面,文件则对应文件结果脱敏然后写入文件供导出。

csv

  结构化类型的数据脱敏较容易实现,因为默认同一列下的数据是同一种敏感数据,对每一行的该列数据调用相同的该类型敏感数据的脱敏方法即可。然后提供导出功能来导出脱敏后的文件。

json

 结构化类型的数据脱敏规则同csv。

pdf/docx/图片

  非结构化的数据文件要整个自动脱敏并原格式输出比较困难。所以只根据相应的识别方法识别出来的文件里的的敏感数据然后对其进行脱敏,渲染到页面,并提供导出功能(导出的为该脱敏路由的返回值即json数据,格式为json文件)。

业务标记

对识别到的敏感文件标记其所属业务、部门、负责人、入库时间、处理建议、敏感等级、备注等。除了下拉预设选项外还可以自定义并添加到选项。

自定义敏感数据类型

https://github.com/J-0k3r/JJDLP/blob/master/core/custom_rules.py

 敏感数据这个定义其实很宽泛,具体到一个公司某个业务线的一份策划到这个公司的利润报告,都可以视为敏感数据。但一个共同的特性就是不希望暴露在外让所有人都能够看见的数据。

但人始终是敏感数据产生的主体,换句话说,不管是什么类型的公司、企业,都有人参与在里面。一个公司/企业最少会存有员工的个人信息(即使没有客户的个人信息)。所以初始提供的默认敏感信息大部分都是个人敏感信息,至少这一块是所有公司/企业都存在的敏感数据,而不至于让做的这个dlp毫无用处。

鉴于敏感数据种类繁多、参差不齐、标准不一。所以提供一个自定义敏感数据类型的接口来增强dlp的扩展性。

关于风险分数和风险等级

在对单个敏感数据类型给定敏感级别时(如姓名为低,身份证号为高)是基于该数据的唯一性强弱考量的,同名的人有很多但身份证号码是唯一的。单拿个人的敏感数据来说,基于敏感数据的现实意义考量,需要多种敏感数据类型组合才能真正具备敏感性(数据泄露后的潜在的危害程度)如:

姓名/住址+电话号码/邮箱=精准诈骗、钓鱼...

身份证号+银行卡号=信用卡恶意透支、金融欺诈、冒名贷款....

身份证图片(人脸)+地址=跟踪、骚扰...

身份证号+手机号+地址=身份冒充(注册公司、犯罪等)

传统按单一敏感数据字段定级存在局限。依据实际危害采用动态组合来计算风险分数并定风险等级。强调组合而非数量。比如某个csv存了1w条身份证号,另一个csv存了2w条手机号但这两个的风险分数会远小于500条的身份证+手机号的csv,因为身份证号和手机号需要对应组合才能确定为同一个人的敏感信息,而单独的两个csv不一定互相对应。

1
风险评估的风险分数的计算和风险等级的评定优化一下。分数上限是100(保留2位小数),分为5个风险等级(微、低、中、高、极高),xx分到xx分对应什么等级(不一定要100/5来平均分)。并且分数的计算要考虑包含敏感种类(种类越多,分数越高)的多少和数量(数量越多分数越高),但是组合的分数要远大于只含一种类型的(身份证图片/银行卡图片除外)如果只包含一种低敏感级别的(姓名、ip地址、地址)则视为无风险。但是包含姓名+地址的则至少是中风险等级(数量大的话可到高但不可能到极高)。ip地址跟任何一个其他类型组合都不当作是组合(如ip+手机号)只当作只有手机号。身份证图片/银行卡图片单独作为一个加分项(就是有的话就加分,但不和其他组合一起算分。比如身份证图片+手机号+姓名:算手机号+姓名的组合分,再加上身份证图片的分数)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1. 风险评估算法优化
分数上限:100分,保留2位小数
风险等级:5个等级
微:0
低:0.01-20
中:20.01-50
高:50.01-80
极高:80.01-100
2. 评分规则实现
种类影响:类型越多,组合加成越大(2种×2.53种×3.54种及以上×5.0
数量影响:使用对数函数计算数量加成
组合加成:组合分数远大于单种类型
特殊规则:
只包含一种低敏感类型(姓名、IP地址、地址)时视为无风险(0分)
姓名+地址至少中风险(≥20分),最高只能到高(≤80分),不能到极高
IP地址不参与组合计算(如IP+手机号只按手机号计算)
图片加分:身份证图片/银行卡图片每个+15分,单独计算,不参与组合

DLP数据泄露防护系统设计
http://example.com/2025/11/25/DLP数据泄露防护系统设计/
作者
J_0k3r
发布于
2025年11月25日
许可协议
BY J_0K3R