将SELinux的安全特性加入安卓

来源:互联网 发布:网络教育不用考试 编辑:程序博客网 时间:2024/05/16 18:33

焦虑的娃温馨提示:焦虑的娃的专题博客“关注安卓安全”的第二篇竟还是一篇译文,呵呵。最近花了好多时间看了许多SEAndroid方面的资料,发现有一篇英文文章讲的很好,简明扼要的概括了SELinux是如何应用到android系统里面去的。简单介绍了强制访问控制的概念,如何将SELinux添加到安卓,如何定制SELinux安全策略,如何验证你所定制的SELinux安全策略,同时给出了好几个应用案例。总而言之,这篇文章可以引领你了解SEAndroid的大概情况,有抛砖引玉的效果。请看到文章的朋友们批评指正,有什么问题就给焦虑的娃留言或者发邮件,我会虚心并且热情地和你探讨。

本文章由焦虑的娃编写,欢迎转载,但是——转载请注明出处。

文章链接:http://blog.csdn.net/obsessive_compulsive/article/details/19567035

作者:焦虑的娃  邮箱:seandroidresearch@163.com

英文原文:http://source.android.com/devices/tech/security/se-linux.html

==========================================================================

 

将SELinux的安全特性加入安卓

 

引言

 

作为安卓安全模型的一部分,安卓使用了SELinux的访问控制策略。SELinux的出现大幅度增强了安卓的安全性。此外,还有许多公司和组织也为增强安卓的安全性做出了不懈的努力。你可以在android.googlesource.com站点看到所有安卓源代码及其贡献者。

在SELinux的强力保护下,安卓可以更好的对应用程序数据和系统日志进行访问控制。这不仅减轻了恶意程序对系统的影响力,而且保护了用户不受移动设备上隐藏的恶意代码所攻击。

在安卓的最新版本中,SELinux是以“enforcing mode”形式存在的,并且具有一套相应的默认的安全策略,该策略遍布于整个安卓开源工程。

在“enforcingmode”中,非法的操作是被禁止的,并且所有的攻击行为会被Linux内核记录下来,保存在dmesg里面。针对SELinux在安卓中的应用,安卓设备生产商应该做的是:在将SELinux的状态置为enforcing mode之前,不断收集SELinux所报出的系统错误信息,并依此改善自己的软件,更新安卓系统的SELinux策略。

 

背景

 

注意,安卓可以更新自己的SELinux策略版本,并允许SELinux基于domain来设置到底处于那一种模式(disable、permissive、enforcing)。

例如,如果你让自己开发的所有应用程序运行在一个单一的domain中,你可以设置该domain为permissive,然后设置其他其他功能和他们的domains为enforcing状态。

Domains通过密钥(用于对应用进行签名)和应用程序建立关联。这是在SELinux策略源文件*.te的顶部进行设置的。

安卓遵循此模型: 即将各个不同应用程序分别孤立在一个单一的domain中。基于此,只有root domain和 root级别的进程(例如initd、installd和vold)现在被设置为enforcing模式。

普通应用程序的domain仍然保持在permissive模式,这一举动允许对应用程序的SELinux策略做进一步的评估,阻止没必要的系统错误。但是,恶意程序仍可以在root domain激发一个行为(该行为是不被允许的),随之而来的便是导致应用程序的崩溃。

因此,设备生产商应该保留安卓默认的设置,并且只让root domain 保持enforcing状态,直到完全解决了dmesg中报告的问题。

也就是说,设备生产商可能需要不断改善他们的SELinux的策略实现来满足对操作系统的诸多添加和修改所带来的问题。参见:客制化段落。

 

强制访问控制

 

与安卓的其他安全措施协同工作,安卓的访问控制策略很大程度上限制了目前脆弱的设备和账户受到潜在的破坏。安卓的DAC(自主访问控制)和MAC(强制访问控制)可以提供一个强有力的方法,确保你的软件运行在最低权限级别。这不仅削弱了攻击行为对系统的影响,而且减小了恶意进程重写系统数据,甚至偷窃数据的可能性。

