写点什么

Linux 内核安全子系统简介(上)

作者:nn-30
  • 2023-11-13
    广东
  • 本文字数:4423 字

    阅读完需:约 15 分钟

Linux内核安全子系统简介(上)

内容来源:deepin社区

作者:zhanglei


Linux 内核中包含了多个安全子系统,它们之间相互独立又有着千丝万缕的联系,导致人们对它们往往有一种雾里看花的感觉。在这篇文章里,我们对 Linux 内核中的安全子系统做一个简单的分析,算是一个入门。


Linux 内核的安全子系统大概包括下面几个:

  • 访问控制(AC,Access Control),它是最常见也是最重要的安全机制。AC 主要是要管理 Linux 下的一个主体(如进程)到底对一个客体(如文件)是否能采取某些访问操作(如读取文件内容)。访问控制又进一步包括:

  • 自主访问控制(DAC),包括访问控制列表(ACL)以及权能模型(POSIX capabilities)

  • 强制访问控制(MAC),包括很多人都听说过的 SELinux 与 AppArmor 都是 MAC

  • 用户验证(Authentication),它主要指的是如何识别一个真实的、物理的人是 Linux 系统中的一个注册账号

  • 资源隔离,将进程之间的资源(包括文件、进程、网络等)隔离开,使得应用程序运行互不影响

  • 配额限制,对软件进行资源配额限制,例如限定某软件或者某些软件最多占用多少资源等

  • 系统沙箱,限定应用程序是否能调用某些系统调用,或者以某种参数调用某些系统调用

  • 可信计算,对系统的完整性进行校验,例如从硬件校验 bootloader 的完整性,从 bootloader 校验内核的完整性等,一般的完整性校验都是通过预先对原内容进行 hash 计算得到一个散列值存储在安全区,再在正式使用数据之前校验散列值是否有变化的方式来实现的

  • 安全审计,在系统运行过程中记录安全日志,在安全事件发生后,通过安全审计可以追查当时的场景,定位原因,修补漏洞,以避免再次发生类似的安全问题

  • 透明加密,对数据进行多层次的透明加密,以保证在没有得到密钥的情况下,被加密保护的数据无法被恢复出明文,而且在得到正确密钥的情况下,应用程序能像访问明文数据一样访问密文数据

  • 网络防护,即对通过网络进出本系统的数据进行安全检查


下面,我们稍微展开说一下各个安全子系统。


访问控制

在 Linux 操作系统下,自主访问控制指的是文件的属主(owner)可以设置文件被系统中所有用户访问的权限。


常见的 DAC 设置命令是chmod,所有用户被划分为三类,即属主(u,user),与属主同组的用户(g,group)以及其它用户(o,others),访问权限则包括读(r,read)、写(w,write)与执行(x,execute),由于用户与访问权限都是三个,因此一般会使用三个八进制的数字表示权限。


例如将文件 file1 的权限设置为属主可读可写,同组用户与其他用户可读,则可以运行chmod 0644 file1,其中 6 即为二进制的 100 + 二进制的 10,表示对属主可读与可写,4 即为二进制的 100,分别表示对同组可读,以及对其它用户可读。


上述文件的权限被保存在文件的 inode 中,进程的安全凭证则是在内核对应的task_structstruct cred *real_credstruct cred *cred中,在打开文件时内核会对 inode 中的文件权限与进程中的安全凭证进行对比与 DAC 检查。这种权限设置方法是从 Unix 沿袭而来的访问控制机制。


由于传统的 DAC 设置用户分类粒度太粗,因此为了提供细粒度的读写执行的访问控制,Linux 又引入了访问控制列表,可以针对某个用户或者用户组设置单独的访问权限,使用的命令是setfaclgetfacl,对应的设置经过编码保存在文件的扩展属性system.posix_acl_access中。


