杨 嘉,曾庆凯
(1.南京大学 计算机软件新技术国家重点实验室,江苏 南京210093;2.南京大学 计算机科学与技术系,江苏 南京210093)
2001年NSA发布了安全增强的Linux系统――SELinux[1]。在SELinux策略中起主导作用的是TE模型,即系统实体根据其安全特性被标记为相应的类型(type)。策略以类型为对象设定访问规则。但是由于SELinux的类型空间庞大,出现不安全访问授权的可能性很大。并且目前在Linux系统中有30-40个应用程序需要相应的访问权限来处理不同敏感等级的数据。直接信任这些程序可能造成安全隐患,尤其是在程序被攻破的情况下,攻击者有足够的权限造成机密数据泄露。相反的,直接移除相应的权限又会影响程序的可用性。
针对上述情况,本文提出了基于信息流分析的权限控制方法。本文将程序执行过程中是否已访问高敏感等级的数据作为当前运行时权限的一个决定因素。同时,针对访问控制只能在系统与程序的接口层实施系统资源管理的局限性,本文采用静态分析的方法,跟踪输入数据在程序内部的流动情况,一直到达数据的输出接口,由此定位到访问权限实际产生效用的程序点。通过插装代码标记的方式实现对程序权限的准确控制。
本文主要有以下几个方面的贡献:提出了一种基于策略信息流的主体安全状态划分方法,对主体权限的管理提供了更精确的控制;采用静态分析的方法,跟踪程序内部的信息流,确定了可能造成信息泄露的程序点,减少了状态切换的次数;修改SELinux安全服务器,实现了运行时动态切换进程安全状态的功能。
表1中列出了主要的策略规则种类和其在策略文件中的数量。类型定义规则申明了系统中所有的实体类型,主体的类型又称作域(Domain)。该规则还支持对类型添加别名,并设定其所在的属性。属性是若干类型构成的集合,集合内的所有类型有共同的性质,这对理解类型的安全特性有很大帮助。例如,domain就是通过属性规则来定义的,以及node_type属性表示网络节点和主机的类型等。访问向量是TE策略的主体部分,它规定了source_t域中的主体是否对target_t类型的客体有permission的权限。class表示客体的种类,permission是定义在class上的操作,class和permission反应了访问规则在系统中能控制的操作语义。SELinux中默认的子进程继承父进程的域,新文件继承父目录的类型,类型迁移定义了主客体类型动态变化的规则。当class为process时表示域迁移规则,source_t下的进程通过执行target_t类型的可执行文件,可转移到new_t域。SELinux的策略只支持在装载新的可执行程序时改变进程主体的域,这种机制忽略了信息流因素对于主体权限的影响,这也是本文工作的改进内容之一。类似的,当class为其它种类时,source_t下的进程在target_t类型的目录下生成是新文件将是new_t类型。
表1 策略语法和统计
表1中第3列显示了相应类型的规则在policy.24版本的targeted策略中的数量。随着应用程序的增加和拓展,策略文件的规模和复杂性呈上升的趋势。举例来说,Linux的日志转储程序logrotate,需要对自己的配置文件进行访问,完成对不同类型的日志文件的处理,记录执行状态,同时还有压缩和电邮指定日志的功能。logrotate_t的访问规则向量就有374条,另有134条类型转换规则。这些策略规则直接定义了底层资源访问的规则,缺乏对高抽象层次安全性质的表述和验证方法。配置策略很可能包含错误的访问授权。
根据范畴不同,信息流分为两种:一种是系统实体之间的信息流,从策略配置中提取,作为影响主体权限的附加因素,用来标记进程主体当前的安全状态;另一种是程序内部的信息流,从编程语言的语义中提取,这一部分的信息流体现系统资源在程序内部的使用和传递。两者的结合构建了完整的信息流图景:程序内部的信息流信息弥补了访问控制的盲点,避免了盲目信任应用程序;系统实体之间的信息流则补充了静态分析技术固有的缺陷,附加的影响因素使得对主体的授权更加准确。
资源的访问本质上就具有信息流动的特征,所以系统的许多安全需求可以通过策略信息流的方式来表达。访问规则中的某些permission就隐含着主客体之间的信息流动。如果该permission引发了从source_t到target_t的信息流,就将其划归modPerm类的权限,例如,file类资源的write权限;反之,划归obsPerm类,例如,file资源上的read权限。
在机密性保护方面,“高敏感等级实体中的信息不能流向低敏感等级的实体”是满足BLP模型的基本要求。该安全需求转换成策略信息流的形式就是:
SecFlow={<o,o’> | obs Perm(s,o)∧mod Perm(s,o’)∧SL(o)≤SL(o’)},其中SL(e)表示系统实体e的安全等级。
在更高的抽象层次上分析系统的安全特性,安全管理员不需要详细了解每一个类型含义。只要对高敏感客体集合(HighType)和不可信客体集合(LowType)进行规定,通过策略信息流分析就能确定引起非法信息流动的相关主体和权限。
来自HighType客体的信息经过一次或者以上的流动传递可能到达LowType的客体中,造成信息泄露,图1显示了这样一条信息流。这里定义从app_t向LowType输出信息的Perm2为不安全的访问权限Punsafe。针对这种情况管理员可以直接将有威胁的权限移除,这样做会影响程序的正常功能。本文认为进程主体在其生命周期内并不一定会使用所有静态配置的权限,也就是说进出app_t的信息流不一定存在必然的关联。本质上,是否能够满足安全要求的关键是权限所引起的信息流动而不是权限本身。因此,将主体的权限依据信息流的因素划分成不同的状态,并在运行时由信息流触发状态转换是一个合理的选择。为此构建了一个新的域,app_sec_t,将其权限设定为:
Perm(app_sec_t)=Perm(app_t)-Punsafe
Role(app_sec_t)=Role(app_t)
Attribute(app_sec_t)=Attribute(app_t)
新生成的域app_sec_t,角色分配规则以及属性都与app_t保持一致。区别是它失去了向低等级客体输出信息的能力。在app_sec_t中运行的进程主体不可能造成HighType客体中信息的泄露,故称之为主体的安全状态。
图1 非法信息流路径
机密性保护的基本方法是监控敏感信息的流动。静态分析方法不需要执行程序,从源代码中抽取语法和语义信息,通过对程序意图的理解,完成追踪和鉴别数据的来源、传递及其使用的任务。因此,本文采用该方法来跟踪程序内部的信息流动。
信息流是信息从一个实体流向另一实体的有效途径,本文将信息流定义为R,是信息流识别对象集W及其上的二元关系→。
本文定义R=(W,→),且→={<src,dest> |src,dest∈W}。
程序对象集W包括程序中的变量集、常量集,以及函数调用和返回语句等在内的程序行为实体集合。→则由信息流源对象src和目的对象dest组成,多条信息流可以构成信息流集合IFs。根据程序控制结构和语法特征,总结有以下的信息流生成规则。
(1)赋值语句:
v0=v1;IFs={<v1,v0>}(v0,v1都不是指针变量)
v0=v1;IFs={<v1,v0>,<v0,v1> }(v0,v1都是指针变量)
v0= & v1;IFs={<v1,v0>,<v0,v1> }
v0=a[i1]...[in];IFs={<a[i1]...[in],v0>,…,<i1,v0>,<in,v0> }(a为N维数组元素)
v0=⊙(v1,…,vN);IFs={<v1,v0>,…,<vN,v0> }(⊙是N元运算符)
(2)函数调用语句:
fun(v1,…,vN);IFs={<v1,fun|1>,…,<vN,fun|N>}(fun是调用的函数名,表示调用点实参到形参的信息流。参数是指针则添加<fun|1,v1>到IFs)
(3)返回语句:
return v0;IFs={<v0,*> }(*是当前函数的调用者)
(4)控制语句:
if(v0==k){v1=…}else{v2=…}IFs={<v0,v1>,<v0,v2>}
switch(v0){casei:{v1=…}……default:{vN=…}}IFs={<v0,v1>,…,<v0,vN> }
while(v0==k){v1=…}IFs={<v0,v1>}
上述规则定义了由程序语义引起的原子信息流。在计算信息流传递的时,加入输入输出接口作为src和dest的筛选条件,就可以得到以输入信息为导向的程序切片。输出接口将使用相应的授权来完成操作。
上一节提到的安全状态划分,可以有效的从程序整体的层次上阻塞敏感信息向低等级客体的通道。但是在程序中,并不是每一处系统操作的执行都会使用有安全隐患的权限。运用静态分析的目的就是筛选出有潜在威胁的输出操作。在这些程序插装标记提示安全服务器切换程序的安全状态,达到限制程序权限的效果。这样在程序代码的子集上实施的权限控制,一方面可以尽可能减少出于安全考虑对程序功能的影响,另一方面可以减少安全状态切换的次数,降低运行时的开销。
在SELinux环境下,进程生命周期内只在装载新的执行镜像时发生域迁移。本文为了更加准确的控制主体的权限,在SELinux安全服务器中实现了状态转换机制。同一个主体在不同的安全状态下拥有不同的访问权限。两个条件可以触发安全状态的转变:一是主体读取了高敏感等级的信息,二是主体试图向客体输出信息。前者发生在相应的访问规则触发之时,后者通过静态分析插装的标记触发。整个程序运行周期的安全上下文状态可以由图2来表示。我们将程序的运行划分成3个安全状态。
图2 安全状态转换
(1)常规状态(app_t):程序运行的初始状态,拥有初始策略配置的所有权限。
(2)中间状态(app_mid_t):当程序接收了敏感数据之后进入该状态,其拥有和常规状态同样的权限。该状态只是为了标记程序是否具有高敏感等级的信息,并不对权限进行限制。
(3)安全状态(app_sec_t):当程序试图执行数据输出操作时,切换到该状态执行。该状态可以阻止主体向低敏感等级的客体输出数据,但不会限制其它操作。此处的状态切换用插装在程序中的标记触发。
本文基于上一节的方法实现了程序运行环境,工作流如图3所示。
图3 原型系统工作流程
策略分析模块对modPerm和obsPerm操作的设定,引用了开源工具apol[2]中的配置。该模块读入策略文件policy.conf,生成原子信息流矩阵。从HighType出发,用深度优先的策略搜索到达LowType的非法信息流路径。本文将中间传递次数上限设定为最多途径2个主体域节点,因为通过两个以上恶意程序之间配合完成信息泄露是比较难实现的。在传递路径上造成第二次信息流动的权限即为Punsafe。然后模块自动生成app_mid_t和app_sec_t两个域和相应的授权,添加到策略文件中。
静态分析在gcc编译器的优化框架下实现,利用了gcc生成的语法树、调用图等结构完成过程内和过程间的信息流分析。输入输出接口的设定主要依据系统操作的语义。例如,read从指定的文件读取数据到程序内存空间的缓冲区中,mmap可以直接将文件的内容映射到程序的地址的空间,故被定义为输入接口。本文也对相关操作的执行进行了跟踪。read和mmap在执行时确实会触发关于对文件读取的访问控制检查。
程序的安全状态对应与程序的3个域,程序被装载时由依照原来的策略规则进入app_t域运行。本文的工作在安全决策函数avc_has_perm()中添加了对源数据类型的检查,来判断是否有HighType类型的信息流入,而程序中插装的标记通过添加新的系统调用实现从应用程序向内核的通信。
本文设定用户登录日志/var/log/wtmp文件的类型wtmp_t为Hightype,同时设定node_type,port_type,etc_t等具有公共安全属性的类型为LowType。经过分析发现Linux下的日志转储程序(logrotate_t)通过上百条策略规则的配置获得了大量的访问权限,其中一部分是由程序自身的功能需求决定的。该程序需要根绝配置文件(etc_t),处理多种服务程序产生的日志(wtmp_t等),同时具备执行脚本和电邮日志的功能。因为程序需要访问的客体类型众多,所以其策略配置也相对复杂。下面是一部分策略片段。
allow logrotate_t etc_t:file{read write open}
allow logrotate wtmp_t:file{read write open execute link unlink}
allow logrotate_t logrotate_tmp_t:file{read write open link unlink}
allow logrotate_t node_t:node{tcp_recv tcp_send}
allow logrotate_t logrotate_mail_t:process transition
可以看到经过logrotate_t的传递有从wtmp_t流向etc_t,node_t的信息流。因为logrotate不需要和socket进行通信,所以本文将于node_t相关的访问权限直接移除。然后定义logrotate_sec_t类型作为信息流安全的域,并赋予其受限制的访问权限。
对logrotate源程序实施静态信息流分析,本文找出了表2所示的输入和输出接口之间的关系。表2中的后两项,程序在执行了dup2将打开的文件描述符重定位到标准输入之后,又通过execlp()调用了其它程序,例如,调用mailx来将mailInput的内容发送到指定的邮箱地址。本文选择在这一步插装标记来阻止进程主体的域迁移。首先,以只读的方式打开一个文件会产生从客体到主体的信息流,因为在进程空间的文件描述符也具有其对应文件的安全属性;其次,将域迁移权限从logrotate_sec_t中去除限制了敏感信息的扩散,也避免了对更多的程序进行分析和插装。
表2 logrotate程序静态分析结果
用信息流来表示主客体的安全属性,学术界已经有一些这方面的研究。UMIP[3]是一种具有高可用性的访问控制模型,它的主要目的是为了保护系统的完整性免受网络攻击。从网络下载的服务和应用程序会带有相应的标签,从而限制这些程序在本地运行的权限。IFEDAC[4-5]将 MAC的信息流属性结合在DAC的访问控制上,用 “污染源”的概念来表示主客体的完整性等级。既保证了安全性,又保留了DAC的易用性。本文借鉴了这方面工作的思想,在SELinux的框架上实现了准确有效的机密性保护机制。
此外,单纯的访问控制技术不能完全满足系统安全性要求,B.Hicks等人[6]的工作也都试图利用静态分析技术将程序和系统的策略统一起来。他们利用类型安全语言Jif[7]能够实施信息流策略的特性,首先验证程序策略与系统策略的一致性[8],再通过特殊的系统服务以用户请求的安全等级启动应用程序。该方法的缺陷是必须在类型安全语言上开展工作,而且由于程序和系统策略的差异,在策略一致性验证方面存在很大的困难。而本文的静态分析工作是在通用语言上进行的,具有更好的适用性。
对于程序运行是权限的划分可以有两种方式实现,一种是直接的代码切片,另一种就是变换程序的安全属性。D.Brumley等人的工作属于前者,Privtrans工具[10]可以根据开发人员提供的敏感变量的标签,通过静态分析其传播路径,将程序切分成两个部分在不同的进程以及权限下运行。这种方法可以达到很好的隔离效果,但是需要对程序语义有深入的了解。而本文中对于输入输出接口的定义来自标准库函数,具有更好的可用性。U.Shankar等人构建的满足CW-Lite模型[10]的系统采用的后面一种方式,但是其对于需要特殊权限的过滤接口(filtering interface)的设定同样面临前者的问题。
SELinux作为一种应用广泛的强制访问控制模型,能够提供灵活的,细粒度的策略配置。但其策略的复杂性也容易导致不安全的授权,对系统造成威胁。本文提出了以信息流为基础的方法,能够分析不合理的策略配置,定位到引起非法信息流的特权,将主体的访问授权划分成不同的安全状态。针对存在安全隐患的程序,本文采用静态分析的方法,在程序的数据输出点插装标记防止非法的信息流输出。策略分析和程序分析两者结合从时间和空间上对程序的权限提供了更加准确的控制。
[1]Zhai G,Ma W,Tian M,et al.Design and implementation of a tool for analyzing SELinux secure policy[C]//Proceedings of ICIS,New York,NY,USA,ACM,2009:446-451.
[2]Tresys.Setools—policy analysis tools for SELinux[EB/OL].[2012-04-20].http://oss.tresys.com/projects/setools.
[3]Li N,Mao Z,Chen H.Usable mandatory integrity protection for operating systems[C]//Proceedings of IEEE Symposium on Security and Privacy.Washington,DC,USA:IEEE Computer Society,2007:164-178.
[4]Mao Z,Li N,Chen H,Jiang X.Combining discretionary policy with mandatory information flow in operating systems[J].ACM Trans Inf Syst Secur,2011,3(14):24-24.
[5]Mao Z,Li N,Chen H,et al.Trojan horse resistant discretionary access control[C]//Proceedings of SACMAT.New York,NY,USA:ACM,2009:237-246.
[6]Hicks B,Rueda S,Jaeger T,et al.From trusted to secure:Building and executing applications that enforce system security[C]//Proceedings of USENIX Annual Technical Conference.Berkeley,CA,USA:USENIX Association,2007:205-218.
[7]Myers A C,Nystrom N,Zheng L,et al.Jif:Java+information flow[EB/OL].[2012-04-15].http://www.cs.cornell.edu/jif/.
[8]Rueda S,King D,Jaeger T.Verifying compliance of trusted programs[C]//Proceedings of USENIX Security Symposium.Berkeley,CA,USA:USENIX Association,2008:321-334.
[9]Bapat D,Butler K,McDaniel P.Towards automated privilege separation[C]//Lecture Notes in Computer Science 4812:Proceedings of the 3rd International Conference on Information Systems Security,2007:272-276.
[10]Shankar U,Jaeger T,Sailer R.Toward automated information-flow integrity verification for security-critical applications[C]//Proceedings of 13th Annual Network and Distributed System Security Symposium.San Diego,California:Internet Society,2006.