从 Web 应用中提取数据库访问控制策略(OSDI 2026)

原题:Extracting Database Access-Control Policies From Web Applications

一句话总结:Ote 假设 Rails 应用中真正决定 SQL 查询的代码核心主要由简单条件和数据流组成,用带界的 concolic execution 记录查询及其路径条件,再用 SQL 视图合并、化简和裁剪生成可审计策略;在 diaspora、Autolab 和 Odin 上最多约 5 小时完成提取,并发现手写策略中的过宽、过窄授权以及一个被外部库配置静默禁用的访问检查。

问题与动机

Web 应用通常没有一份独立的数据库访问策略。授权逻辑分散在控制器、模型、模板和多个查询过滤条件中。缺少检查或过滤条件写错,可能直接暴露敏感数据;即使没有漏洞,维护者也很难从不断演化的代码中恢复“应用实际上能读什么”。

已有显式策略框架要求应用重写为特定编程模型,难以覆盖遗留 Rails 应用。Ote 选择反向提取:先观察应用在不同数据库状态、会话参数和请求参数下发出的查询,再把“查询在什么条件下被发出”整理成 SQL view-based policy。人需要审阅这个策略,决定它是否符合隐私要求;确认后还可以交给 Blockaid 一类执行器,约束后续代码变更。

论文的目标不是给出完整性和紧致性的形式保证。作者把输出定义为三个理想目标:允许应用可能发出的全部查询、尽量少暴露信息、并保持 SQL 表示可读。Ote 的实际结果依赖输入空间边界、支持的 SQL 子集、人工提供的数据库约束,以及 LLM relevance judge 的判断。

关键观察 / 隐含假设

  • 观察 1:查询发出核心通常比完整 Web 应用简单。 作者对三个应用的分析认为,影响查询发出的代码主要是查询结果是否为空、基本值比较、遍历查询结果以及把前一个查询的值传给后一个查询;模板渲染、日志和 HTML 格式化通常不在这个核心中(§4.1)。
    • 依赖假设:查询使用参数化 SQL,且查询相关表达式主要由 Ote 已插桩的简单操作构成。
    • 可能失效场景:正则校验、字符串拼接、复杂数值运算或外部库逻辑决定查询时,符号值可能被具体化,导致遗漏查询或生成过宽、过窄的策略。
  • 观察 2:不相关分支造成的路径爆炸是实际瓶颈。 五个 handler 在不剪枝时超过 10 小时仍未完成,论文估计可能需要数天;很多分支只影响页面展示,不影响数据访问(§4.6、§7.4)。
    • 依赖假设:LLM coding agent 能根据条件位置和源代码判断某分支是否影响查询或状态。
    • 可能失效场景:动态 Rails 元编程、外部库副作用或缺少上下文会使 judge 把相关分支判为无关。Ote 将 unsure 和格式错误按 relevant 处理,并要求人工复核。
  • 假设 1:可以用有限数据库模型代表足够多的应用状态。 原型默认每张表最多 2 行、每个查询最多返回 1 行,并由用户提供唯一性和包含关系等约束(§4.4)。
    • 证据强度:中。三个应用上输出有用,但该边界无法保证覆盖真实多行循环、排序和数据规模相关行为。
  • 假设 2:PSJ view 足以表达目标应用的访问策略。 Ote 的策略语言支持 project-select-join 查询,复杂 SQL 只能近似处理;否定条件、一般聚合和部分 outer join 尚未完整支持(§3.2、§7.3)。
    • 证据强度:中。评测中的应用能被处理,但论文明确报告了需要重写或丢弃部分语义的查询。

核心方法

Ote 的输入是 Rails handler、应用数据库约束和 Docker 化应用。驱动器用带界的 concolic execution 运行 handler:输入同时有具体值和符号表达式,分支条件被记录,SMT solver 通过否定已走过的条件生成新输入。执行器在修改过的 JRuby 和 Rails 数据层上运行,每次执行输出查询记录、分支记录以及可回溯的 stack trace(§§4.3–4.5)。

Ote 只在可能属于查询发出核心的操作上维护符号状态。记录 QUERY 时保存 SQL、参数和结果是否为空;记录 BRANCH 时保存条件及实际走过的方向。通过把前序查询结果表示为符号行,后续查询可以引用例如 r1.course_id 这样的数据流。数据库约束同时用于限制有效状态和简化路径条件。

为缓解路径爆炸,Ote 异步调用基于 Codex CLI 的 relevance judge。judge 查看分支和对应 stack trace,回答 relevant、irrelevant 或 unsure。驱动器跳过不相关分支的否定,不再探索已覆盖的相关条件序列;judge 的结果和解释保留下来供审计。人工可以用 RELEVANCE-HINT 注释纠正 Rails 或外部库语义。

