我们是一家人:关联信息流追踪器
摘要
尽管信息流安全是一个已建立较久的领域,但在具有形式化保证 但实际影响有限的重量级 information-flow con-trol与适用于漏洞查找但 缺乏形式化保障的轻量级tainting技术之间,仍存在令人不安的差距。本 文提出一种框架,用于探索从污染分析(仅跟踪数据流)到完整的信息流 控制(同时跟踪数据流和控制流)之间各种执行机制的中间地带。我们形 式化地说明了该框架在健全性与宽松性之间所能实现的权衡。该框架以分 阶段方式部署,通过静态嵌入动态监控器,并对安全策略保持参数化,因 为安全策略无需在最终部署前固定。这种灵活性有助于实现一种安全应用 商店架构,其中静态验证阶段由应用商店执行,而动态阶段则部署于客户 端。为展示该框架的实用性,我们针对Java核心实现了我们的方法,并在 安卓环境下评估了其在实施隐私政策方面的用例。我们还展示了如何轻松 调整最先进的JavaScript动态监控器以实现我们的方法。
关键词: 基于语言的安全 · Information-flow control · Taint跟踪
1 引言
动机
软件所处理的敏感信息数量巨大,使得安全成为一个主要问题。最近的 一份报告显示,Google Play 商店中十大最受欢迎的手电筒应用中的多个可能 会将图片和视频、用户位置以及联系人列表等敏感信息发送到不可信服务器[49]。
不幸的是,可信代码也会引发严重的安全缺陷,这一点已被在 OpenSSL 库中 发现的心脏出血漏洞所证实[51]。
信息流控制 [44]通过设计提供了一种有吸引力的安全保障方法。它有助于 跟踪信息从机密/不可信源到公开/可信汇的流动,确保在机密性方面,机密输 入不会泄露到公共输出中;在完整性方面,不可信输入不会影响可信输出。
背景
应用程序可能通过编程语言结构泄露信息,从而产生两种基本类型的信 息流:显式和 隐式流 [21]。考虑一种设有变量 secret和 public分别用于存 储机密(或高)和公开(或低)信息的场景。当敏感信息通过赋值显式传递时, 就会发生显式流,例如在 public中:= secret。隐式流则通过程序的控制流结 构产生,例如条件语句和循环,如如果 secret则 public:=0否则 public: = 1。变量 public的最终值依赖于 secret的初始值,这是因为在高上下文中进行 了低赋值,即在一个秘密条件所控制的分支中对低变量进行的赋值。
信息流控制通常分为静态和动态两类:(1)静态技术主要采用Denning方 法[21],通过为输入数据(例如变量、API)分配安全标签,并确保秘密计算 与公开计算之间的隔离,其本质是维护“在高上下文C中不发生低赋值”的不变 式。其他静态技术包括程序逻辑[10,13],、模型检测[8,23],、抽象解释[27]和 定理证明[20,40]。然而,静态技术面临精度问题(误报率高),会拒绝许多安 全程序。这些问题包括动态代码求值和别名,如以下代码片段所示: x.f:= 0; y.f:= secret ; out(L x.f)。一个复杂的静态分析必须近似判断对象引用 x和 y是否为别名。此外,由于安全策略必须在验证时已知,这使得静态技术在动 态环境中适用性较差。(2)动态技术利用程序运行时信息来跟踪信息流 [5,26,43]。通过监控被分析程序的执行以检测安全违规行为。总体而言,监控 器强制执行的不变式是:不允许从高变量向低变量发生显式或隐式的赋值。动 态技术特别适用于高度动态的环境和策略,在这些场景中代码通常直到运行时 才可知。然而,由于其底层语义条件非干涉[28],并非迹性质[38],,动态技术 难以处理当前执行未覆盖的分支。考虑如下操作位置信息的安全程序:如果 (MIN ≤ loc) && (loc ≤ MAX) 则 tmp:= loc否则跳过。如果用户(秘密) 位置 loc位于由常量MIN和MAX界定的区域内,程序会将精确位置存储在一个 临时变量 tmp中,但从未将其发送给公开观察者。一种动态分析技术,例如无 敏感升级[5,58],,会错误地拒绝该程序(因为在高上下文C中发生了安全标签 升级),尽管 loc和 tmp实际上从未被发送给攻击者。宽松升级[6]可提高精 度,但它会错误地排除任何后续基于变量 tmp进行分支的安全程序。
结合动态与静态分析,hybrid方法最近受到了越来越多的关注 [18,31,36,37,39]。尽管这些方法能够提供强有力的形式化保证,但迄今为止, 它们的实际影响仍然有限,主要原因是精度(或宽松性)较低。此外,静态、 动态以及混合式信息流分析都需要掌握控制流图的知识,以便正确传播用于跟 踪的program counter安全标签
上下文C的敏感性。每当代码经过重量级优化和混淆(例如,为了保护其知识 产权)或存在反射时,该标签都难以恢复。
相比之下,污点追踪 是计算机安全领域的一个实际成功案例,在硬件和软 件栈的各个层面都有广泛应用 [45,47]。污点追踪是一种纯粹的数据依赖分析, 仅追踪显式流。由于其轻量级特性,忽略了完全信息流控制所必需的任何控制 流依赖,因而取得了成功。但缺点在于,污点追踪主要被用作一种漏洞查找技 术,除了少数例外情况 [45,46,57],之外,并不提供形式化保证。重要的是, 隐式流不仅可能出现在恶意代码中,[33,42],还可能出现在可信程序(由可信 程序员编写)中 [11,34,35,50]。
这些考虑指出了信息流控制领域中重量级技术与轻量级污染技术之间令人 不安的差距:前者具有形式化保证但实际影响有限,而后者在漏洞查找方面有 用却缺乏形式化保障。
方法
通过考虑健全性与宽松性之间的权衡,本文探索了中间路线,提出一个 涵盖从污点追踪到完整信息流控制的多种执行机制的框架。我们同时处理可信 和恶意代码。然而,我们在两类隐式流之间做出了关键区分:可观察的隐式流 与隐藏的隐式流,借用了斯塔伊库和普拉德尔的术语[50]。每当变量在高安全 上下文中被更新并随后输出给攻击者时,就会产生可观察的隐式流。但并非所 有隐式流都是可观察的,因为变量未被更新这一事实本身也可能泄露信息(参 见图3);我们将这类情况称为隐藏的隐式流。追踪显式流和可观察的隐式流提 高了对可信代码的安全门槛[50]。这种方法允许采用宽松、轻量级且纯粹动态的 执行方式,类似于污点追踪,同时提供更高的安全保障。为了评估该技术的健 全性和宽松性,我们提出了可观察保密性这一新的安全条件,它捕捉了可观察 隐式流的本质。它帮助我们回答一个问题:“对于有用程序减少误报的同时, 我们在安全性上付出了什么代价?” 我们指出,可观察与隐藏隐式流之间的区 别完全是出于执行便利性和宽松性的考虑。此外,我们利用现有技术并扩展该 框架以涵盖隐藏的隐式流,从而应对恶意代码。接着,我们展示了一系列流敏 感的动态监控器,这些监控器通过调整文献中标准的信息流监控器来实施一系 列安全策略[5,43]。
该框架以分阶段方式部署。我们通过轻量级程序变换,将针对(可观察和/ 或隐藏的隐式流)的动态监控器静态嵌入到程序代码中,并利用动态污点跟踪 器来实施更强的安全策略。对于恶意代码,我们采用瓦查拉贾尼等人[53]为系 统代码提出的交叉复制技术,将隐藏的隐式流转换为可观察的隐式流。相关变 换及定理的完备性证明可在论文完整版本[14]中找到。
安全应用商店
该方法在策略和执行方面的灵活性促进了一种安全应用商店架构,如图1所示。开发者将代码提交至应用商店,应用商店计算源和汇,并利用 控制流图将隐式流转换为显式流。对于可信(非恶意)应用,轻量级的转换 (将可观察的隐式流转换为显式流)可能已足够;否则需要进行交叉复制。随 后,应用商店可以执行代码优化和混淆,并代表开发者发布生成的APK文件 (连同源和汇)。最后,终端用户可以下载应用,定义自己的安全策略,并在 动态污点跟踪器上运行该应用,值得注意的是,无需程序的控制流图。此外, 终端用户也可以利用静态污点跟踪器[1,29]来针对代码验证其策略。
我们实现了一个Java核心的变换,并在计步器应用这一用例上进行评估。 我们在TaintDroid [24]上运行经过变换的应用,并根据用户定义策略对其进行 检查。我们还展示了JSFlow [30], (一种用于JavaScript的动态监控器)如何 通过将安全条件更改为可观察保密性来提供更高的精度。
结构与贡献
总之,本文做出了以下贡献:(i)可观察保密性,一种用于验证 相对于可观察的隐式和显式流在正确性和精度上的安全条件(第2节);(ii) 一个框架,能够表达从污点追踪到信息流控制的一系列执行机制(第3节); (iii)利用动态污点追踪实现更高安全保障的轻量级变换(第4节);(iv)一 种灵活的应用商店架构及针对Android应用的原型实现(第5节)。
2 安全框架
我们采用基于知识的定义[4,9,10]来引入从弱/显式保密性[45,57]到非干涉[28]的 安全条件。
2.1 语言
考虑一种带有I/O原语的简单命令式语言SIMPL。该语言的表达式由变量 x ∈ Var、 内置值 n ∈ Val(例如
整数和布尔值,二元运算符 ⊕和一元运算符 。我们用 tt表示布尔值 真 和 ff 表示布尔值假。语言结构包含跳过、赋值、条件语句、循环、输入和输出。 SIMPL 的完整语法可以在图2中找到。
我们使用输入和输出通道来建模程序与外部世界的通信。我们为输入和输 出通道标注安全级别 (定义如下),以表示在相应通道上传输信息的机密性 级别。我们将SIMPL程序的集合记为 P。我们用 x¯表示变量集合{x1,···, xn}, 使得对于所有1 ≤ i ≤ n, xi ∈ Var,以及用 V ars(e)表示表达式 e的自由变量集合。
我们假设存在一个有界格的安全级别(L,,,)。一个级别 ∈ L表示 存在于给定通道或程序变量中的数据的机密性。我们假设有多少个安全级别就 有多少个对应的通道。通常, 表示安全级别之间的序关系,和 分别表 示并运算和交运算格操作符。我们用和 ⊥分别表示格的最大元素和最小元 素。在示例中,我们使用一个两级安全格 L={L,H},其中级别H(高)用于 包含机密信息的变量/通道,级别L(低)用于包含公开信息的变量/通道,并 且L H。我们主要关注机密性,注意到通过取对偶可类似地处理完整性[16]。
我们通过环境 E ∈ Env对输入建模,该环境将通道映射到输入值流。为简 化起见,我们为每个级别 ∈ L考虑一个流。一个环境 E: L → N → Val将 级别映射到无限值序列。两个环境 E1和 E2是 ‐等价的,记作 E1 ≈ E2,当 且仅当 ∀′. ′ ⇒ E1( ′) = E2( ′)。另一种输入来源是程序变量的初始值。
我们将内存建模为从变量到值的映射 m: Var → Val。我们使用 m, m0, m1, . . . 来表示内存状态。我们用 m[x → n]表示将变量 x赋值为 n的内存 m。 我们用 m(e)表示表达式 e在内存 m中的值。安全环境 Γ: Var → L是从程序 变量到格元素的映射。安全环境通过程序变量为内存分配安全级别。我们用术 语安全级别和安全标签作为同义词。两个内存状态 m1和 m2是 ‐等价的,记作 m1 ≈ m2,当且仅当 ∀x ∈Var. Γ(x) ⇒ m1(x) = m2(x)。
观测集 α ∈ Obs 是一个安全级别和一个值的对,即 Obs= L×Val,或空观测 ε。 迹 τ 是一个观测的有限序列。我们用 τ.τ′ 表示迹 τ 和 τ′ 的连接,用 |τ|表示迹 τ 的长度。我们用 τ 表示迹 τ 在安全级别 上的投影。形式上,我们有ε = ε 且 (′, n).τ′ =(′, n).(τ′ ) 如果 ′ ;否则为 (′, n).τ′ = τ′ 。两个迹 τ 1、 τ 2 是 ‐等价的,记作 τ 1 ≈ τ 2, 当且仅当 τ 1 = τ 2 。
2.2 语义
SIMPL的操作语义是标准的,详见完整版本[14]。状态(E, m)是由环境 E ∈ Env和内存m ∈ Mem组成的一对。一个配置 E 〈P, m〉由环境 E、程序P和内 存 m构成。我们用 E 〈P, m〉 −→α E′ 〈P′, m′〉表示一个配置 E 〈P, m〉经 过一步求值得到配置 E′ 〈P′, m′〉,并产生观测集 α ∈Obs。我们用 →−∗或 −→τ∗ 表示 →−的自反传递闭包。当配置不重要时,我们使用 E 〈P, m〉 τ′ −→。我们用 ε表示程序终止。
2.3 定义保密性
本小节的目标是提供一种以攻击者为中心的保密性定义。该条件要求,通过观 测程序输出所获得的知识不会使攻击者能够获取关于初始程序状态(输入和内 存)的敏感信息。我们假设攻击者知晓程序代码,并且对所有过去的观测具有 完美记忆。我们首先通过一个示例说明安全条件,然后给出其形式化定义。
示例1。 设 P=如果 h则 输出(L,1) 否则 输出(L, 2)为一个SIMPL程序,且 h为秘密变量, 即 Γ(h) = H。根据 h的初始值,该程序会在安全级别为L的信道上输出输出(L,1)或输出( L,2)。
安全级别为L的攻击者可以对 h的初始值进行如下推理:(i)在未看到 任何输出之前,攻击者认为 h的任意布尔值都是可能的,因此其知识为 h ∈{ tt,ff}。(ii)如果执行了语句out(L,1),攻击者便可将知识精炼为 h ∈{tt}, 从而得知 h的初始值。(iii)类似地,如果执行了语句out(L,2),攻击者便得 知 h最初为假。因此,该程序是不安全的。
我们现在定义攻击者在级别 通过观测程序 P的迹所获得的知识。我们通过考 虑攻击者基于其观测认为可能的初始状态集合来描述这一点。具体而言,对于 给定的初始状态(E0, m0)和程序 P,如果 E ≈ E0, m ≈ m0,成立,并且它与由 E0 〈P, m0〉产生的迹相匹配,则初始状态(E, m)被认为是可能的。我们以标准 方式定义攻击者的知识[4]:
定义1(知识)。 对于程序 P、知识集、初始状态( E0 | E ≈ E0 ∧ m ≈ m 0 ∧ m 0 τ k P E0 m 0 τ={ E m ∃P ′ E′ m ′ τ′. E 〈P m〉 τ ′ −→ ∗ E′ 〈P′ m ′〉 ∧ τ ≈ τ′ })、安全级别和迹,其由 (,,,)(,)(,,,,,)给出。
我们关注的是对进度不敏感的安全,这种安全忽略通过观测计算进度(例 如程序发散[3])导致的信息泄露。为此,我们放宽了攻击者在每个执行步骤中 都不得获取任何知识的要求,允许因观测到计算进度而产生的泄露。具体而言, 我们将进度知识定义为:基于某个输出事件已经发生这一事实(而不论确切输 出值为何),攻击者认为可能的初始状态的集合。
定义2(进度知识)。 对于程序 P、初始状态(E0, m0 = { τ m0 τ E m | E ≈ E0 ∧ m ≈ m0 ∧ ∃P′ E′ m′ τ′ α = ε. E 〈P m〉 τ′ −→∗ E′ )、级别 ,以及迹,其进度知识集由 kP(P, E0,,)(,)(,,,,,〈P′, m′〉 −→α∗ ∧ α = α ∧ τ ≈ τ′)}给出。
我们现在可以通过要求在观察迹 τ后获得的进度知识与观察迹 τ.α后获得 的知识相同,来定义一种progress-insensitive保密性。因此,攻击者通过观察 确切输出值所获得的知识,与通过观察计算进度(即某个输出事件已经发生) 所获得的知识是相同的。
定义3(进度无关保密性)。 一个程序 P在级别 , E 〈P P m〉 −τ−.→α ∗ E′ 〈P′ m′〉 ∧ α = α ∧ α = ε, kP P E m τ= 上满足 进度无关保密性,记作Sec(),当且仅当若,,则有(,,,)k(P, E, m, τ.α)。 P满足进度无关 保密性,记作 Sec | = P当且仅当Sec() P,对所有 成立。
我们可以看到,示例1中的程序在安全级别 L上不满足进度无关的保密性, 因为观测到某个某些输出(即 out(L,1) 或 out(L,2)的进度知识为 h ∈{tt, ff},而观测到确切输出(例如 out(L,1))的知识为 h ∈{tt}。
2.4 安全条件
信息流监控器可以执行进度无关保密性,从而防止隐式流和显式流。另一方面, 污点追踪是一种仅防止显式流的执行机制,否则会忽略任何控制流依赖 [21]。
与非干涉不同,污点追踪的安全条件 [45,57] 更多地作为评估底层执行机制的 健全性和精度的语义标准,而非提供安全性的直观含义。基于相同的动机,我 们提出了一族安全条件,使得能够从污点追踪到信息流控制之间探索执行机制 的空间。
我们的安全条件依赖于攻击者对程序代码和执行的观察能力。我们根据攻 击者在每次运行中对程序代码的视角进行建模,并提取出攻击者认为在任何具 体执行中可能存在的程序slice。这使得我们可以重用定义3中的相同条件,用 于攻击者能够观察到的程序slice。
具体来说,污点追踪的安全条件可 以模型化为:针对仅观测从程序P的具体执 行中提取的显式语句(输入、输出和赋 值)的攻击者所定义的保密性 P。类似 地,(终止条件不敏感的)非干涉性[3] 对应于攻击者能够完整观测 P的保密性。
我们将使用图3中的示例来说明安全条件。考虑程序 P,其布尔变量 h的 安全级别为H,布尔变量l1、 l2的安全级别为L。可以看出,该程序通过一系 列控制流决策,将变量 h的初始值输出给安全级别为L的观察者。事实上,该 程序不满足定义3中的条件。
我们引入提取上下文 C作为一种工具,用于对攻击者在程序代码上的观 察能力进行建模。提取上下文提供了一种机制,利用语言的操作语义,针对任 何给定的具体执行提取出攻击者所观测到的程序切片。
C::=[] | skip | x:= e | x ← in() | out(, e) | C; C | if e then C else C
从语法上讲,提取上下文是可能包含占位符[]的程序。在本文中,上下文 最多包含一个占位符,用于表示当前程序执行尚未评估的程序语句。我们扩展 了操作语义,以转换上下文,从而为弱保密性和可观察保密性提取程序。
弱保密性
弱保密性[57],污点追踪的一个安全条件,指出任何程序运行所执行 的显式语句序列都必须是安全的。我们将弱保密性形式化为针对程序的保密性 (参见定义3),即从原始程序的任何(可能不完整)执行中提取出的显式语句 序列的保密性。为此,我们通过在配置中添加提取上下文来实现。这里我们讨 论图4中报告的一些有趣的规则。完整的规则集可以在[14]中找到。
每个程序执行都从空上下文[]开始。为了提取显式语句,我们将赋值和输 出命令传播到上下文C中,而条件语句则被忽略(即上下文保持不变)。顺序 组合确保了显式语句序列的正确传播。可以证明,完整的(终止的)执行不包 含空洞,而不完整执行恰好包含一个空洞。
我们通过从任意程序执行中提取的显式语句来定义弱保密性。我们用 C[ skip]表示在上下文C C中将空位替换为命令skip的结果。否则,如果上下文 C中没有空位,则得到 C[skip]= C。这是必要的,因为安全条件是针对任何执 行定义的,包括完整和不完整执行。
定义4(弱保密性)。 一个程序 P满足初始状态(,)的弱保密性,记作WSE,m P, 当且仅当若 E 〈P, m,[]〉 −→τ∗ E′ 〈P′, m′, C〉,则有 Sec | = C[跳过]。一个程序 P 满足弱保密性,记作WS P,当且仅当对所有状态(E, m),WSE,m P成立。
考虑图3中的程序以及初始状态(E0, m0)。根据 m0(h)= tt且 m0(h)= ff,我们分别提取出程序 (5) 或程序 (6),如图5所示。
我们可以看到,两 个程序中均不包含变量 h, 因此它们都满足保密性 (定义3)。因此,原始 程序 P满足弱保密性。
可观察保密性
我们现在提出一种新的安全条件,称为可观察保密性,用于捕 捉可观察的隐式流的直观含义。可观察的隐式流是指每当一个变量在程序当前 执行的高分支中被修改,并随后输出给攻击者时所产生的隐式流。防止可观察 的隐式流对于纯动态机制而言具有重要意义,因为它相比弱保密性提供了更高 的安全性,同时允许动态监控器比非干涉监控器更加宽松。然而,这种宽松性 的代价是忽略了隐藏的隐式流。以下程序中,若 h的安全级别为H,则当 m0(h) = tt时存在可观察的隐式流,否则该流是隐藏的。
l:= ff; if h then{l:= tt} else{skip}; out(L, l)
安全条件考虑了一种攻击者,该攻击者仅观察具体程序执行过程中所执行 的指令(包括控制流和显式语句),而忽略(即用跳过替换)未执行分支中出 现的任何指令。为了捕捉这些信息流,我们扩展了小步操作语义,以提取该攻 击者可观察到的程序代码,如图6所示。
赋值、输入、输出和顺序组合的规则与弱保密性相同。条件语句的规则将 observable条件传播到上下文 C中,以跟踪已执行分支,并将未执行分支替换 为skip。新引入的空位[]确保在已执行分支下的命令能被新的上下文正确修改。 循环语句被展开为条件语句,并以类似方式处理。顺序组合确保观测集语句序 列被正确传播。当应用规则 O-SeqEmpty时,上下文 C不包含任何空位,因 此引入一个新的空位以正确处理剩余命令 P2。
定义5 (可观察保密性)。 当且仅当 E 〈P, m,[]〉 τ −→ ∗ E′ 时,程序对初始状态 (E, m)满足可观察保密性,记作OSE,m P
〈P′, m′, C〉,我们有 Sec | = C[跳过]。一个程序 P满足可观察保密性,记作OS P, 当且仅当OSE,m P对于所有状态(E, m)。
对于上述示例,可观察保密性的操作语义规则生成了以下程序:
l:= ff; if h then{l:= tt} else{skip}; out(L, l) l:= ff; if h then{skip} else{skip}; out(L, l)
第一个程序不满足保密性(定义3),而第二个程序满足。因此,原始程序不 满足可观察保密性。
完全保密
完全保密是一种安全条件,用于对攻击者具有程序代码的全部知识 并因此能够通过显式和(可观测或隐藏的)隐式流获取信息的情况进行保密性 建模。这对应于进度不敏感非干扰(定义3)。
定义6(完全保密性)。 对于初始状态(E, m),若程序 P满足完全保密性,记作 FSE,m P,当且仅当只要 E 〈P, m〉 τ −→ ∗ E′ 〈P′, m′〉成立,则有Sec | = P。若程 序 P满足完全保密性,记作FS P,当且仅当对所有状态(E, m)均有FSE,m P。
3 执行框架
我们采用流敏感的动态监控器(跟踪器)的变体来实施上一节中提出的安全条件。 与现有工作相比
(参见第6节),我们使用语义安全条件——弱保密性和可观测保密性——来证 明弱跟踪和可观测跟踪机制的健全性。
图7展示了插桩语义,该语义在安全标签、传递函数和约束上是参数化的。 通过实例化每个参数(表1),我们展示了该语义如何实现弱保密性(定理1)、 可观测保密性(定理2)和完全保密性(定理3)的可靠动态跟踪器。所有证明 均报告于完整版本 [14]。
插桩语义假设一个有界格(L,,,)和一个初始安全环境 Γ,如第2.1节 所定义。我们使用一个程序计数器安全级别栈 pc来跟踪在某一执行点处的安 全上下文,即条件和循环表达式的安全级别。我们用:: pc表示一个标签栈,其 中标签 是其栈顶元素。为方便表示,我们也用 pc表示栈中元素安全级别的 上界。监控语义引入了特殊的指令 end来记录控制流中的汇合点,并相应地更 新 pc栈。仪器化配置 Γ,pc, E 〈P, m〉扩展了原始的
我们是一家人:关联信息流跟踪器 1 35
配置包含安全环境 Γ和安全上下文栈 pc。我们用 Γ,pc, E 〈c, m〉 −→α→ Γ′,pc′, E′ 〈c′, m′〉表示插装配置 Γ,pc, E 〈c, m〉经过一步求值得到插装配置 Γ′, pc′, E′ 〈c′, m′〉,并产生观测集 α ∈Obs。我们用→−→∗或 −→τ→∗表示 −→α→的自反 传递闭包。我们用 Γ(e)表示x∈V ars(e)Γ(x),用 E表示异常终止。
接下来,我们使用表1中的约束来实例化图7中的规则,并提出一组用于弱 跟踪(即污点追踪)、可观测跟踪和完全跟踪(即无敏感升级 [5])的动态监控 器。这些监控器采用failstop策略,在执行可能不安全的语句时异常终止程序 (参见 E的规则)。注意,异常终止不会产生任何可观测事件,它被视为一种进 度通道,类似于非终止。我们用I E,m P表示从初始状态(E, m)、初始安全 环境 Γ和初始栈 ⊥开始执行受监控程序 P的过程,其中 I ∈{WS, OS, F S}。
受监控的执行可能会通过将不安全的执行转变为异常终止来改变原始程序 的语义。为了描述监控语义,我们将第2.4节中的安全条件实例化为插桩执行的 语义,并在记法上略作滥用,用I | =E,m P表示在插桩语义下 P的一次执行。然 后我们证明,在插桩执行下运行的任何程序,即 I E,m P,,满足安全条件, 即I | =E,m P。
弱跟踪
弱跟踪是一种动态机制,用于防止从较高级别的安全级别源到较低级 别的安全级别汇的显式流。弱跟踪允许通过隐式流发生泄露。表1的第二列给 出了典型的污点分析为我们的语言所实施的约束集。
表1。 图7中监控器的约束7
| Rule | Weak | Observable | Full |
|---|---|---|---|
| φasgT | tt | tt | pc Γ(x) |
| φasgF | ff | ff | pc Γ(x) |
| φoutT | Γ(e) | Γ(e) pc | Γ(e) pc |
| φoutF | Γ(e) | Γ(e) pc | Γ(e) pc |
| φinT | tt | pc | pc |
| φinF | ff | pc′ | pc′ |
| φend | tt | pc= :: pc | pc= :: pc |
| f /φwh | 真 | ′= pc Γ(e) pc ′= ′:: pc | ′= pcΓ(e) pc ′= ′:: pc |
φi
由于该分析忽略了所有隐 式流, pc栈是冗余的,我们在 监控器执行过程中从不更新它。 出于同样的原因,我们对条件 语句和循环的规则不施加任何 附加条件。规则 S-Assign 将 右侧表达式的安全级别传播到 左侧变量,以跟踪潜在的显式 流。 而规则 S-Assign-F永远不会适用。规则 S-Out确保只有来自较低级别的直接流 会影响给定的输出级别。如果约束未被满足,程序将异常终止(参见 S-Out-F)。
为了说明弱跟踪监视器,考虑图3中的程序。最初,安全环境 Γ将标签 L 分配给变量 l1和 l2,将标签 H分配给变量 h。执行第(1)行后,安全环境
136 M. 巴留 等人 Γ′不会改变,因为 pc= L 且对所有 n ∈Val都有 Γ(n) = L,因此Γ′(l1) = Γ′(l2) = L Γ(ff) = L(参见规则 S-Assign)。此外,第(2)行和第(3)行不会修改 Γ′(参见规则 S-IfTrue和 S-IfFalse)。最后,第(4)行的输出是允许的,因为 Γ(l2) = L L(参 见规则 S-Out)。事实上,该程序满足弱保密性(定义4),并且被弱跟踪所接受。
我们证明了在弱跟踪监视器下执行的任何程序,即 I= W S,都满足弱保密性。
定理1. WS E,m P ⇒ WSE,m P
可观测跟踪
可观测跟踪是一种动态安全机制,用于处理显式流和可观察的隐 式流。当在高安全上下文中更新的低安全变量随后被输出到低安全通道时,就 会发生可观察的隐式流。该条件证明了程序相对于仅知晓当前执行控制流路径 的攻击者的安全性。可观测跟踪具有一个吸引人的特性,即仅在具体程序执行 过程中传播变量的安全标签,而无需分析未执行分支中被修改的变量。这一点 非常显著,因为它避免了对具有反射等动态特性的语言通常所需的复杂静态分 析。此外,正如我们稍后讨论的,可观测跟踪比现有的执行机制(如NSU[5]或 宽松升级[6])更具宽松性。这种宽松性是以实施不同的安全条件为代价的,即 采用可观察保密性而非完全保密性。对于可信代码,可观察保密性可能已足够 用于发现非故意的安全漏洞。而对于恶意代码,我们提出了一种转换方法(第 4节4),使得可观测跟踪能够强制执行完全保密性,同时仍比完全跟踪更具宽 松性。
用于可观测跟踪的插桩语义(参见表1的第三列)通过以下方式加强了弱跟 踪的约束:(i)引入pc栈,以正确跟踪在高上下文中更新的变量的安全标签变 化;(ii)禁止在高上下文中从低安全通道输入;(iii)通过对低通道的输出施 加约束,禁止依赖于高上下文的低表达式输出。
再次考虑图3中在可观测跟踪的插桩语义下的程序。执行(1)
我们是一家人:关联信息流跟踪器13 7
Γ′不会改变,因为 pc= L 且对所有 n ∈Val都有 Γ(n) = L,因此Γ′(l1) = Γ′(l2) = L Γ(ff) = L(参见规则 S-Assign)。此外,第(2)行和第(3)行不会修改 Γ′(参见规则 S-IfTrue和 S-IfFalse)。最后,第(4)行的输出是允许的,因为 Γ(l2) = L L(参 见规则 S-Out)。事实上,该程序满足弱保密性(定义4),并且被弱跟踪所接受。
我们证明了在弱跟踪监视器下执行的任何程序,即 I= W S,都满足弱保密性。
定理1. WS E,m P ⇒ WSE,m P
可观测跟踪
可观测跟踪是一种动态安全机制,用于处理显式流和可观察的隐 式流。当在高安全上下文中更新的低安全变量随后被输出到低安全通道时,就 会发生可观察的隐式流。该条件证明了程序相对于仅知晓当前执行控制流路径 的攻击者的安全性。可观测跟踪具有一个吸引人的特性,即仅在具体程序执行 过程中传播变量的安全标签,而无需分析未执行分支中被修改的变量。这一点 非常显著,因为它避免了对具有反射等动态特性的语言通常所需的复杂静态分 析。此外,正如我们稍后讨论的,可观测跟踪比现有的执行机制(如NSU[5]或 宽松升级[6])更具宽松性。这种宽松性是以实施不同的安全条件为代价的,即 采用可观察保密性而非完全保密性。对于可信代码,可观察保密性可能已足够 用于发现非故意的安全漏洞。而对于恶意代码,我们提出了一种转换方法(第 4节4),使得可观测跟踪能够强制执行完全保密性,同时仍比完全跟踪更具宽 松性。
用于可观测跟踪的插桩语义(参见表1的第三列)通过以下方式加强了弱跟 踪的约束:(i)引入pc栈,以正确跟踪在高上下文中更新的变量的安全标签变 化;(ii)禁止在高上下文中从低安全通道输入;(iii)通过对低通道的输出施 加约束,禁止依赖于高上下文的低表达式输出。
再次考虑图3中在可观测跟踪的插桩语义下的程序。执行(1)中的赋值后, 变量 l1和l2具有安全级别L。如果 h为真,则在(2)中的第一个条件语句之后, 变量 l1具有安全级别H(参见 S-IfTrue规则)。因此,(3)中第二个条件语句 的守卫为假,我们执行否则分支。变量 l2的安全级别仍为L,因此(4)中在L通 道上的输出是允许的(参见 S-Out规则)。否则,如果 h为假,则执行否则 分支,且 l1具有安全级别L。第二个条件语句不会改变l2的安全级别,尽管执行 了则分支。事实上,该守卫仅依赖于级别L的变量,即 l1,因此 l2的安全级别 仍为L,后续输出被允许。该程序实际上满足可观察保密性。
我们证明了在可观测跟踪监控器下执行的任何程序,即 I= OS,都满足可观察保 密性。
我们是一家人:关联信息流跟踪器13 7
定理2. OS E,m P ⇒操作系统E,m P
完全跟踪
完全跟踪,最广为人知的形式是无敏感升级[5,58],可防止从高安全 级别的源到低安全级别汇的显式和(可观测或隐藏的)隐式流。这是通过禁止 在高上下文中更改变量的安全标签来实现的(与可观测跟踪所采用的策略相反)。
虽然该策略对完全保密是可靠的,但它会错误地中止任何在高安全上下文中更 新低安全级别变量的程序,即使该变量从未输出到低通道。这令人遗憾,因为 它拒绝了那些仅将敏感数据用于内部计算而从不将其发送到低通道的安全程序。
完全跟踪的语义为可观测跟踪规则增加了额外的约束(参见表1的第四列)。特别是, 规则 S-Assign仅允许在低安全上下文中进行低赋值,即每当 pc Γ(x)时。
再次考虑图3中的程序以及完全跟踪语义。与之前一样,初始时 Γ(l1) = Γ(l2)= L,且 Γ(h)=H。如果 h的值为真,则执行第一个条件语句的 then分支,并由于在高上下文中发生低赋值而停止程序。这是完全跟踪的一种 合理行为,因为原始程序不满足完全保密性。然而,完全跟踪也会停止任何包 含(2)中条件语句的安全程序。例如,如果我们把(4)中的输出语句替换为 out(L,1) 或 out(H l2),所得程序显然满足完全保密性。但只要 h为真,完全 跟踪就会错误地停止程序。
我们证明,在完全跟踪监控器下执行的任何程序,即 I= F S,都满足完全保密性。
定理3. FS E,m P ⇒ FSE,m P
4 分阶段信息流控制
两个主要因素阻碍了动态信息流控制在实际中的采用:实现困难和宽松性不足。
为了在运行时正确更新程序计数器栈,可观测和完全跟踪需要了解程序的控制 流图。这一要求对于非结构化、高度优化或混淆的代码(例如交付给终端用户 的代码)来说是不现实的(参见第1节)。相比之下,弱跟踪忽略控制流图,仅 考虑显式语句。因此,其执行更为宽松且更容易实现。
在完整版本中 [14],我们提出了一种分阶段分析方法,首先应用轻量级程 序变换,将隐式流转换为显式流,从而将实施可观察和完全保密的任务委托给 弱跟踪器。具体而言,我们以保持语义的方式将程序计数器栈内联到源代码中, 引入虚假依赖,使弱跟踪器能够捕获潜在的可观察和/或隐藏的隐式流。该变换 对底层安全策略完全透明,因此适用于第1节所设想的场景。
138 M. 巴留 等人 表2.宽松性
| Program Γ(h) = H, Γ(l) = Γ(k) = L 且 h=真 | Weak | Full | PU | OT | |
|---|---|---|---|---|---|
| P0 | l:=真 ;如果 h则 {l:= h};输出(L l) | − | − | − | − |
| P1 | 如果 h则 l:=真 | + | − | + | + |
| P2 | 如果 h则 l:=真;如果 l则 跳过 | + | − | − | + |
| P3 | l:=真 ; k:=真 ;如果 h则 {l:=假}; 如果 l则 {k:=假};输出(L,1) | + | − | − | + |
| P4如果 h则 输出(L, 1)否则 输出(L,1) | + | − | − | − | |
| P5 | l:=真 ; k:=真 ;如果 h则 {l:=假}; 如果 l则 {k:=假};输出(L k) | + | ✗ | ✗ | + |
健全性与宽松性。 我们使用表2中的示例来说明现有动态跟踪器的健全性和宽松性。
除了程序 P5之外,所有程序 都满足完全保密的安全要求。我们 在图8中总结了安全条件(实线椭圆) 与执行机制(虚线椭圆)之间的关 系。安全条件之间是不可比较的, 这一点由表2中的程序 P0、 P4和 P5 表明。此外,跟踪器所接受的安全 程序集合之间存在严格的包含关系 (参见表2)。
定理4。 FT E,m P ⇒ OT E,m P ⇒ WT E,m P
表格2展现了最先进的纯动态跟踪器的宽松性。所有跟踪器都考虑了显式 流,然而,如程序P0所示,由于近似处理,它们可能不够精确(参见“−”)。
完全跟踪会拒绝 P1 ,即NSU [5],,而程序P2会被宽松升级[6],拒绝,尽管 它们均未执行任何输出操作。 P3通过隐藏的隐式流将高安全级布尔变量 h的 值编码到变量 k的最终值中,但 k从未被输出。可观测跟踪(第6和第7列)正 确地接受了该程序,从而减少了其他跟踪器可能报告的误报数量。 P0和 P4由 于过度近似,将被大多数跟踪器拒绝。可以说,像 P0和 P4这样的程序模式不 太可能被使用,并且对于可信代码,可以通过代码转换等方式进行修复。
这些考虑为将可观测跟踪用作一种宽容的纯动态安全测试机制提供了有力依据。
然而,程序
我们是一家人:关联信息流跟踪器13 9
仍可能通过隐藏的隐式流泄露。该不安全程序 P5将被NSU和宽松升级正确拒 绝(参见“”),而可观测跟踪会正确接受它。
5 实现与评估
实现
我们的工具是基于Soot框架 [54]构建的一个原型,并使用一种中间字 节码语言 Jimple[54],来实现第3节中提出的静态转换。我们在完整版本中对 Jimple进行了描述,并讨论了高级语言特性 [14]。我们为安卓应用程序实现了 代码转换。插装后的应用程序随后通过TaintDroid运行 [24]。该实现的代码已 在线提供 [14]。总体而言,由于采用了Jimple作为中间语言以及变换的模块化 设计,静态转换的实现非常直接。这表明与复杂的信息流跟踪器相比,该方法 确实是轻量级的。
用例:计步器
为了评估我们的方法,我们将所提出的实现在一个来自流行的 F‐Droid仓库的开源计步应用[41]上进行应用。默认情况下,该应用不执行网络 输出。为了检查是否能够正确检测非法信息流,我们在多个场景中添加了网络 通信。我们在此部分给出这些示例的简化形式,以抽象出与安卓传感器查询相 关的特定问题;完整的示例请参见实现的源代码[14]。
使用统计: 计步应用程序可能希望向开发者报告使用信息。然而,用户可 能不希望将实际的步数报告给开发者。通过跟踪可观察的隐式流,在低安全级 别上下文中报告使用信息不会产生误报。但是,在高上下文中披露实际步数或 报告应用程序在某一天被使用将会引发错误(图9)。
降级发送平均速度: 该应用程序还可以将平均速度发送到服务器,以便与 其他用户进行比较。然而,实际的步数仍然不应被披露。我们实现了一种 如[14]中所述的where式降密策略。
位置信息: 为了向用户展示更详细的信息,我们还扩展了应用程序,加入了基 本的位置跟踪功能,以便显示每个城市中的步数等信息。由于位置信息是敏感 的,我们的转换确保了不会通过显式或可观察的隐式流泄露任何关于用户坐标 的信息。然后,我们修改了
140 M. 巴留 等
程序,使其通过图3中所示的隐藏的隐式流泄露位置信息。同样,我们的交叉复制 转换确保了此类泄露被阻止。
Use Case: JSFlow
现有的信息流工具(例如JSFlow [30],)可以轻松修改 为实施可观察保密性,而非非干涉。对于JSFlow的最新版本1.1,仅需注释掉少 量4行代码即可更改为实施可观察保密性。
关于JSFlow [31]中值敏感性的研究指出了由于无敏感升级策略导致的精 度问题,例如在(x:= 1;if h then x:= 2 else skip; out(L,1))这样的例子 中。像JSFlow这样的标准信息流监控器会阻止该程序,以避免在秘密上下文 C中升级 x的标签,即使 x在程序后续执行中从未被输出。然而,修改后的 JSFlow若实施可观察保密性,则会接受该程序。
6 相关工作
参考基于语言的信息流安全[44]和污点追踪[47],的综述,我们仅讨论最密切相关 的工作。
信息流策略
与非干涉性相对比,[28], Volpano [57]提出了弱保密性,这是一种 用于污点追踪的安全条件。Schoepe 等人通过显式保密性[45]对弱保密性进行了 推广,并使用分面值[46]来实施该条件。我们的工作探讨了可观察保密性作为中间 地带。与弱保密性和非干涉性类似,可观察保密性不是一种迹性质。
多位作者研究了基于知识的条件 [3,4,9,10]。我们通过探讨攻击者对程序代 码的视角来区分策略,特别是与阿萨罗夫和钟 [2], 提出的forgetful攻击者相关 的内容,尽管确切的关系仍有待进一步研究。虽然现实中的隐式流很重要 [33,42],,但它们也可能出现在可信代码中 [34,35]。通过追踪显式和可观察的 隐式流,我们在污点追踪方面提高了安全门槛。
分阶段分析
我们的工作受到贝林格[15],的启发,其提供了使用污点追踪来 执行非干涉策略的形式化论证。贝林格还利用交叉复制技术来考虑隐藏的隐式 流。相比之下,我们依据相对于未插桩语义的弱保密性等语义条件,证明了执 行机制的健全性。另一方面,贝林格引入了路径追踪的概念以处理终止敏感非 干涉,并通过在Coq中的形式化(针对一种无输入/输出的命令式语言)支持该 理论。我们的工作区分了恶意代码和可信代码,为这两种场景提供了安全条件 和执行机制(包括一个原型实现)。
Rifle [53]通过程序插桩和污点追踪中的交叉复制来处理隐式流,并为显式流 和隐式流分别设置污点寄存器。其重点在于效率,因为健全性仅被非正式地论证。
与贝林格的工作类似,我们的工作为Rifle思想的有用性提供了形式化且实际的证据。
我们是一家人:关联信息流追踪器 141
其他研究利用交叉复制技术来实施非干涉策略。勒盖尔尼克[36]在用于非 干涉的混合监控器中使用了交叉复制,并将可观察的隐式流和隐藏的隐式流分 别称为隐式流和显式间接流。楚格等人[19]提出了一种处理JavaScript代码的 混合方法。该方法首先静态计算一个动态残差,然后在第二阶段于运行时进行 检查。针对可信代码,康等人[34]研究了特定的(称为culprit)隐式流。Bao etal.[11]识别出严格控制依赖,并通过实验评估其在污点追踪中的有效性。这 些工作阐明了可观察的隐式流的优势。
动态执行与内联
芬顿 [26]研究了纯动态信息流监控器。奥斯汀和弗拉纳根 [5]利用无敏感升级 [58]来对JavaScript实施非干涉,并提出宽松升级 [6] 以提高精度。我们指出NSU可能过于严格,并提出了针对恶意代码和可信代码 提高精度的解决方案。丘德诺夫和瑙曼 [18]以及马加津纽斯等人 [37]提出了 信息流监控器内联,将NSU策略集成到程序代码中。别洛娃和雷兹克[17]综述 了近期关于(信息流)监控器内联的研究工作。我们的变换可被视为对动态监 控器的一种轻量级内联,适用于(可观测和/或隐藏的)隐式流。鲁索和萨贝尔 菲尔德 [43]讨论了静态与动态流敏感分析之间的权衡。我们借鉴了他们的流敏 感监控器。
安全多执行[22]和分面值[7]强制执行非干涉:程序会根据安全级别的数 量执行相应次数,每个级别的输出由对应的执行过程计算得出。巴尔特等人[12] 研究了用于实现安全多执行的程序变换。这些技术在构造上是安全的,并提供 高精度。然而,它们需要在不同安全级别之间进行同步,并且在具有副作用和 输入/输出的语言中面临挑战。此外,它们可能会修改语义并引入崩溃,从而难 以检测攻击。相比之下,我们专注于故障停止监控,以完全宽松性为代价来避 免此类缺陷。
静态与混合执行
Volpano 等人 [56]通过安全类型系统形式化了丹宁的静态 分析 [21]相对于非干涉的健全性,并通过进一步的工作引入高级特性进行了扩 展 [44]。亨特和桑兹 [32]提出了流敏感安全类型。我们的工作利用动态分析 来执行类似的安全策略。其他信息流分析方法包括程序逻辑 [10,13],模型检测 [8,23],抽象解释 [27]以及定理证明 [20,40]。尽管这些方法比安全类型系统更 精确,但在可扩展性方面可能面临诸多挑战。
混合执行结合了静态和动态分析。勒盖尔尼克[36]提出了支持顺序和并发 语言的混合流敏感机制。文卡塔克里斯南等人[55]提出了一种针对包含过程的 语言的混合监控器,并证明其可实现非干涉。什罗夫等人[48]提出了一种针对 具有堆的语言、采用动态依赖分析的监控器。特里普等人[52]通过结合静态分 析和动态部分求值,研究了JavaScript代码的混合安全。摩尔和钟[39]
142 M. 巴留 等
提出两种针对混合监控器的优化方法以提高效率:选择性跟踪变量安全级别和 针对具有动态内存的语言的内存抽象。混合方法使用静态分析来近似计算未被 特定执行所覆盖的程序路径的计算效果。对于具有复杂特性的语言(例如反射 和非结构化控制流),这可能具有挑战性。我们通过针对隐式流(基本上是布 尔表达式)执行静态分析,并将复杂特性的解析委托给动态污点跟踪器,从而 实现平衡。
移动应用安全
在移动应用领域,存在大量关于信息流分析的研究工作。这些 分析大多仅考虑显式流。这是由于语言特性的复杂性和高度动态的生命周期所 致,然而,对于潜在的恶意代码和可信代码而言,隐式流同样重要。我们在图 1中的方案使现有工作能够以灵活的方式提供更强的安全保障。TaintDroid [24]是一种动态污点跟踪器,旨在捕捉Android应用中的隐私泄露问题。在我 们的实现中,使用TaintDroid作为动态组件。大多数静态分析工作针对弱保密 性[1,29]来验证安全性。尽管在提高精度方面取得了显著进展,但误报率仍然较 高[29]。
恩斯特等人 [25] 提出了针对高完整性应用商店的信息流需求的协同验证。 开发者与应用商店合作以降低整体验证成本。具体而言,开发者提供带有信息 流规范(安全类型)的源代码,而应用商店则验证其正确性。我们的模型是互 补的,相比之下以用户为中心,允许更灵活的策略并减轻开发者的负担。
7 结论
我们提出了一个信息流跟踪器框架,使我们能够关联从污点追踪到信息流控制 的一系列执行机制。通过区分恶意代码和可信代码,并权衡健全性与宽松性之 间的取舍,我们探索了其中的中间路径。我们采用分阶段方式部署该框架,将 轻量级静态分析与动态污点追踪相结合,从而构想出一种安全应用商店架构。 我们还通过原型实现对这一方法进行了实验。
未来的工作包括动态安全策略以及来自F‐Droid仓库的案例研究。尽管当 前框架允许用户端使用参数化策略,我们推测,由于静态转换对底层策略透明, 因此可以扩展以处理丰富的动态安全策略。
988

被折叠的 条评论
为什么被折叠?



