本文将概述几篇云上形式化验证的论文,其中大部分源于 amazon.science 里的 Automated Reasoning 分类。

本文关注的重点方向包括:

英语术语 中文术语 含义
Policy 策略 用于形式化表达一组 IAM 授权,是由 Statement 构成的一个数组
Statement 语句 构成策略数组的元素,包含 Effect, Action, Conditon, Resource 等维度
Effect 效果 Allow 和 Deny 二选一,表示本条 Statement 是授权语义和拒绝语义
Action 权限 表示本条 Statement 关联的授权或拒绝的权限点
Resource 资源 表示本条 Statement 关联的授权或拒绝的资源
Condition 条件 表示本条 Statement 关联的授权或拒绝的条件;AWS 提供丰富了的条件键
Match 命中/匹配 表示一组请求是否同时满足本条 StatementAction, ResourceCondition

AWS 策略的总体规则:当一组真实请求命中至少一条 Allow 语句且没有命中任何 Deny 语句则鉴权通过。

会议或期刊名 CCF 评级
Computer Aided Verification A
Conference on Object-Oriented Programming Systems, Languages, and Applications A
Usenix Security Symposium A
Theory and Applications of Satisfiability Testing B
Formal Methods in Computer-Aided Design C

IP Counting in Public Access

FMCAD 2024, AWS, Loris D’Antoni: Projective model counting for IP addresses in access control policies

简介:Zelkova 想根据“授权的 IP 数量是否超过特定阈值”来判断策略是否是 Public Access。论文基于 bounded projective IP-counting problem 提出了两种编码方式,使得 99.999% 的策略都能在 3s 内出解。

IP 等价类:一个很自然的想法。由于策略里每条针对 IP 的 Condition 一定是 CIDR 格式,且真实场景里用户策略不会太长,可以借助离散化的思想,把 2322^{32} 个 IP 位向量(这里只考虑 IPv4)划分成一个个连续段。

基础编码方式:设 IP 的等价类是 S1,S2,,SnS_1,S_2,\dots,S_n,各自的大小为 Si|S_i|。再设 sis_iSiS_i 的代表元(siSis_i \in S_i)。用 φp(x,ip)\varphi_p(\mathbf{x},ip) 表示策略 pp 在一个特定 IP 取值下的构成的约束关系。构造一个计数器 counter,依次枚举每一个等价类 SiS_i,将约束 φp(x,ip=si)\varphi_p(\mathbf{x},ip=s_i) 代入 SMT 求解器,若有解则 counter 累加 Si|S_i|,观察其是否超过 threshold。

方式一:Arithmetic Approach。论文认为同时支持 arithmetic 和 string 理论的 SMT 求解器(如 CVC5, Z3 等主流求解器)经过如下一次编码和求解即可完成阈值判断。我认为这 nn 个场景需要单独求解才能确保正确性,没有完全理解这种编码方式。难道论文是通过将每一个 φp(x)\varphi_p(\mathbf{x}) 里的所有变量都复制一份来做到互不干扰?