每条查询轨迹先被转换为 conditioned query:一个 SQL 查询及其发出所需的前序查询、分支条件。Ote 删除必然成立或未被后续使用的条件,传播等式,合并只在单个分支方向上不同的记录,并移除被更宽条件 subsume 的记录(§5.2)。随后,它把条件逐项 conjoin 到关系代数表达式中,生成 SQL view;请求参数不能出现在最终策略中,因此会依据列约束消除这类参数(§5.3)。

最后,Ote 使用扩展后的 Blockaid 检查一个 view 是否已被其余 view 包含,分别做 handler 内和跨 handler 的裁剪。用户也可以先添加更宽但不涉及隐私的 view,再让裁剪器删除冗余的窄 view。这个步骤把“哪些条件只是业务逻辑、哪些条件是隐私边界”的判断留给人,同时避免手工推导 view subsumption。

设计取舍

  • 带界的 concolic execution 对动态语言更实用,但牺牲覆盖保证。 修改 JRuby 可透明追踪 Rails 执行,代价是只支持 Rails 和有限的符号操作;输入行数、返回行数和数据库约束决定了探索边界。
  • LLM judge 换取可扩展剪枝,但引入新的审计面。 不相关分支的静态识别在 Ruby/Rails 中很难,LLM 能处理动态代码上下文;但其 verdict 没有形式保证,而且每次调用可能耗时数分钟。论文人工检查了所有 irrelevant verdict,并将 unsure 视为 relevant。
  • PSJ view 提高可读性和裁剪效率,但会损失复杂 SQL 语义。 LEFT JOIN、COUNT、时间戳比较等在评测中被重写、拆分或近似。输出策略因此可能比真实行为更宽或更窄,必须由熟悉 SQL 和应用的人员复核。
  • 策略默认偏紧,减少漏授权风险,但增加审阅负担。 Ote 保留业务条件,生成的 view 通常多于手写策略。对于 profile 这类本来应公开的数据,用户需要显式添加更宽 view 才能压缩结果。

实验与结果

  • 在 diaspora(超过 850k 用户、50 张表)、Autolab(26 张表)和 Odin(17 张表)三个真实 Rails 应用上评测;实验使用 Google Compute Engine c3-standard-176、48 个并行 executor、Z3 4.11.2 和修改后的 JRuby(§§7.1–7.2)。
  • 端到端提取最多约 5 小时;启用 relevance-based pruning 后,原本超过 10 小时未完成的 handler 得以完成(§7.4)。
  • 最终策略规模被压到每个应用约 24–144 个 SQL views,达到可供人工审阅的数量级(§7.3)。具体 view 数量随 handler 和裁剪阶段变化,表 2 给出了完整矩阵。
  • relevance judge 产生了 600 多个 irrelevant verdict;论文逐一人工复核,且这些 verdict 集中在有限的代码位置。Odin 分支较少,没有启用该优化(§7.5)。
  • 与既有手写策略比较时,Ote 找到 Autolab 中把 disabled course 的五类记录错误开放给 course assistant 的过宽授权,也找到手写策略遗漏的 diaspora remote person、通知数据以及 Autolab 课程附件等过窄授权(§7.6)。
  • 审阅 Autolab 输出时,作者发现所有 submission view 都没有检查 assessments.exam。追踪后确认 lazy_column 被错误配置为 exam? 而非列名 exam,使检查方法总是返回 falsy,静默禁用了访问检查(§7.6)。
  • 在 diaspora 中加入 4 个更宽的 profile views 后,裁剪器删除了 39 个 profile-related views 中的 36 个,说明人工负责隐私语义、工具负责包含关系化简的分工有效(§7.7)。

论断—证据表

论断证据评测边界置信度
Ote 能在真实 Rails 应用上提取可审阅的策略三个应用的抽取结果和最终 view 数量(§§7.1、7.3,表 2)Rails;每表至多 2 个符号行;每查询至多 1 行;PSJ 近似
relevance judge 对可扩展性很重要启用剪枝后最多约 5 小时完成;禁用时部分 handler 超过 10 小时(§7.4)仅对长路径 handler 启用;gpt-5/Codex CLI;人工复核 verdict
提取策略能暴露手写策略和代码中的授权错误Autolab、diaspora 的过宽/过窄策略差异及 exam? 配置 bug(§7.6)两个应用有既有手写策略;结果依赖人工审阅
输出策略可以被进一步压缩而保留相同信息profile 场景加入 4 个宽 view 后删除 36/39 个相关 view(§7.7)依赖用户理解“哪些业务条件不是隐私条件”
Ote 不保证完整和紧致有界路径探索、未插桩操作、LLM 判断错误和 PSJ 近似(§3.2、§4.7)论文给出设计级限制,未提供形式覆盖率

