防御性安全研究,测试一个仅具备注入能力的低权限数据库角色能否在原生 PostgreSQL 上可逆地致盲基于触发器的审计器并污染归因——以及哪些防御措施能真正阻止它。一切都在一次性、本地 Docker 容器中运行,使用完全合成的数据(RFC 5737 文档 IP、虚构身份)。不涉及任何真实系统、凭据或数据。
参见 self-defeating-audits-lab.md 中的实验室简报。
构建被广泛复制的 PostgreSQL wiki“审计触发器”受害者,然后在 PostgreSQL 14 和 16 上逐格推演可行性矩阵,带外测量每个攻击向量是否真正阻止写入被审计、是否可零残留地逆转,以及哪些防御措施能消灭它。
cd scripts
./00_up.sh 16 # bring up postgres:16-alpine on localhost:55432
./run_matrix.sh 16 # run every matrix cell + defenses -> ../results/RESULTS_pg16.md
docker rm -f sda_pg16 # free the port between versions
./00_up.sh 14
./run_matrix.sh 14 # -> ../results/RESULTS_pg14.md
./teardown.sh # remove all lab containers
需要 Docker。使用 -alpine 镜像(功能上相同的引擎)。
该研究还在另外两个引擎家族上复现。MySQL 家族(MariaDB,DEFINER 触发器模型)位于 scripts/mysql/ 下:
cd scripts/mysql
./00_up.sh 10.11 && ./run_matrix_mysql.sh 10.11 # -> results/RESULTS_mariadb_10.11.md
docker rm -f sda_maria_10_11 && ./00_up.sh 10.6 && ./run_matrix_mysql.sh 10.6
SQL Server(所有权链模型)位于 scripts/mssql/ 下——通过宿主机 sqlcmd 在本地 LocalDB 实例上运行(无需 Docker;低权限攻击者通过 EXECUTE AS USER 模拟进行建模):
cd scripts/mssql
./run_matrix_mssql.sh # -> results/RESULTS_mssql.md ; then ./teardown.sh
可复现性注意事项(SQL Server)。 与 Docker 引擎不同,SQL Server 这一支具有宿主机依赖:它通过
sqlcmd在本地 SQL Server LocalDB 实例上运行(路径硬编码在run_matrix_mssql.sh中),因此仅限 Windows,且无法固定到镜像摘要。低权限攻击者通过EXECUTE AS USER模拟进行建模(LocalDB 仅支持 Windows 认证)。引擎行为结论(DISABLE 零残留;DDL 防护遗漏 DISABLE)与会话类型无关,对真实登录同样成立;对象授权结论则通过模拟得到忠实验证。它是三个引擎中可移植性最差的——如实说明。
跨引擎核心结果:search_path 影子攻击类(1A/1B)既不能迁移到 MySQL,也不能迁移到 SQL Server(没有 search_path),但触发器替换、休眠绕过和归因污染可以。MySQL 的 DEFINER 权限绑定使致盲更易被检测;SQL Server 与 PostgreSQL 一样允许字节级完美还原,并增加了一个其自身 DDL 防护遗漏的零残留 DISABLE TRIGGER 原语。完整的三种引擎对比见 FINDINGS.md。
| 路径 | 说明 |
|---|---|
scripts/00_up.sh | 固定版本的临时容器(PostgreSQL) |
scripts/mysql/ | MySQL 家族(MariaDB)受害者、攻击、防御与编排器 |
scripts/mssql/ | SQL Server(LocalDB)受害者、攻击、防御与编排器 |
results/RESULTS_mariadb_*.md | MySQL 家族可行性 + 防御矩阵 |
results/RESULTS_mssql.md | SQL Server 可行性 + 防御矩阵 |
scripts/10_victim.sql | wiki 模式的审计受害者(SECURITY DEFINER 触发器);开关:pub_create、pin_path、app_owns |
scripts/20_attacks.sql | 所有攻击向量(1A/1B/1C、GUC 休眠、归因污染),每个单元格一个 \if 守卫 |
scripts/30_defenses.sql | DDL 事件触发器守卫 + 哈希链式仅追加 sink |
scripts/40_snapshot.sql | 用于 RQ2 对象差异比对的数据目录快照 |
scripts/run_matrix.sh | 编排器:构建每个单元格、测量并写入 results/RESULTS_pg<VER>.md |
scripts/teardown.sh | 移除容器 |
results/RESULTS_pg14.md, results/RESULTS_pg16.md | 各版本已填写的可行性 + 防御矩阵 |
results/_evidence_pg*.log, results/_snap_1C_*.txt | 原始命令/输出证据 |
FINDINGS.md | 通俗英语的 RQ1–RQ5 结论、防御×攻击矩阵、新颖性定位、摘要 |
CREATE SCHEMA),并非因为“pg_catalog 优先”。植入到本就可写的 public 确实能实现影子化:1S(同签名、schema 排序)和 1T(精确重载击败内置函数——即使 pg_catalog 排在第一位——隔离了类型特异性)都能致盲(有效载荷被置空)。row_to_json 重载——当 public 可写且触发器 search_path 未固定时,致盲审计器。在原生 PostgreSQL ≤14 上可达;15+ 上受错误配置限制。 固定 search_path 可在任何地方击败它。pgaudit/log_statement)+ 哈希链 sink 是能封堵整个攻击集合的防御措施。在本地实验室的原生 PostgreSQL 上使用匿名化/合成数据进行复现。攻击 SQL 仅限于此处构建的实验室 schema;这是一项可行性/防御研究,而非武器化载荷。底层原语已公开(CVE-2018-1058;SECURITY DEFINER search_path 提权)——贡献在于组合方式与防御评估。未涉及任何真实系统。