在 Linux 系统下有一个系统管理员账号,即 root。它是一个 bug 级的存在,普通用户设置的读写权限对于 root 来说是没有作用的,root 可以跳过 DAC 直接读取、删除、修改普通用户的任何文件。也就是说一旦一个人拥有了 root 权限,他实际上就可以在 Linux 下为所欲为了。而有些功能既需要访问系统级的资源,从而需要有 root 权限,又需要被普通用户使用,因此*nix 又发明了 setuid,用来将某个属主为 root 的可执行程序设置为普通用户可用,在普通用户使用此程序时拥有 root 的权限,退出此程序时则恢复普通用户的权限。此类程序包括需要创建原始套接字的ping、需要修改/etc/shadow文件等的passwd等。


这种设置带来的安全风险很大,一旦此类程序中可能存在的安全漏洞被利用,攻击者即可对整个系统为所欲为。因此,Linux 又遵循 POSIX 的权能模型(capabilities),将传统的 root 权限分解为了多个子权限,例如审计、修改属主、发信号、网络管理、原始套接字等。这样,某个原本需要 setuid 权限的程序可以通过setcap等命令为程序设置相应的最小权能,即使相应的程序被攻击者利用获得了特权,攻击者能获得的也只有很小的一部分特权,无法为所欲为。


不过,DAC 最大的问题是资源的访问权限控制都是由资源的属主来设置的,而没有安全意识的用户往往不知道应该如何设置访问权限以保证整体安全,毕竟,安全漏洞往往是出在最短板上的。因此,对于 DAC,它最大的问题是“不怕神一样的对手,就怕猪一样的队友”。


为了解决猪队友的问题,强制访问控制(MAC)被提上了日程。强制访问控制定义了一整套安全访问控制的体系,系统管理员(或安全管理员)能够通过实施 MAC,限定远比 DAC 更细致更广泛的访问控制。例如在 MAC 下,我们可以限定即使都是由 root 启动,但是只有由 init 启动的 nginx 才能绑定 80 端口,但是从 bash 启动的 nginx 则只能绑定 8080 端口。


最著名的 MAC 是美国国家安全局(NSA)开发的 SELinux,它也是使用最为广泛的 MAC,在 Android 中也使用到了它。SELinux 提供了安全策略,例如基于类型的 TE(Type Enforcement)、基于密级的 MLS(MultiLevel Security),以及同密级下不同分类的 MCS(MultiCategory Security)等,此外,通过角色与用户的划分,SELinux 还提供了基于角色的访问控制(RBAC)。


不过 SELinux 虽然可以避免猪队友的问题,但是它的细粒度管理方式对管理员来说实在是太麻烦了。缺省情况下它提供了几个用户、十几个角色、上千个分类、数千个类型、上万个类型转换,要正确理解、使用甚至修改这些规则,对于任何管理员来说都是极大的负担,而且新的软件仍然在源源不断地开发出来,旧有的软件在持续升级与复杂化,这使得事后访问控制的软件兼容负担日益加重。


用户验证

Linux 在用户验证上提供了一种灵活的机制,那就是 PAM(可插拔认证模块)。


PAM 提供了一个所有服务的中心验证机制,适用于普通登录、ssh 登录等需要进行身份认证的系统中。在 Linux 操作系统中存在多个 PAM 模块,例如负责使用用户名密码对用户进行认证的pam_unix.so模块,负责拒绝用户认证的pam_deny.so模块,负责通过用户认证的pam_permit.so模块等。


一般通过文本方式通过本地进入系统使用的程序为 login,通过网络远程进入系统使用的程序为 sshd,通过图形界面方式通过本地进入系统使用的程序为 lightdm。上述的每个负责鉴别用户与登录的程序都将通过 PAM 机制对用户进行认证。


login 等程序并不进行实质的 Linux 用户认证,具体的认证方式都是通过 Linux 系统管理员对 PAM 模块的配置完成的。例如最常见的配置是使用上述的pam_unix.so,要求用户输入用户名与密码进行认证。但是系统管理员也可以配置pam_fprintd要求用户在使用 login 或者 lightdm 登录的时候通过指纹进行用户认证,而这些认证方式对使用了 PAM 的 login 等程序而言,都是透明的。


