📡 Taylor Wessing数据泄露工具包
通用取证审计与图层分解套件,用于揭露并识别Taylor Wessing LLP与Valve Corporation所进行的仅视觉性PDF编辑。
🔍 执行摘要
该。 通用PDF脱密审计器与图层分解工具 是一款专业的、离线优先的取证审计与图层分解套件,专为识别、验证和清理纯视觉PDF脱敏漏洞而设计。该工具包作为开源实用程序,供安全研究人员、数据保护官及合规审计员在公开披露前验证文档结构完整性。
⚖️ 技术力量不对称
此审计工具旨在解决企业数据处理中一个关键性的权力失衡问题。当大型企业集团(例如 Valve公司) 由精英律师事务所(如 泰勒·韦辛律师事务所),任何系统性的数据泄露都不会损害公司或其高薪律师的利益——却会灾难性地侵犯其 对手 (因法律与技术疏忽而导致敏感个人数据泄露的个体数据主体、第三方用户及未成年人)。该工具包使个人和独立审计人员能够验证数据安全性,并追究企业行为者的责任。
📊 案例研究:Taylor Wessing / Valve GDPR 泄露事件
在处理关于Steam用户数据的GDPR第15条主体访问请求(SARs)过程中,外部法律顾问处理并发送的文件里发现了一个严重的安全漏洞。 泰勒·韦辛律师事务所 代表 Valve公司.
技术故障分析
与其永久性地清理PDF内容流内部的原始字符数组,不如采用一种自动化的定制PDF生成流水线(利用 Aspose.PDF for .NET已部署。该系统以编程方式查询了敏感字段的坐标并绘制了 纯黑色矢量形状 (使用PDF的 re 并且 f/F/b/B 运算符)叠加在文本之上。
由于视觉绘制图层不会修改或破坏底层原始文本数组,数千条未脱敏的私人记录——包括账户凭据、登录信息、电子邮件、安全日志以及未成年人去匿名化数据——在已发送的文件中依然完整保留,可被复制和提取。
📂 附件A:与帕特里克·楚海德博士的泄露通信
以下是收到的确切回复: 帕特里克·楚尔海德博士 (Taylor Wessing LLP律师事务所薪资合伙人)在PhishDestroy正式通知该律所其PDF编辑失败及随后Steam用户数据泄露事件后,他并未启动GDPR第33条违约通知程序,而是选择了写下这段话:
您好,PhishDestroy 团队,
感谢您发来这条看似经过翻译、但确实颇具趣味性的消息。请问您指的是与PhishDestroy团队之间哪次涉及“刑事追诉”的沟通?我确信自己此前从未以任何形式与PhishDestroy进行过交流。因此,请提供您所称的那次沟通内容,以便我了解究竟是怎么回事。
很遗憾,您的来信在内容上很难甚至无法理解。作为提示:如果实际行为与您信中所附的免责声明相悖,那么该声明——声称某些行为并未实施或并非有意为之——便毫无意义。
帕特里克·祖尔海德
🔍 PhishDestroy 分析:
- "有趣的留言"(娱乐性消息): 一位高薪的“IT法律专家”将涉及未成年人Steam账户泄露的重大GDPR数据泄露取证通知称为“有趣”。
- “schwer bis gar nicht zu folgen”(完全无法理解) 我们向他提供了精确的十六进制值、其PDF的元数据、36秒批处理流水线的时间戳,以及具体的 Aspose 20.8 导致泄露的版本。显然,对于一位IT法律博士来说,IT指标太难“跟进”了。
🛠️ 多工具能力
该套件提供三种互补的、完全客户端运行的模式,用于分析和破解虚假的视觉脱敏处理:
- 📡 模式1:X射线扫描器(PDF.js): 实时渲染PDF的可视化显示,但同步提取底层未脱敏的文本字符。你看到的是黑色遮罩,却能即刻读出其中的秘密。
- ✂️ 模式2:图层剥离器(PDF-Lib): 外科级流层清理。物理替换矩形视觉绘制命令
re f,re F) 与n(no-paint) 操作符,删除黑色条带。 - 🔎 模式3:碰撞审计(Fitz布局): 高亮重叠的文本和图形,以自动生成汇编的泄露列表。
💻 命令行用法(decensor.py)
# 1. Decompose PDF to raw text layers (Strips all drawings, lines, and masks globally)
python decensor.py -i compromised.pdf -d -o naked_document.pdf
# 2. Extract and save all text hidden under black visual shapes to a leaks text report
python decensor.py -i compromised.pdf -e verified_leaks.txt
# 3. List page-by-page structural element counts
python decensor.py -i compromised.pdf -l
🔍 核心Python流净化器
import re, fitz
def strip_black_bars_global(input_path, output_path):
doc = fitz.open(input_path)
for xref in range(1, doc.xref_length()):
if not doc.is_stream(xref):
continue
try:
obj_dict = doc.xref_object(xref)
if any(m in obj_dict for m in ["/Type /Font", "/Subtype /Image", "/Type /Halftone"]):
continue
stream_bytes = doc.xref_stream(xref)
text = stream_bytes.decode('latin-1')
# Swap rectangular painting operators with no-fill 're n', preserving newlines
modified_text, count = re.subn(
r'\bre\s+([fFbB]\*?)(?=\s|$)',
lambda m: f"re{m.group(0)[2:-len(m.group(1))]}n",
text
)
if count > 0:
doc.update_stream(xref, modified_text.encode('latin-1'))
except Exception:
continue
doc.save(output_path, garbage=4, deflate=True, clean=True)
doc.close()
