SELinux 简介
系统管理员一般无法通过基于用户、组群和其它权限(称为 Discretionary Access Control,DAC)的标准访问策略生成全面、精细的安全策略。例如,限制特定应用程序只能查看日志文件,而同时允许其他应用程序在日志文件中添加新数据。
Security Enhanced Linux(SELinux)实施强制访问控制(MAC)。每个进程和系统资源都有一个特殊的安全性标签,称为 SELinux 上下文(context)。SELinux 上下文有时被称为 SELinux 标签,它是一个提取系统级别细节并专注于实体的安全属性的标识符。这不仅提供了在 SELinux 策略中引用对象的一个一致方法,而且消除了在其他身份识别系统中可能存在的模糊性。例如,某个文件可以在使用绑定挂载的系统中有多个有效的路径名称。
运行 SELinux 的好处
SELinux 提供以下优点:
- 所有进程和文件都被标记。SELinux 策略规则定义了进程如何与文件交互,以及进程如何相互交互。只有存在明确允许的 SELinux 策略规则时,才能允许访问。
- 精细访问控制。传统的 UNIX 通过用户的授权、基于 Linux 的用户和组进行控制。而 SELinux 的访问控制基于所有可用信息,如 SELinux 用户、角色、类型以及可选的安全级别。
- SELinux 策略由系统管理员进行定义,并在系统范围内强制执行。
- 改进了权限升级攻击的缓解方案。进程在域中运行,因此是相互分离的。SELinux 策略规则定义了如何处理访问文件和其它进程。如果某个进程被破坏,攻击者只能访问该进程的正常功能,而且只能访问已被配置为可以被该进程访问的文件。例如:如果 Apache HTTP 服务器被破坏,攻击者无法使用该进程读取用户主目录中的文件,除非添加或者配置了特定的 SELinux 策略规则允许这类访问。
- SELinux 可以用来强制实施数据机密性和完整性,同时保护进程不受不可信输入的影响。
SELinux 本身并不是:
- 防病毒软件
- 用来替换密码、防火墙和其它安全系统
- 多合一的安全解决方案
SELinux 旨在增强现有的安全解决方案,而不是替换它们。即使运行 SELinux,仍需要遵循好的安全实践,如保持软件更新、使用安全的密码、使用防火墙。
Red Hat Enterprise Linux 8 提供以下用于 SELinux 的软件包
策略: selinux-policy-targeted、selinux-policy-mls
工具: policycoreutils、policycoreutils-gui、libselinux-utils、policycoreutils-python-utils、setools-console、 checkpolicy
yum -y install policycoreutils libselinux-utils policycoreutils-python-utils setools-console checkpolicy policycoreutils-gui
更改 SELinux 状态和模式
SELinux 可使用三种模式之一运行:
enforcing(强制):Enforcing 模式是默认操作模式,在 enforcing 模式下 SELinux 可正常运行,并在整个系统中强制实施载入的安全策略。
permissive(宽容):permissive 模式中,系统会象 enforcing 模式一样加载安全策略,包括标记对象并在日志中记录访问拒绝条目,但它并不会拒绝任何操作。不建议在生产环境系统中使用 permissive 模式,但 permissive 模式对 SELinux 策略开发和调试很有帮助。
disabled(禁用):强烈建议不要使用禁用(disabled)模式。它不仅会使系统避免强制使用 SELinux 策略,还会避免为任何持久对象(如文件)添加标签,这使得在以后启用 SELinux 非常困难。
开启selinux的方式:
在您选择的文本编辑器中打开 /etc/selinux/config 文件,例如:
# vi /etc/selinux/config
# This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. # See also: # https://docs.fedoraproject.org/en-US/quick-docs/getting-started-with-selinux/#getting-started-with-selinux-selinux-states-and-modes # # NOTE: In earlier Fedora kernel builds, SELINUX=disabled would also # fully disable SELinux during boot. If you need a system with SELinux # fully disabled instead of SELinux running with no policy loaded, you # need to pass selinux=0 to the kernel command line. You can use grubby # to persistently set the bootloader to boot with selinux=0: # # grubby --update-kernel ALL --args selinux=0 # # To revert back to SELinux enabled: # # grubby --update-kernel ALL --remove-args selinux # SELINUX=enforcing # SELINUXTYPE= can take one of these three values: # targeted - Targeted processes are protected, # minimum - Modification of targeted policy. Only selected processes are protected. # mls - Multi Level Security protection. SELINUXTYPE=targeted
或者可通过getenforce、setenforce 0、setenforce 1进行临时的切换。
SELinux安全上下文
SELinux 管理过程中,进程是否可以正确地访问文件资源,取决于它们的安全上下文。进程和文件都有自己的安全上下文,SELinux 会为进程和文件添加安全信息标签,比如 SELinux 用户、角色、类型、类别等,当运行 SELinux 后,所有这些信息都将作为访问控制的依据。
查看文件、目录、进程的安全上下文,执行命令如下:
ls -Z # 查看文件的安全上下文
ls -Zd /root # 查看目录的安全上下文
ps auxZ | grep sshd # 查看进程的安全上下文
只要进程和文件的安全上下文匹配,该进程就可以访问该文件资源。
安全上下文看起来比较复杂,它使用“:”分隔为 4 个字段,其实共有 5 个字段,只是最后一个“类别”字段是可选的,例如:
system_u:system_r:sshd_t:s0:[类别]
身份字段 :角色 :类型 :灵敏度:[类别]
身份字段(user):用于标识该数据被哪个身份所拥有,相当于权限中的用户身份。
seinfo -u ###列出SELinux中所有的身份(user)
角色(role):用来表示此数据是进程还是文件或目录。
常见的角色有以下两种:
object_r:代表该数据是文件或目录,这里的“_r”代表 role。
system_r:代表该数据是进程,这里的“_r”代表 role。
seinfo -r ###列出SELinux中所有的角色(role)
类型(type):类型字段是安全上下文中最重要的字段,进程是否可以访问文件,主要就是看进程的安全上下文类型字段是否和文件的安全上下文类型字段相匹配,如果匹配则可以访问。 注意,类型字段在文件或目录的安全上下文中被称作类型(type),但是在进程的安全上下文中被称作域(domain)。也就是说,在主体(Subject)的安全上下文中,这个字段被称为域;在目标(Object)的安全上下文中,这个字段被称为类型。域和类型需要匹配(进程的类型要和文件的类型相匹配),才能正确访问。
seinfo -t ###列出SELinux中所有的类型(type)
# 较多(4975)仅展示部分
灵敏度:灵敏度一般是用 s0、s1、s2 来命名的,数字代表灵敏度的分级。数值越大,代表灵敏度越高。
类别:类别字段不是必须有的,所以我们使用 ls 和 ps 命令查询的时候并没有看到类别字段。但是我们可以通过 seinfo 命令来查询:
seinfo -u -x
2.5 selinux的调试
我们通过调试apache的服务进行演示,通过修改apache的监听端口及网页目录产生关于selinux的错误。
grep -E "Listen|DocumentRoot" /etc/httpd/conf/httpd.conf
# 修改了默认端口80,改为了1211,并且把DocumentRoot 修改路径为/WEB
修改了Document 路径后,下面这部分需要手动同步添加,不然就算不开启SElinux也会出现“403 Forbidden”
# 修改后确保selinux是打开状态后,重启httpd服务,出现如下报错
SELinux 策略假设 httpd
在端口 80 上运行:(查看默认情况下http,在SElinux下所使用的端口)
sudo semanage port -l |grep http
增加端口1211到http服务相关提供端口
sudo semanage port -a -t http_port_t -p tcp 1211
httpd 服务启动成功
但是,访问网页内容却出现了一下信息
使用setroubleshoot-server 工具进行拍错 (测试未成功)
dnf install -y setroubleshoot-server
sealert -l "*" |more
SELinux is preventing /usr/sbin/httpd from getattr access on the file /WEB/index.html. ***** Plugin catchall_labels (83.8 confidence) suggests ******************* If you want to allow httpd to have getattr access on the index.html file Then you need to change the label on /WEB/index.html Do # semanage fcontext -a -t FILE_TYPE '/WEB/index.html' 中间大量类型信息省略... 中间大量类型信息省略... 中间大量类型信息省略... Then execute: restorecon -v '/WEB/index.html' ***** Plugin catchall (17.1 confidence) suggests ************************** If you believe that httpd should be allowed getattr access on the index.html file by default. Then you should report this as a bug. You can generate a local policy module to allow this access. Do allow this access for now by executing: # ausearch -c 'httpd' --raw | audit2allow -M my-httpd # semodule -X 300 -i my-httpd.pp Additional Information: Source Context system_u:system_r:httpd_t:s0 Target Context unconfined_u:object_r:default_t:s0 Target Objects /WEB/index.html [ file ] Source httpd Source Path /usr/sbin/httpd Port <Unknown> Host c9t1 Source RPM Packages httpd-2.4.51-8.el9.x86_64 Target RPM Packages SELinux Policy RPM selinux-policy-targeted-34.1.31-2.el9.noarch Local Policy RPM selinux-policy-targeted-34.1.31-2.el9.noarch Selinux Enabled True Policy Type targeted Enforcing Mode Enforcing Host Name c9t1 Platform Linux c9t1 5.14.0-85.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Wed May 4 13:10:42 UTC 2022 x86_64 x86_64 Alert Count 6 First Seen 2022-05-10 08:46:48 CST Last Seen 2022-05-10 08:57:31 CST Local ID 39af49a1-b3c7-42c0-85f6-7e65fda97d7b Raw Audit Messages type=AVC msg=audit(1652144251.562:1829): avc: denied { getattr } for pid=62576 comm="httpd" path="/WEB/index.html" dev="dm-0" ino=68847177 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=0 type=SYSCALL msg=audit(1652144251.562:1829): arch=x86_64 syscall=newfstatat success=no exit=EACCES a0=ffffff9c a1=7fa53003dd70 a2=7fa53616c830 a3=100 items=0 ppid=62569 pid=62576 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm=httpd exe=/usr/sbin/httpd subj=system_u:system_r:httpd_t:s0 key=(null) Hash: httpd,httpd_t,default_t,file,getattr
再次尝试查看httpd 的错误日志
sudo tail -F /var/log/httpd/error_log
使用 matchpathcon 工具比较标准 SELinux 类型和新路径,寻找区别:
matchpathcon /var/www/html /WEB
确实和默认的网页存储位置的SElinux配置信息不一致
方式一:
将新 /web 内容目录的 SELinux 类型改为默认 /var/www/html 目录的类型:
semanage fcontext -a -e /var/www/html /WEB matchpathcon /var/www/html /WEB /var/www/html system_u:object_r:httpd_sys_content_t:s0 /web system_u:object_r:httpd_sys_content_t:s0
方式二:
semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?"
或者
semanage fcontext -a -t httpd_sys_content_t "/WEB/*"
semanage fcontext -a -t httpd_sys_content_t "/WEB"
restorecon -Rv /web
sudo semanage fcontext -l |more # 确认添加成功
sestatus命令将显示SELinux启用状态
sestatus # sestatus命令将显示SELinux启用状态 -v # 使用选项-v可以显示在/etc/sestatus.conf文件中列出的文件和进程的SELinux上下文 -b # 可以显示布尔值的当前状态,如下所示在“ Policy booleans:”部分中显示所有参数的当前SELinux布尔值。
学习内容均参考Farmsec:http://book.fsec.io/101-%E5%9F%BA%E7%A1%80%E7%AF%87/101-B-linux%E6%9C%8D%E5%8A%A1/101-B9-selinux.html
额外参考内容:使用sestatus命令来查看SELinux的当前状态