使用了 PAM 的优点在于,一方面,将用户鉴别功能从每个应用软件中独立出来,单独进行模块化设计,实现和维护;另一方面,为这些鉴别模块建立标准 API,以便各应用程序能方便的使用它们提供的各种功能;同时,鉴别机制对其上层用户(包括应用程序和最终用户)是透明的,便于使用与维护。


PAM 采用了分层的模块式开发,提供了四种类型的模块:

  • 认证管理(auth),负责进行用户认证,这也是 PAM 模块的主要功能,它可以提供不同的认证方式,对用户进行组合认证

  • 账号管理(account),负责管理用户账户的有效性,例如账户是否过期了,账户是否可以允许访问对应的服务等

  • 会话管理(session),负责在用户建立会话之前或者销毁会话之后处理工作,例如记录审计日志,或者挂载/卸载用户的家目录等

  • 口令管理(password),负责更新用户认证的机制,例如常见的要求输入确认密码的场景,以及要求密码复杂度的场景


PAM 的配置文件通常在/etc/pam.d/下。


模块将按照在配置文件中列出的顺序被调用,这取决于每个条目允许的控制标记(control flag)的值。常见的控制标记值包括:

  • required:所有 required 模块都必须运行到底,如果中间产生了失败,则失败信息将会被记录下来,到最后返回第一个失败的信息,如果都成功了,则返回成功

  • sufficient:如果标记为 sufficient 的模块返回成功,并且先前没有 required 或 sufficient 模块失败,则忽略剩余的其余模块并直接返回认证成功。

  • optional:如果 PAM 模块中没有一个模块是 required 的,并且没有任何一个 sufficient 模块成功,则至少要有一个 optional 模块返回成功才算成功


实际上,上述的控制标记值只是一个简化的标记而已,在 PAM 配置时可以配置数十个参数,例如 success、open_err、new_authtok_reqd、default、ignore 等,相应的值包括 ok、ignore、bad、done、die 等。上述的 required 实际上就是[success=ok new_authtok_reqd=ok ignore=ignore default=bad]的缩写,而 sufficient 则是[success=done new_authtok_reqd=done default=ignore]的缩写。


下面是 login 程序使用到的 PAM 配置文件(文件名为/etc/pam.d/login)的样例。

## The PAM configuration file for the Shadow `login' service#
auth optional pam_faildelay.so delay=3000000
auth [success=ok new_authtok_reqd=ok ignore=ignore user_unknown=bad default=die] pam_securetty.so
auth requisite pam_nologin.so
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close
session required pam_env.so readenv=1session required pam_env.so readenv=1 envfile=/etc/default/locale
@include common-auth
auth optional pam_group.so
session required pam_limits.so
session optional pam_lastlog.so
session optional pam_exec.so type=open_session stdout /bin/uname -snrvmsession optional pam_motd.so
session required pam_loginuid.so
@include common-account@include common-session@include common-password
复制代码


在上述配置文件中,以 #开始的每行文字是注释(已经删除了大部分),以 auth 开始的每行文字是认证相关的 PAM 模块及其配置,以 session 开始的每行文字是会话相关的 PAM 模块及其配置,而以 @include 开头的行则是将其它 PAM 配置文件的内容导入了本配置文件,这样可以提供一定的模块化与较好的可维护性。值得注意的是,这里的 PAM 配置文件都是自动生成的,里面的注释也比较详细,可以提供较好的手工修改与管理的基础。


当前 PAM 模块面临的最主要的问题是:

  • 传统 PAM 体系与各个模块是基于 console 的,对于图形界面支持仍需改进

  • 大量新型认证方式(如人脸识别、虹膜识别、指纹识别等)需要我们开发相应的 PAM 模块以提供支持


了解 deepin:deepin - 基于Linux的开源国产操作系统

了解 WHLUG:WHLUG – 深度科技社区

了解 deepin Meetup:deepin Meetup – 深度科技社区

用户头像

nn-30

关注

还未添加个人签名 2023-10-30 加入

还未添加个人简介

评论

发布
暂无评论
Linux内核安全子系统简介(上)_Linux_nn-30_InfoQ写作社区