从安卓4.3版本开始,在传统DAC的基础上,SELinux为安卓提供了MAC保护伞。举例说明:有些进程必须以root身份运行来向原始块设备写入数据。我们知道,在传统的基于DAC的Linux环境中,如果root用户被攻陷,那么拥有root权限的进程则可以向任何原始快设备中写入数据。然而,现在安卓有了SELinux的帮助,SELinux可以用来标记这些设备,以实现即使获取到root权限,该进程也仅可以向策略中指定的设备写入数据,其他的设备想都别想。

参见“用例段落”中更多地例子,来理解SELinux是如何抵御威胁的。

 

如何把SELinux特性加入到安卓中

 

安卓中的SELinux目前是以enforcing mode存在的,而不是disable状态或者permissive状态(permissive状态可以作为指引,使测试和开发变得更加容易)。

尽管enforcingmode是全局的,请牢记着这种情况在基于单个domain的这种情况可是例外,就像在应用domain中一样。

SEAndroid拥有一切SELinux的特征。你只需要把最新的安卓内核整合进来,然后把~platform/external/sepolicy(你可以在该路径下找到许多例子)路径下的文件包含进来:

l  https://android.googlesource.com/kernel/common/

l  https://android.googlesource.com/platform/external/sepolicy/

这些文件在编译时会包含SELinux内核安全策略并兼容以前老版本的安卓操作系统。

把这些文件放置在/device/manufacturer/device-name/sepolicy路径下。

然后修改BoardConfig.mk文件(该文件位于包含sepolicy的子路径),来引用sepolicy策略文件,方法如下:

BOARD_SEPOLICY_DIRS:= \

        <root>/device/manufacturer/device-name/sepolicy

BOARD_SEPOLICY_UNION:= \

        genfs_contexts \ 

        file_contexts \ 

        sepolicy.te

在重新编译整个工程之后,你的设备就具备SELinux功能了。

你现在可以定制自己的SELinux策略,来适应你自己对安卓系统的修改(这将会在定制段落说明),或者验证你的当前存在的配置(后面有介绍)。

 

客制化

 

一旦你在安卓系统中整合了这些基础功能,并且彻底地分析了结果,你就可以在你自己的策略设置中添加条目来对安卓系统做一些客制化的工作。

当然,你添加的这些策略必须满足安卓兼容性程序的需求,并且,你不能移除默认的SELinux设置。

设备生产商不应该移除现存的安卓安全设置。否则可能会破坏SELinux在安卓上的部署,破坏受SELinux保护的应用的良好安全环境。这也包含了第三方应用(需要改进以变得更易用和更具操作性)。在具备SELinux功能的设备上,如要应用正常工作,则绝不允许自身有任何修改。

参见内核安全特征段落,该段提供了安卓兼容性定义文档(针对特殊要求):

http://source.android.com/compatibility/index.html

SELinux使用白名单的方法,这意味着SELinux会向某些特殊的角色赋予特权。

因为目前安卓默认的SELinux策略已经支持整个AOSP,OEM实际上不需要再去修改SELinux的默认设置。但是,如果OEM做了SELinux策略的修改和定制,就应该特别注意,切勿破坏现存的应用。这里给出一些建议吧:

1.      使用最新的安卓内核;

2.      采用最少特权原则;

3.      你只管处理你自己对安卓系统的添加和修改,其他的不用管。因为默认的安全策略会自动在AOSP的代码库中产生作用。也就是说,你对安卓原生态系统添加了什么内容,你就写你所添加内容对应的策略配置就OK了,其他的就别管了,否则可能会出问题(这时我的理解);

4.      把软件组件划分为不同的模块,由不同的模块分别执行单一的任务;

5.      建立SELinux策略,该策略可以将这些任务从无关的功能中孤立开来;

6.      将这些策略写入*.te(SELinux策略文件的扩展)文件中,该文件位于: /device/manufacturer/device-name/sepolicy;

7.      发布你定制的SELinux版本时,先让其处在permissive mode中(因为还没经过测试噢);

8.      分析结果,并不断改善策略配置。

一旦将自己的SELinux定制内容整合到安卓系统中,OEM安卓开发过程应该包含一个步骤来确认SELinux的兼容性。在一个理想的软件开发过程中,SELinux策略只有在软件模型改变时才会发生改变,而不是在实际的实现时(不是很懂)。

当设备生产商开始定制SELinux时,应该首先仔细审核对安卓的添加内容。如果他们添加了一个组件,用以实现一个新的功能,设备生产商必须确保该组件满足安卓安全策略的要求,同时也要(在开启为enforcement之前)满足OEM精心开发的相关安全策略。

