Pre
相信大家都学过不少关于计算机安全的课程和知识, 大家多多少少对各种各样的攻击方式有一定的了解。但是当谈及到底什么样的程序可以被认为是安全的时候, 这都不会是一个容易回答的问题。 说出几条例如内存安全, 权限不会泄漏之类的规则不难,但是什么是安全规则却很难回答。毕竟这种本质论多少有点形而上学的意思。 我记得我在这个学校也学习过一学期的计算机安全的课程,但是唯一的印象也只剩下了各种攻击和内存排布之类的东西。 但是如果想要验证程序是安全的首先我们必须回答这个问题。 这里说的验证当然是严谨的(rigorous), 并不简单的经验主义的使用测试来说明程序的安全性, 而是使用形式化方法严格证明程序安全。
计算机科学家们在70年代末[1] 对这个问题进行了不少的探索, 最后在1982年, J.A. Goguen 和J Meseguer发布了一篇非常重要的论文, Secruity Policies and Secruity Models. 在这篇文章中他们第一次提出了不相干(noniterference)的概念,并抽象了一个语义模型(使用抽象代数类型), 在这个模型下,大量的安全规则可以被形式化的描述了。
Noninterference
从比较高的层次上来讲noninterference的概念非常简单,如果我们去掉程序中拥有高执行权限的用户和他相关的行为,从低权限的用户看来系统不会发生任何的变化。但是既然是形式化的描述我们还是要严谨的来说明。
security model
模型必然是为了描述某种特定的系统来使得。 noninterference主要希望描述的对象是动态的capability 系统, 在这种系统中,有高权限用户和低权限的用户, 他们都可以在自己权限下使用对应的指令,于此同时,系统也存在权限变更指令,也就是在程序运行中,可以动态的给予不同的用户不同的权限。如果一个指令满足权限那么系统状态会发生对应的变化, 如果不满足,系统将保持当前状态(非常有model checking的味道)。
但是遗憾的是我们这里讨论的程序都是确定程序,也就是说对于不同用户的指令输入,输出总是相同的, 因而整个系统也就成了一个有限状态机。
系统可以有如下的形式化定义:
- U: user用户
- S: state程序运行中的状态
- SC: 状态转移指令
- Out: 程序输出
- Capt: Capability table: 权限表,角色对应的指令权限
- CC: Capability Command权限变更指令
- out: 输出函数 ,表示程序在某一状态下,某一用户在其权限下观察到的程序输出
- do: 状态转移函数,表示程序在某一用户在其权限下使用命令程序状态发生的的变化
- cdo: 权限转移函数,和上面类似,不过是权限指令造成的权限变化(权限指令并不由用户输入)
- t0,s0: 初始状态和初始权限
其中我们把的子集叫做能力(ability),简称Ab. 然后我们可以给出Capt 的类型
也就是说权限表是记录不同用户所对应能力的这么一种抽象数据结构。
最后我们可以使用ML风格的伪代码来描述我们整个状态机的转移函数(同时包含了权限状态和控制状态的变化):
其中第三个参数可能比较误导,原文说指令可以看作一个字符串w, 而这个输入中包括了多组的用户和输入元组对,这里的第三行的点是字符串连接函数。这个类型显然是对不上的。原因主要是因为这个文章的年代比较久,82年这个时候甚至还没有ML语言之类的类型系统, 如果用现代一点的方法严谨的说就是第三个参数的类型应该为。其中点是cons.而第三句的后半部分也是懂得都懂,默认科里化加上构造。
增加记号:
这里我们可以很明显的看出整个状态机所描述的是一个确定性(deterministic)系统。这其实是一个限制很大条件,因为我们生活中的大多数程序都不是确定性的。
定义删除操作(purge)
G,A,分别是用户集合和命令集合,删除包含G中用户的, 删除包含A中命令的元组对,,表示删除在上面这个list中包含的G,A所有相关用户命令
noninterference rule
在定义了模型之后我们可以来形式化的阐述不相干性了。
一组用户G 如果满足
那么G用户和其他用户G‘不相干。记做:
对于一种能力A, 一组用户G 如果满足
能力A与用户组G中的用户不相干。记做:
对于一种能力A,一组用户G 如果满足
那么G中拥有能力A的用户和剩下的用户G'不相干。记做:
在后续的很多论文中,上面的模型一般被称为GMNI模型.
security policy
很多安全策略都可以使用上面说的模型来描述,。看俩例子吧:
isolation: -G |: G, -U |: U
channel control: -A,G |: G' and -A,G' | G
不相干模型的局限性和后续工作
首先显然不相干模型是一种有限状态机的模型,他在对应nondeterminitic的情况时是不适用的,也就意味着我们对于系统的抽象是非常粗糙的。McLean 的工作扩展了这个模型使得它可以适用与不确定性的情况。但是随着人们对计算机安全的认识,很多的规则其实还是无法用这个来表示的。比如我们看到GMNI这种思路本质还是在规定什么样的行为是“不好”的,这种也被称为safety性质,但是只有safety是不够的,很多时候我们也需要去告诉系统什么样的行为是安全的或者说是"好的",这也被称为liveness性质。这在这种模型中就完全无法描述, 所以后续又出现了大量各种各样的安全模型。
在2010年,Micheal Clarkson[3]提出了一种大一统论,他称其为超性质(hyperproperties),这种理论试图在拓扑上对世界上所有的安全模型进行描述和统一,并且期待模型检查技术能够给出比较好的解决方案,但是目前对于超性质相关的实际model checker还没有太多的进展。
然而我们永远不可能拥有完美的模型。模型复杂化带来的问题1是验证的难度大大提升了, 但是还有一个本质的问题无法解决,那就是侧信道攻击,即使你的软件在逻辑上完美无缺,对于某些物理世界的观察依然可能导致信息泄露,一个非常好的例子就是有一种攻击可以通过服务返回数据的CPU计算时间的周期变化来推测服务器中某些密钥数据。
我在雪城安全课上最大的收获是,我的老师上课讲了这么一个故事。 如何在所有知情人都守口如瓶的情况下知道一个房间里的灯亮过没有。最简单的方法就是摸摸那个灯泡烫不烫。这其中没有任何信息流上的泄露但是侧信道却能告诉我们很多。
不过不管怎么样安全模型加上很多形式化方法确实在这两年有了很多的应用,比如之前很有名的seL4操作系统内核,就是一个成功使用GMNI模型的例子。
Reference
[1] R. J. Feiertag, K. N. Levitt, and L. Robinson. 1977. Proving multilevel security of a system design. SIGOPS Oper. Syst. Rev. 11, 5 (November 1977), 57–65. DOI:https://doi.org/10.1145/1067625.806547
[2] J. A. Goguen and J. Meseguer, "Security Policies and Security Models," 1982 IEEE Symposium on Security and Privacy, Oakland, CA, USA, 1982, pp. 11-11, doi: 10.1109/SP.1982.10014.
[3]Michael R. Clarkson and Fred B. Schneider. 2010. Hyperproperties. J. Comput. Secur. 18, 6 (September 2010), 1157–1210.