批判性分析

论证链条

论文的主链条基本闭合:作者先测量查询相关代码的结构和路径爆炸,再用选择性符号追踪减少实现范围,用 relevance judge 缩小路径空间,最后把轨迹转换成可审计的 view。三个应用中的策略差异确实能定位手写策略和应用代码错误。

但“提取的策略比手写策略更准确”不能理解为无条件结论。Ote 的输出是应用在有限模型和有限路径上的观察结果。复杂条件可能被漏掉,SQL 近似可能改变信息含义,judge 也可能漏判。论文展示了实用价值,没有证明输出覆盖全部可发出的查询。

假设压力测试

最脆弱的假设是简单查询发出核心。Rails 应用若在查询参数、URL 校验、权限判断或模型回调中使用未插桩字符串和算术操作,Ote 可能看不到真实依赖。论文通过把 URL 固定为合法值、改写非参数化查询来绕开部分问题,但这些改动也说明工具需要应用专家配合。

“每个查询至多返回一行”适合许多 lookup,但会压低对列表页、批量关系和循环查询的覆盖。论文的 view 生成算法可以表达前序查询结果的组合,但实验输入边界仍限制了它看到的组合数量。生产数据库中多行结果、排序稳定性和数据规模触发的分支需要单独测量。

LLM judge 的错误不会只影响性能:若相关分支被判为 irrelevant,最终策略可能丢失访问条件。作者通过人工复核和保守的 unsure 规则降低风险,但没有报告独立审阅者之间的一致性、误判率或 judge 版本变化下的稳定性。

实验可信度

应用选择覆盖社交网络、课程平台和教学社区,且包含此前已有手写策略的对照,适合验证“能否帮助审计”。性能实验也明确报告了并行度、solver、LLM 模型和执行时间。缺口在于样本仍只有三个 Rails 应用,且应用被做过兼容性修改;论文没有在更多框架、复杂 SQL 或真实生产 trace 上验证泛化性。

策略正确性主要靠作者人工检查和与手写策略比较。手写策略本身并非金标准,作者发现的差异需要结合应用意图判断。论文没有给出完整的独立 ground truth、系统化漏查询率或对所有生成 view 的形式等价验证。因此,结果充分支持“辅助审计有用”,不足以支持“策略自动正确”。

系统性缺陷

  • 人工成本仍然存在:用户要提供数据库约束、写 relevance hints、判断 SQL 近似是否安全、审阅策略并决定是否 broadening。论文明确说这些步骤需要 Rails、SQL 和应用领域知识(§7.8)。
  • 部署耦合较强:当前实现绑定修改过的 JRuby、Rails 和 MySQL;缓存被关闭,查询在 tmpfs 上运行。论文未评估这些设置对真实延迟、缓存相关访问路径和运维成本的影响。
  • 安全风险可能转移到审阅流程:策略看起来合理可能造成 automation bias。论文在 §9 提出这个风险,但没有实验验证审阅者是否会过度信任输出。
  • 策略可读性是瓶颈:几十到上百个 view 仍可能难以由人理解,尤其当条件来自业务逻辑而非隐私边界。SQL DSL 和策略可视化是合理的后续方向,但当前系统没有提供。
  • LLM 依赖的可复现性有限:judge 使用 Codex CLI、gpt-5 和超时重试。论文记录了 verdict,但没有把 judge 替换成确定性分析器,也没有评估模型更新对路径集合的影响。

局限与后续工作

  • 局限 1:策略语言和查询支持不完整。 PSJ 无法自然表达否定条件,复杂 join、aggregation、ordering 和字符串操作需要近似或暂不支持。后续应在带完整 SQL 语义的基准上测量近似导致的过宽/过窄比例。
  • 局限 2:输入空间边界限制覆盖。 每表 2 行和每查询 1 行便于终止,但不适合系统性验证多行循环。可以构造逐步增加行数的实验,观察新增路径和 view 是否收敛。
  • 局限 3:相关性判断依赖 LLM。 应比较 LLM judge、静态切片和人工标注在误判率、成本、总提取时间上的差异,并对模型升级做回归测试。
  • 局限 4:跨框架泛化尚未验证。 论文认为方法可推广到其他语言,但当前实现只支持 Rails。下一步应在至少一种 Python 或 JavaScript ORM 上复现“查询发出核心”假设。
  • 局限 5:人机审阅界面不足。 需要把 view、生成它的 transcript、输入、源码 stack trace 和相关 judge verdict 联动展示,并测量审阅者找 bug 的时间和误报率。

相关