为了阻止非必要的问题发生,最好能够做到足够的宽泛和兼容,而不是过于限制和不兼容,结果是破坏了的设备功能。相反的,设备生产商对安卓系统的改变将会使其他人受益,它们应该提供一个针对默认SELinux策略的修改补丁。如果该补丁可以直接打给默认安全策略,那么设备生产商将不再需要在每个安卓发布版中做相应的修改。

 

应用案例

 

下面有几个关于攻击安卓的例子,用来讲解如何精心开发自己的软件和制定相关的SELinux策略:

l  软链接 —— 因为软链接看似一个文件,他们经常被作为一个文件来读取。这可能会导致系统被攻击。例如,一些特权组件(例如init)改变某个文件的权限,有时被过分的暴漏。

攻击者这时可能会将这些公开的文件用软链接替换掉,用自己写的代码来代替,当然,自己写的代码可能会允许攻击者修改任意文件。但是如果你知道自己写的应用程序肯定不会和软链接打交道,那你就可以使用SELinux来阻止这一切的发生。

l  系统文件 —— 我们都知道系统文件只有系统服务可以修改,但是,因为netd、init和vold都是(Native service)以root身份运行的,他们可以访问这些系统文件。所以,如果netd被攻陷,它就可以破坏这些系统文件,这势必会危害系统服务本身。

有了SELinux,你就可以标记这些文件为原生的系统数据文件。因此,可以读和写这些文件的domain只有系统服务。即使netd被攻陷,它也不能切换domains到系统服务的domain。尽管它具有root权限,也无法访问这些系统文件。

l  应用数据 —— 另外一个例子是,一些进程必须以root身份运行,但是我们又不想让其访问应用数据。SELinux在这里就非常有用了,因为可以做声明来阻止某进程去访问应用数据,例如某一个和应用数据无关的domain,就可以被阻止,而不能去访问internet。

l  设置文件属性 —— 有一些命令,例如chmod和chown等,我们可以为他们确定一个文件集,在这个文件集里,相关的domain可以执行文件属性设置命令。对于任何该文件集外部的文件,一旦文件属性变化,则被阻止,即使是root也没门儿。所以,一个应用程序可以针对标记过的app_data_files,执行chmod或者chown,但是不能直接对未经标记的shell_data_files或者system_data_files进行文件属性设置。

 

相关文件

 

如果你决定定制SELinux策略的配置,那么本段可以帮助你。参见客制化段落的各个步骤。

建议设备生产商从默认的安卓SELinux策略开始修改,对默认的策略做最小的修改,来解决自己对安卓系统的修改和添加所带来的安全问题。现存的安卓SELinux策略文件在~platform/external/sepolicy目录下。

安卓对SELinux策略版本进行升级,这允许SELinux模式可以在某个domain设置为permissive(而在其他domain设置为enforcing)。例如,如果你在一个单一的domain中运行所有你的应用程序,你可以将该domain设置为permissive,然后将所有其他的功能和他们的domains设置为enforcement。domains通过密钥(用于对应用程序进行签名)和应用发生关联。这些设置是在SELinux策略原文件*.te中进行配置的。

如果你要定制SELinux,那么你必须创建或者编辑下面这些文件:

l  新的SELinux策略原文件(*.te) —— 位于<root>/device/manufacturer/device-name/sepolicy路径。这些文件定义domains和他们的labels。在编译过程中新的策略文件和现存的策略文件会链接起来,成为一个SELinux内核策略文件。

重要提示:不要修改app.te文件,这个文件是AOSP提供的。如果你修改了,那么你就破坏了第三方应用的安全环境,将他们置于危险的境地。

l  修改BoardConfig.mk文件 —— 该文件位于<device-name>路径下,该路径包含了sepolicy子路径。这个文件必须得倒合适的修改,用于引用sepolicy子路径。

l  修改file_contexts文件 —— 该文件位于sepolicy子路径。这个文件用于给文件打标签,并且在用户空间进行管理。因为你生成了新的策略,所以你要修改这个文件来引用他们。为了让新的file_contexts产生作用,你必须在一个将再次打上标签的文件中运行restorecon。

sepolicy路径中剩下的其他文件要么是自动生成的,要么应该保持原封不动。策略文件的形式是:allow,domain和context,为一个动作集合:

l  Allow —— 给角色权限来在指定的domain中实现具体动作,该动作在context中做具体描述

l  Domain —— domain代表了规则的范围,并且在内核里面可以转化为一个安全的ID(SID)。

l  Context —— 规则的标识符,这会被转换为一个内核中的整数

举一个例子吧:

allow appdomainapp_data_file:filerw_file_perms;

这条语句说明,一个应用程序被允许读取或者写入打app_data_file标签的文件。在编译的过程中,这些重写文件和已有的SELinux设置链接起来,成为一个单独的安全策略。这些重写的文件加到基础安全策略里面比从现有安全策略里面除去来得更好。

一旦新的策略文件和BoardConfig.mk更新的比较到位,新的策略配置将会自动在设备上产生作用。

 

验证你当前SELinux的配置

 

安卓强力推荐OEM去测试他们的整个SELinux实现方案。当设备生产商实现自己的SELinux策略时,应该首先发布他们自己的策略在permissive mode状态下。如果可能,可以把新的策略应用到设备列表的测试池。

一旦予以应用,一定要确保SELinux是跑在正确的mode上,这可以通过下面命令实现:

getenforce

这将会打印全局SELinuxmode:或者disabled,或者enforcing或者permissive。请注意,这个命令仅仅显示全局SELinux mode。如果要为每个domain决定SELinux mode,你必须检查相应的文件。

然后检查错误。错误码是以事件日志的方式发送并存储在内核dmesg中,并且你在本地设备上可以看见它。设备生产商应该在设备商的demsg中认真审查SELinux的输出,并在发布为permissive模式之前,精炼和改善SELinux的策略配置,并最终使之成为enforcing mode。

利用这个内核dmesg,设备生产商可以轻易的确认系统用户或者系统组件什么时候违反了SELinux策略。设备生产商此时可以处理并解决掉这个恶意的行为:或者对软件做一些修改,或者对SELinux策略做一些修改,或者全都修改。

特别的,这些日志消息暗示着什么样的角色和什么样的进程会在策略加强下失败并且为什么会失败。下面是一个例子:

denied  { connectto } for  pid=2671 comm="ping"path="/dev/socket/dnsproxyd"

scontext=u:r:shell:s0tcontext=u:r:netd:s0 tclass=unix_stream_socket

解释说明:

l  上面的 { connectto } 代表到底做了什么操作。它和最后的tclass(unix_stream_socket)一起,粗略的告诉你“之前到底在谁身上发生了什么事情”。在这种情况下,我们可以大概了解到,一些什么东西曾试图链接一个unix stream socket。

l  Scontext(u:r:shell:s0)告诉你这个曾发生的行为是在什么上下文。这里,我们可以看到有一个什么东西曾以shell的身份运行。

l  tcontext (u:r:netd:s0)告诉你曾发生过的行为的最终目标是谁。这里,我们可以看到目标是netd所拥有unix_stream_socket。

l  上面的comm="ping" 给你一个额外的提示:在denial日志产生的时候,当时正在运行什么。这里,我们就不多解释了:ping。

安卓会不断把这些信息拿过来仔细分析,并且改善默认的安全策略,以实现对SELinux策略稍加定制,就可以跑在更多地不同的安卓设备上。因为有这种机制,OEM必须让他们自己的修改内容去适应安卓操作系统。

然后,通过安卓兼容性测试(CTS),运行SELinux处于激活状态(使能状态)的设备。如前所述,任何新的策略仍然必须满足安卓兼容程序要求。

最后,如果可能的话,在内部开启为enforcement(在雇员的设备上),目的是提高失败的能见度。确定任何用户问题,并解决它们。

 

帮助

 

安卓强力推荐设备生产商工作在他们的安卓账户管理器上,以便分析SELinux的检测结果并改善策略配置。

随着时间的推移,安卓将会支持越来越多的设备生产商在SELinux策略里面的添加内容。要获得更多地信息,请发邮件至:security@android.com

 

 

焦虑的娃温馨提示:本译文将会随着笔者对安卓安全的认识的变化而不断更新,敬请关注。此外,对于技术博客,本人是比较倾向于原创性的,所以以后会经常出系列性的原创博客出来(专门针对安卓安全),敬请期待。

 

0 0
原创粉丝点击