(i=1n{Siif  x. φp(x,ip)0otherwise)thresold\left(\sum_{i=1}^n \begin{cases} |S_i| \quad &\text{if }~\exists \mathbf{x}.~\varphi_p(\mathbf{x},ip) \\ 0 &\text{otherwise} \end{cases}\right) \ge \text{thresold}

方式二:Arithmetic-free Approach。对于不支持 arithmetic 的求解器(如 AWS 自研的 NFA2SAT),论文先用背包找到所有 IP 等价类的极小集 {T1,T2,,Tm}\{T_1,T_2,\dots,T_m\},即 ijTi⊈Tj\forall_{i\ne j} T_i \not \subseteq T_ji(SjTiSj)thresold\forall_i (\sum _{S_j \in T_i} |S_j|) \ge \text{thresold}。再将这些极小集按前一种方式构建约束即可,这样就规避了所有涉及 arithmetic 的操作。

SMT-D

FMCAD 2024, AWS, Clark Barrett: SMT-D: New Strategies for Portfolio-Based SMT Solving:

简介

论文提出了名为 SMT-D 的基于 CVC5 实例的 Portfolio 框架,主打基于 Clause Sharing 的规则分享机制,叠加上 Delayed SharingGuided Randomization 两种特性,总体效果好于基于 OPENSMT2 实例的 SMTS。

  • SMTS 同时支持 Clause SharingPartition 机制,本论文做 SMTS 实验时没有开启 Partition 的开关。
  • CVC5-P 仅支持 Partition 机制,本论文做 CVC5-P 实验时默认保持了这一机制。
  • 从第二张图单实例对比中可以看出 OPENSMT2 好于 CVC5,但加了 64 节点的分享后 SMT-D 超过了 SMTS。

术语 解释
Delayed Sharing 强制要求每个求解器在 preprocessing 阶段后才能分享 lemma
Guided Randomization 观察到随着集群规模的增大,配置各异的求解器能唯一学到的规则数量趋于饱和。将集群分成 normal 和 noisy 两块,后者拥有更激进的参数配置且只导入导出更短的 lemma
CS / CS-GR 仅带有 Clause Sharing / 同时带有 Clause SharingGuided Randomization
PAR-2 SAT 竞赛的计分方式,统计所有实例的用时之和,超时( >1200s>1200s) 有双倍惩罚。
SMT-D 当前混合求解器框架的 SOTA(SMT COMP 22 Cloud Track)

框架

论文抽象了中心化的 Controller 负责信息交换和监控,底下每个 Worker 能互相分享学到的新规则(lemma)。

  • Controller 用 python 实现 ,gRPC 通信(便于跨场景),交互格式选用宽松但是直观的 SMTLIB。
  • Controller 用 “上一次发送至今的间隔” 和 “待发送的 lemma 队列长度” 两个维度来决定 shouldSend 函数。实测发现即收即发的效果不错,因为使用的 CVC5 每秒钟支持导入超过 10001000lemma,即使是 64 实例的求解器集群,在 lemma8|lemma| \le 8 的筛选规则下只有 1/2141/214 个测试数据会达到瓶颈。
  • lemma 里的子句数量来衡量价值。每个求解器不会分享包含新变量的 lemma
  • normal 集群和 noisy 集群数量各占 (75%,25%)(75\%,25\%),CVC5 用来控制随机性地 rnd_freq 参数,前者默认后者开到 75%75\%。前者的导入导出阈值是 8\le 8,后者的导入阈值 =1=1 导出阈值 4\le 4

NFA2SAT with Concatenation

FMCAD 2024, AWS, Kevin Lotz: Solving String Constraints with Concatenation Using SAT

Reduce Privilege for Policy

OOPSLA 2024, AWS, Loris D’Antoni: Automatically reducing privilege for access control policies

简介

本文专注于 AWS 策略生成场景,即给出原始策略和一些已通过的请求集合,IAM-PolicyRefiner 会生成一个满足最小化权限的新策略 。本论文提出了三个评价维度,最大的特色是将 Readability 这个感性的维度给量化。

维度 粗略解释
Readability 策略的可读性,即让新策略在字面量尽可能的和原来保持接近。
Soundness 策略的合理性,即能让已通过的请求仍然保持正确授权。
Tightness 策略的紧密性,即满足前两个条件下授权语义越小越好。

IAM-PolicyRefiner 的整体流程是:读取 AWS Cloud Trail 里所有鉴权通过的请求,找到每个请求对应的授权策略里第一条匹配的语句,计算该语句 ss 的搜索空间 Ss\mathcal{S}_s。这些搜索空间的并集即构成了所有 Readability 的策略集。整个 IAM-PolicyRefiner 用 3000\sim 3000 行 Scala 实现,利用其 map 和 reduce 做到并行,结果如下:

Abstraction 和 Well-Behaved 的定义

为了方便阐述论文的推理细节,本文约定以下记号:

符号 概念
M(s)M(s) 语句 ss 能匹配的请求(Request) 集合
ee 表示一条语句的效果是 Allow 还是 Deny
Ψ:Vpred\Psi:V \to \text{pred} 表示一条语句的具体约束,将所有变量映射成断言
CC 待匹配的请求(Request)的总集
AA 所有尝试去匹配这些请求的策略全集
Σ,σ,Σ\Sigma,\sigma,\Sigma^* 单个字符的集合,不含通配符的字符串,不含通配符的字符串总集
pat,L(pat)pat,\mathcal{L}(pat) 正则约束,正则约束匹配的所有不含通配符的字符串集合
Ω(σ,pat)\Omega(\sigma,pat) σ\sigma 匹配 patpat 的所有情况构成的数组,每个元素是不同正则项对应的元组

下面在策略集合 AA 上考虑一种偏序关系 \sqsubseteq

符号 概念
(A,)(A,\sqsubseteq) ab,(a,b)Aa \sqsubseteq b,(a,b) \in A 表示 aa 命中的请求集合完全包含于 bb 命中的请求集合
(A,)(A, \sqcup) m=ab,(a,b,m)Am=a \sqcup b,(a,b,m) \in A 表示 aabbAA 中的满足唯一性的封闭并运算,即 aw,bwa \sqsubseteq w, b \sqsubseteq wwA,awbwmw\forall w \in A, a \sqsubseteq w \land b \sqsubseteq w \to m \sqsubseteq w
\bot AA 中基于 \sqsubseteq 的最小元,可以理解成授权为空的策略,即 aA,A\forall a \in A, \bot \sqsubseteq A
γ(A2C)\gamma(A \mapsto 2^C) 将一条策略 aa 映射到它能匹配的请求集合
β(CA)\beta(C \mapsto A) 能匹配某一条请求 cc 的基于 \sqsubseteq 的最小 Policy aa。也就是说 $\nexists b \in A, c \in \gamma(b), a \sqsubset b $

将一组满足上述全部性质的 Abstraction A=(C,A,,β,γ,,)\mathcal{A}=(C,A,\sqsubseteq,\beta,\gamma,\sqcup,\bot) 称为 Well-behaved。此时 DC\forall D \subseteq C,存在能匹配上的唯一最小元 aAa \in A,即 Dγ(a)D \subseteq \gamma(a)bA,Dγ(b)ba\forall_{b \in A,D \subseteq \gamma(b) } b \subseteq a。而且 aa 可以按如下规则构造:

a=dDβ(d)a=\bigsqcup_{d \in D}\beta(d)

策略的搜索空间和 Abstraction 构造

Predicate Search Space Φψ[v]\Phi_{\psi[v]}:对于变量 vv 和原始约束 Ψ[v]\Psi[v],根据不同约束类型定义对应搜索空间的集合。

Statement Search Space Ss\mathcal{S}_s:相比原始语句 s=(e,Ψ)s=(e,\Psi),所有变量都在其 Predicate Search Space 里取值。

(e,Ψ)Ss    V(Ψs)=V(Ψ)vV(Ψ)Ψ[v]ΦΨ[v](e,\Psi') \in \mathcal{S}_s \iff V(\Psi_s)=V(\Psi') \bigwedge \forall_{v \in V(\Psi)} \Psi'[v] \in \Phi_{\Psi[v]}

Policy Search Space Pp\mathcal{P}_p:所有 deny 语句保持不变,所有 allow 语句在其 Statement Search Space 里取值。

若语句 s=(e,Ψ)s=(e,\Psi) 所有约束 ψpred(s)\psi \in pred(s) 构成的 Aψ=(val(ψ),Φψ,,βψ,γψ,ψ,)\mathcal{A_\psi}=(val(\psi),\Phi_\psi,\to,\beta_{\psi},\gamma_{\psi},\sqcup_{\psi},\bot)Well-behaved 的,则针对 Ss\mathcal{S}_s 构造出的如下 Abstraction As=(M(s),Ss,s,βs,γs,s,)\mathcal{A}_{\mathcal{s}}=(M(s), \mathcal{S}_s,\sqsubseteq_{\mathcal{s}},\beta_{\mathcal{s}},\gamma_{\mathcal{s}},\sqcup_{\mathcal{s}},\bot)Well-behaved 的:

asb    {M(a)M(b)if e=allowM(b)M(a)if e=denyβs(r)=(e,Ψ)Sss.t.V(Ψ)=V(Ψ)  vV(Ψ)Ψ[v]=βΨ[v](r(v))γs(e,Ψ)=M(Ψ)(e,Ψ1)s(e,Ψ2)=(e,Ψ)s.t.vV(Ψ)Ψ[v]=Ψ1[v]Ψ[v]Ψ2[v]\begin{aligned} a \sqsubseteq_{\mathcal{s}}& b \iff \begin{cases} M(a) \subseteq M(b) & \text{if } e=allow \\ M(b) \subseteq M(a) & \text{if } e=deny \\ \end{cases} \\ \beta_{\mathcal{s}}(r)&=(e,\Psi') \in \mathcal{S}_s \quad \text{s.t.} \quad V(\Psi)=V(\Psi') ~\land~ \forall_{v \in V(\Psi)} \Psi'[v]=\beta_{\Psi[v]}(r(v)) \\ \gamma_{\mathcal{s}}(e,\Psi')&=M(\Psi') \\ (e,\Psi_1) \sqcup_{\mathcal{s}}(e,\Psi_2)&=(e,\Psi')\quad \text{s.t.} \quad \forall_{v \in V(\Psi)} \Psi'[v]=\Psi_1[v] \sqcup_{\Psi[v]}\Psi_2[v] \\ \end{aligned}

若策略 p=(Allow:{a1,a2,,an},Deny:{d1,d2,,dm})p=(Allow:\{a_1,a_2,\dots,a_n\},Deny:\{d_1,d_2,\dots,d_m\}) 的所有约束 ψipred(ai)\psi \in \bigcup_i pred(a_i) 构成的 Aψ\mathcal{A_\psi}Well-behaved 的,现在针对 Pp\mathcal{P}_p 构造出的如下 Abstraction AP=(Granted(p),Pp,P,βP,γP,P,)\mathcal{A}_{\mathcal{P}}=(Granted(p), \mathcal{P}_p,\sqsubseteq_{\mathcal{P}},\beta_{\mathcal{P}},\gamma_{\mathcal{P}},\sqcup_{\mathcal{P}},\bot)

aPb    Granted(a)Granted(b)βP(r)={a1,,an,d1,,dm} s.t. 1in{ai=rj<iM(aj)rM(ai)ai=βai(r)otherwiseγP(P)=Granted(P){a11,,an1,d1,,dm}P{a12,,an2,d1,,dm}={a11a1a12,,an1anan2,d1,,dm}\begin{aligned} a \sqsubseteq_{\mathcal{P}}& b \iff Granted(a) \subseteq Granted(b) \\ \beta_{\mathcal{P}}(r)&=\{a_1',\dots,a_n',d_1,\dots,d_m\} \text{ s.t. } \forall_{1 \le i \le n} \begin{cases} a_i'=\bot & r \in \cup_{j<i}M(a_j) \lor r \notin M(a_i) \\ a_i'=\beta_{a_i}(r) & \text{otherwise} \\ \end{cases} \\ \gamma_{\mathcal{P}}(P')&=Granted(P') \\ \{a_1^1,\dots,a_n^1,d_1,\dots,d_m\} &\sqcup_{\mathcal{P}} \{a_1^2,\dots,a_n^2,d_1,\dots, d_m\}=\{a_1^1 \sqcup_{a_1}a_1^2,\dots,a_n^1 \sqcup_{a_n}a_n^2,d_1,\dots,d_m\} \end{aligned}

注意 AP\mathcal{A_{\mathcal{P}}} 不是 Well-behaved 的,反例如下:pp 的两条语句各自授权了 action 形如 aa*b*b 的所有权限。若请求 rr 的 action 是 abab(同时被两条语句匹配),按上述构造方式,Pp\mathcal{P}_pβ(r)\beta(r) 的最小集会被修正为 abab*\bot,但实际上 \botab*ab 同样符合要求,且前后两者均是极小集而不是最小集。

pp 中 allow 语句之间覆盖的请求没有交集,即 1i<jnM(ai)M(aj)=\forall_{1 \le i < j \le n} M(a_i) \cap M(a_j)=\emptyset,此时 APA_{\mathcal{P}} Well-behaved

不同类型的 Abstraction 构造

相等构造:对于 v=cv=c,考虑 C={c}C=\{c\}A={v=c,}A=\{v=c,\bot\},构造出来显然是 Well-behaved 的。

不等构造:对于 vcv \ne c,构造如下 Well-behavedAc=(val(c),Φc,,βc,γc,c,)\mathcal{A}_{\ne c}=(val(\ne c), \Phi_{\ne c},\to,\beta_{\ne c},\gamma_{\ne c},\sqcup_{\ne c},\bot)

val(c)={ddcdValuestype(c)(p)},i.e. all values d and has same type as cΦc={v=ddc}{vc}{}βc=v=dγc(v=d)={d},γc(vc)=val(c)acb={abababvcotherwise\begin{aligned} val(\ne c)&=\{d | d \ne c \land d \in Values_{type(c)}(p)\}, \text{i.e. all values } \ne d\text{ and has same type as }c \\ \Phi_{\ne c}&=\{v=d | d \ne c\} \cup \{v \ne c\} \cup \{\bot\} \\ \beta_{\ne c}&= \quad v=d \\ \gamma_{\ne c}(v=d)&=\{d\},\gamma_{\ne c}(v \ne c)=val(\ne c) \\ a \sqcup_{\ne c} b&=\begin{cases} a& b \to a \\ b& a \to b \\ v \ne c & \text{otherwise} \end{cases} \end{aligned}

比较构造:对于 vcv \le c,考虑 C={ddcdValuestype(c)(p)}C=\{d | d \le c \land d \in Values_{type(c)}(p)\},构造出来显然是 Well-behaved 的。

通配符 ? 构造:考虑 C=ΣC=\SigmaA=Σ{?}{}A=\Sigma \cup \{?\} \cup \{\bot \} ,构造出来显然是 Well-behaved 的。

通配符 * 构造:包含 * 和 σ\sigma 的 Abstraction A\mathcal{A}_{*} 有很多构造方式,其中 Well-behaved 的是 Apref\mathcal{A}_{pref}Asucc\mathcal{A}_{succ}

字符串前缀构造:构造如下的 Well-behavedApref=(Σ,Φpref,L,βpref,γpref,pref,)\mathcal{A}_{pref}=(\Sigma^*, \Phi_{pref},\subseteq_{\mathcal{L}},\beta_{pref},\gamma_{pref},\sqcup_{pref},\bot)

Φpref=Σ{σWσΣW{?,}}{}βpref(σ)=σγ(pat)=L(pat)xprefy={xyxyxyz?z=lcp(x,y)z+1=x=yxz?yz?zz=lcp(x,y)\begin{aligned} \Phi_{pref} &= \Sigma^* \cup \left\{\sigma W | \sigma \in \Sigma^* \land W \in \{?,*\} \right\} \cup \{\bot\} \\ \beta_{pref}(\sigma)&=\sigma \\ \gamma(pat)&=\mathcal{L}(pat) \\ x \sqcup_{pref} y&=\begin{cases} x & y \to x \\ y & x \to y \\ z? & z=lcp(x,y) \land |z|+1=|x|=|y| \land x \ne z? \land y \ne z? \\ z* & z=lcp(x,y) \end{cases} \end{aligned}

字符串前后缀构造:一个很自然的想法是将 Apref\mathcal{A}_{pref}Asucc\mathcal{A}_{succ} 合并成 Apref+suff\mathcal{A}_{pref+suff},即对于请求集合 {aa,aaa,aca}\{aa,aaa,aca\} 各自做一遍得到 (a,a)(a*,*a),合并后即为 aaa*a。可惜有反例,请求集合 {aa,aaa}\{aa,aaa\} 各自做一遍得到 (aa,aa)(aa*,*aa),合并后的 aaaaaa*aa 会错误地要求字符串长度至少是 44。不过 Apref+suff\mathcal{A}_{pref+suff} 并不是完全没有意义的,如果所有请求都满足长度至少为 ppref+psucc|p_{pref}|+|p_{succ}|,这种合并的方式一定是 Soundness 的,可以用来替代 A\mathcal{A}_{*}

特定正则串构造:对于特定的正则串 pat=σ0W1σ1Wnσnpat=\sigma_0W_1\sigma_1\dots W_n\sigma_n(其中 Wi{,?}W_i \in \{*,?\} ),借助 A\mathcal{A}_*A?\mathcal{A}_? 来构造如下 Abstraction Apat=(L(pat),Φpat,L,βpat,γpat,pat,)\mathcal{A}_{pat}=(\mathcal{L}(pat),\Phi_{pat}, \subseteq_{\mathcal{L}}, \beta_{pat},\gamma_{pat},\sqcup_{pat},\bot)

Φpat={σ0x1σ1xnσn xiΦWi}{}βpat(σ)=σ0x1σ1xnσns.t. xi=Ω(σ,pat)[0][i]γpat(pat)=L(pat)pat1patpat2={pat1pat2pat1pat2pat1pat2σ0z1σ1znσns.t. izi=xi1Wixi2otherwise\begin{aligned} \Phi_{pat}&=\{\sigma_0x_1\sigma_1\dots x_n\sigma_n\ | x_i \in \Phi_{W_i}\} \cup \{\bot\} \\ \beta_{pat}(\sigma)&=\sigma_0x_1\sigma_1\dots x_n\sigma_n \quad \text{s.t. }x_i=\Omega(\sigma,pat)[0][i] \\ \gamma_{pat}(pat')&=\mathcal{L}(pat') \\ pat_1 \sqcup_{pat} pat_2 &= \begin{cases} pat_1 & pat_2 \to pat_1 \\ pat_2 & pat_1 \to pat_2 \\ \sigma_0z_1\sigma_1\dots z_n\sigma_n \quad \text{s.t. } \forall_i z_i=x_i^1 \sqcup_{W_i}x_i^2 & \text{otherwise} \end{cases} \end{aligned}

可惜 Apat\mathcal{A}_{pat} 不是 Well-behaved 的,因为 β(σ)\beta(\sigma) 会盲选第一个匹配方案。以 pat=aapat=a*a* 来举反例:

σ\sigma Ω(σi,pat)\Omega(\sigma_i,pat)
σ1=aaaa\sigma_1=aaaa [(aa,ϵ),(a,a),(ϵ,aa)][(aa,\epsilon),(a,a),(\epsilon,aa)]
σ2=aaaaa\sigma_2=aaaaa [(aaa,ϵ),(aa,a),(a,aa),(ϵ,aaa)][(aaa,\epsilon),(aa,a),(a,aa),(\epsilon,aaa)]
σ3=abaa\sigma_3=abaa [(b,a)][(b,a)]

β(σi)\beta(\sigma_i) 盲选第一个匹配方案后,两个位置的结果分别是 {aa,aaa,b}\{aa,aaa,b\}{ϵ,ϵ,a}\{\epsilon,\epsilon,a\},两两合并后的结果是 (,)(*,*)。但如果智能地选择了第二个、第三个和第一个,{a,a,b}\{a,a,b\}{a,aa,a}\{a,aa,a\} 能合并出一个更紧的结果 (?,a)(?,a*)

论文把 σ,Ω(σ,pat)>1\exist \sigma,|\Omega(\sigma,pat)|>1patpat 称为 ambiguous pattern,指出 unambiguousApat\mathcal{A}_{pat} Well-behaved 的。

析取构造ψ=ψ1ψn\psi_{\lor}=\psi_1 \lor \dots \lor \psi_n 构造出来显然是 Well-behaved 的,如果 iAψi\forall_i \mathcal{A}_{\psi_i}Well-behaved 的。

合取构造ψ=ψ1ψn\psi_{\land}=\psi_1 \land \dots \land \psi_n 构造出来显然是 Well-behaved 的,如果 iAψi\forall_i \mathcal{A}_{\psi_i}Well-behaved 的。

IAM-PolicyRefinerNeg

从请求集 CC 中找到最小权限策略的过程称为 IAM-PolicyRefiner。论文表示很多时候求对偶问题会更方便,即我们想找到一个最大权限策略使得其拒绝整个请求集 CC,称为 IAM-PolicyRefinerNeg。搜索空间看似变得不规则了,但我们只需稍微修改下之前 Policy Search Space Pp\mathcal{P}_p 的定义,改为 Allow 不变而 Deny 变化。

NFA2SAT

CAV 2023, AWS, Kevin Lotz: Solving String Constraints Using SAT

简介

提出了 NFA2SAT 的字符串约束求解器,使用 CaDiCaL 作为后端,将字符串约束转化为纯 SAT 约束迭代式求解。整体思想类似 WOORPJE,但证明了迭代长度的上限,可以在有限步停止并输出 UNSAT。

对比经典的 SMT 求解器,NFA2DFA 更适合 SAT 但不适合 UNSAT。ZALIGVINDER 测试集上结果如下:

框架

本文考虑的字符串命题 ψ\psi 的定义如下:

F=FFFF¬FAtomAtom=xREx=yRE=RERERERERERERE?w\begin{align} F&=F \lor F \mid F \land F \mid \lnot F \mid \text{Atom} \\ Atom&=x \in RE \mid x=y \\ RE&=RE \cup RE \mid RE \cdot RE \mid RE^* \mid RE \cap RE \mid ? \mid w \end{align}

利用 BMC 思想,将字符串命题 ψ\psi 转化成分步 SAT 询问,第 bb 次格式形如 ψADbhb\psi_{\mathcal{A}} \land \mathbf{D}^b \land h^b

  • ψA\psi_{\mathcal{A}} 表示将原命题进行 Boolean Abstraction,即将 xRE,x=yx \in RE,x=y 等原子约束替换成布尔变量。
  • Dbhb\mathbf{D}^b \land h^b 会针对每组原子约束,结合当前的长度上限 bb 进行编码。

字母表缩减技术

论文证明了字符串命题 ψ\psi 只需考虑所有约束里出现的字符+每个字符串变量增加一个专属字符。

增量编码细节

字符串变量 xx 编码细节:假设第 kk 次求解的长度上限是 bk(x)b_k(x),设置 bk(x)×(Σ+1)b_k(x) \times (|\Sigma|+1) 个辅助布尔变量表示 x[i]x[i] 是否是字符 jj(其中用 λ\lambda 表示独立于 Σ\Sigma 外的填充专用字符)。相比于前一次的增量限制为:

hbk1bk=(xbk1(x)+1bk(x)ExactOne(hx[i]aa{Σ,λ}))(xbk1(x)bk(x)1hx[i]λhx[i+1]λ)h^{b_{k}}_{b_{k-1}}=\left(\bigwedge_{x} \bigwedge_{b_{k-1}(x)+1}^{b_{k}(x)} ExactOne({h^a_{x[i]}} | a \in \{\Sigma, \lambda\})\right) \land \left(\bigwedge_{x} \bigwedge_{b_{k-1}(x)}^{b_{k}(x)-1} h_{x[i]}^\lambda \to h_{x[i+1]}^\lambda \right)

其中第二部分是用来限制占位符后必须全是占位符,保证解的唯一性。

正则约束 xRx \in R 编码细节:构造对应的 NFA (Q,Σ,δ,q0,F)(Q,\Sigma,\delta,q_0,F),注意每个状态 qq 都设一条连向自己的转移边 λ\lambda。对自动机里的每个状态都设置字符串长度个布尔变量 SqiS_q^i,表示字符串变量的前缀 x[1..i]x[1..i] 是否能走到状态 qq

通过枚举状态和转移边的组合 (q,a)q(q,a) \to q' 来构造约束:

bk1(x)bk(x)1(q,a)dom(δ)qδ(q,a)(Sqihx[i+1]a)Sqi+1\bigwedge_{b_{k-1}(x)}^{b_{k}(x)-1} \bigwedge_{(q,a) \in dom(\delta)} \bigwedge_{q' \in \delta(q,a)} (S_q^i \land h_{x[i+1]}^a) \to S_{q'}^{i+1}

每个 SqiS_q^i 集群之间的转移自洽还不够,必须限定 SqiS_{q'}^i 如果为真就必须有一条从 Sqi1S_q^{i-1} 过来的通路,即:

bk1(x)+1bk(x)qQ(Sqi(q,a)pred(q)(Sqi1hx[i]a))\bigwedge_{b_{k-1}(x)+1}^{b_{k}(x)} \bigwedge_{q'\in Q} \left(S_{q'}^i \to \bigvee_{(q,a) \in pred(q')} (S_q^{i-1} \land h_{x[i]}^a)\right)

kk 步判断 xRx \in R 是否成立,等价于验证 NFA 上走正好 bk(x)b_k(x) 步能否被接受,即 Acc(x)=qendSqendbk(x)Acc(x)=\bigvee_{q_{end}}S_{q_{end}}^{b_k(x)}。新增一个选择变量 sks_k,将 xRx \in RxRx \notin R 编码为 skAcc(x)s_k \to Acc(x)sk¬Acc(x)s_k \to \lnot Acc(x),本次要求 sk(j<k¬sj)s_k \land \left(\bigwedge_{j<k} \lnot s_j \right)

相(不)等约束编码细节:命题 ψ\psi 里只会由字符串变量和常量字符串构建相(不)等关系,所以编码相对简单。第 kk 次求解时,只需分类考虑 w|w| 和区间 (bk1(x),bk(x)](b_{k-1}(x),b_k(x)] 的大小关系,在 hx[i]a,w[i],λh_{x[i]}^a,w[i],\lambda 三者里构建约束。

上界推算

hh 是字符串命题 ψ\psi 里所有字符串长度之和最短的解,论文希望能确定 hh 的上界,来保证算法能停下来。

首先考虑 normal form(整体是 CNF,每个元素都是不为字符串相等的原子约束)的字符串命题 φ\varphi。如果针对变量 xix_i 的约束只含有 xiRx_i \in RxiRx_i \notin R 形式,我们可以构造大型 NFA Mi=t=1kL(Rt)t=1l(Rt)M_i=\bigcap_{t=1}^k \mathcal{L}(R_t) \cap \bigcap_{t=1}^l \overline{(R'_t)}。设 QiQ_iMiM_i 的状态集合,可得 h(xi)Qi|h(x_i)| \le |Q_i|。论文进一步证明了若含有 kk 个形如 xiwx_i \ne w 的不等约束:

h(xi)2k×Q1××Qn|h(x_i)| \le 2^k \times |Q_1| \times \dots \times |Q_n|

当然在实际实践中,可以先把命题拆成一些变量彼此独立的部分,以减小 Qi|Q_i| 对上限的影响。

针对可能存在的相等约束 x=wx=w,我们知道 h(xi)=w|h(x_i)|=|w|,且 ψx=w\psi \land x=w 可转化为 ψ=ψ[x=w]\psi'=\psi[x=w] 来消去这条相等约束。如果 ψ\psi 不是 CNF 的形式,可以转化为外层 DNF 内层 CNF 的一般形式,上界就是取最大值。

Multi-Step IAM Attacks

USENIX 2023, Citi, Ilia Shevrin: Detecting Multi-Step IAM Attacks in AWS Environments via Model Checking

简介

本论文深度基于 AWS 的云上环境,深度建模了 IAM 的鉴权系统,并在此之上创新性地构建了云上多步提权攻击路径检测的 Bounded Model Checking。作者坦言当前的 BMC 是 not complete 的,即只能预设一个最大步长来聚焦短的攻击路径,没法像 k-induction 那样证明整个系统的安全性。实测发现步长 5\ge 5 的路径非常少。

本论文除了构造了 Bool+Str 的常规 SMT 编码外,还提出了一种基于纯 Bool 的 SAT 编码(还原 Str 时需要 SMT 编码)。实验分别测试了同账号场景(资源个数分布在 200700200 \sim 700 之间)和同组织跨账号场景(账号个数分布在 5805 \sim 80,平均每个账号有约 200200 个资源),可以发现在大规模场景里后者具有明显的优势。

IAM 鉴权建模

本论文有明确的威胁假设和覆盖场景,包括:攻击者必须从某个合法的 AWS 身份开始操作,攻击者知道账号或组织下的资源配置和资源名,攻击者仅通过 IAM 体系发起提权(而非网络等方式),切换委托没有时效等。

IAM 鉴权建模完全参照 AWS 对外公开的鉴权流程,下面展示了鉴权全流程图和身份策略鉴权逻辑图。本论文对 InvokeFunctionRunInstances 的建模处理和 AssumeRole 很接近,即这两个操作都可以达成目标身份的切换。UpdateFunctionCode 可以覆盖 Function 内容,就和 UpdateAssumePolicyRole 一样。

框架

整个提权建模就是个 BMC 框架。通过 AWS 的 GetAccountAuthorizationDetails 接口拿到详细的云上安全配置并做初始化。实验代码用 JAVA 开发,使用的 SMT 求解器后端是 Z3,通过 Z3 Java API 调用来建模。

SMT 转 SAT

值得一提的是论文提出的 String 约束转 Bool 约束的思路。将所有策略里的正则约束全部提权出来构成数组(字符串常量看作一种特殊的正约束),每个字符串变量就能转化成等长的布尔数组,表示是否满足当前正则约束。由于这个数组的顺序不重要,以下用 str[reg]str[reg] 表示变量 strstr 关于正则约束 regreg 的布尔变量。当整个算法求解结束时,字符串变量获得的其实是一组布尔数组的 01 取值,需要再用一个后处理(Algorithm 2)来构造真实串。

整个流程有个预处理(Algorithm 1),即两两枚举正则约束 (reg1,reg2)(reg_1,reg_2) 来识别两者的包含关系或者冲突关系,反映在布尔数组的关系里。这个算法最早在 AWS 论文中提出,仅在不含 ? 只含 * 的场景下能保证正确性(约束的完整性)。也就是说,仅 Bool 建模的做法出解后,有可能会发生字符串解无法被还原的严重问题。

Incremental Inprocessing in SAT

SAT 2019, Johannes Kepler University, Katalin Fazekas: Incremental Inprocessing in SAT Solving, Slides

A billion SMT queries a day

CAV 2022 (Invited Paper), AWS, Neha Rungta: A billion SMT queries a day

Zelkova and Z3AUTOMATA

FMCAD 2018, AWS, John Backes: Semantic-based automated reasoning for AWS access policies using SMT