一、概念引入:
DAC(Discretionary Access Control)
:自主访问控制。在这种模式下,决定一个资源是否能被访问的因素是对应用户是否有该资源的权限(读、写、执行)。只要访问这个资源的进程符合以上的条件就可以被访问。其中root 用户不受任何管制,系统上任何资源都可以无限制地访问。
MAC(Mandatory Access Control)
:强制访问控制。在这种模式下,决定一个资源是否能被访问的因素除了用户权限之外,还需要判断对应的进程是否同样拥有对该资源的访问权限。即使进程是以 root 身份运行的,也需要判断这个进程的类型以及允许访问的资源类型才能决定是否允许访问某个资源。
SELinux
(Security Enhanced Linux),也就是安全强化的 Linux,是由美国国家安全局(NSA)联合其他安全机构(比如 SCC 公司)共同开发的,旨在增强传统 Linux 操作系统的安全性,解决传统 Linux 系统中自主访问控制(DAC)系统中的各种权限问题(如 root 权限过高等)。
二、SElinux的三种工作模式:
Enforcing(1) #强制模式,将拦截服务的不合法请求。
Permissive(0) #警告模式,遇到服务越权访问时只发出警告而不强制拦截。
Disabled #关闭模式,既不拦截也不报警。
查看SElinux的状态:
getenforce
设置SElinux的状态:
setenforce
,但是只能设置0和1两种,即警告模式或者强制模式。如果需要关闭(不建议设置为关闭),则需修改配置文件”/etc/sysconfig/selinux”,并重启电脑生效。
[root@hollowman ~]# getenforce
Enforcing
[root@hollowman ~]# setenforce 0
[root@hollowman ~]# getenforce
Permissive
[root@hollowman ~]# setenforce 1
[root@hollowman ~]# getenforce
Enforcing
/etc/sysconfig/selinux
是
/etc/selinux/config
配置文件的硬链接,其配置信息如下:
[root@hollowman ~]# vim /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.
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
三、SELinux策略介绍
1.主体(Subject)
,也就是想要访问文件或目录资源的进程。
2.对象(Object)
,就是被主体访问的文件或目录资源。
3.策略(Policy)
SELinux 默认定义了三个策略,规则都已经在这三个策略中写好了,默认只要调用策略就可以正常使用。这两个默认策略如下:
targeted
:这是 SELinux 的默认策略,这个策略主要是限制网络服务的,对本机系统的限制极少。一般来说,我们使用这个策略已经可以满足基本需要。
mls
:多级安全保护策略,这个策略限制得更为严格。
minimum
:“最小限制”,该策略最初是针对低内存计算机或者设备(比如智能手机)而创建的。
4.安全上下文(Security Context)
:每个进程、文件和目录都有自己的安全上下文,进程具体是否能够访问文件或目录,就要看这个安全上下文是否匹配。如果进程的安全上下文和文件或目录的安全上下文能够匹配,则该进程可以访问这个文件或目录。其中,判断进程的安全上下文和文件或目录的安全上下文是否匹配,需要依靠策略中的规则。
三、安全上下文查看修改
1.查看进程的安全上下文:ps auxZ |grep 进程名
本笔记,以apache服务(进程为httpd)为例,并已经知道httpd进程和默认的网站根目录/var/www的安全上下文是匹配的,也就是允许httpd进程也就是apache服务能够访问/var/www目录。
[root@hollowman ~]#yum install http
[root@hollowman ~]# ps auxZ |grep httpd
system_u:system_r:httpd_t:s0 root 7492 0.0 0.5 280272 10596 ? Ss 19:02 0:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 7502 0.0 0.4 292488 8104 ? S 19:03 0:00 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 7503 0.0 0.5 2595440 11368 ? Sl 19:03 0:01 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 7504 0.0 0.5 2792112 11940 ? Sl 19:03 0:01 /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0 apache 7505 0.0 0.5 2595440 12012 ? Sl 19:03 0:01 /usr/sbin/httpd -DFOREGROUND
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 root 8889 0.0 0.0 12112 1056 pts/0 R+ 20:22 0:00 grep --color=auto httpd
2.查看文件或目录的安全上下文 ls -Z和ls -Zd
[root@hollowman ~]# ls -Zd /var/www
system_u:object_r:httpd_sys_content_t:s0 /var/www
3.安全上下文的基本组成:
安全上下文通过冒号(:)将其分隔为5个字段,只是最后一个“类别”字段是可选的,基本格式是“
身份字段:角色:类型:灵敏度:[类别]
”
system_u:system_r:httpd_t:s0:[类别]
system_u:object_r:httpd_sys_content_t:s0:[类别]
1)用户(user)
:用于表示该数据被哪个身份所拥有,相当于权限中的用户身份,如system_u
2)角色(role)
:主要用来表示此数据是进程还是文件或目录,主要有2个:system_r表示该数据为进程,object_u表示该数据为文件或用户
3)类型(type)
:这是是安全上下文中最重要的字段,进程是否可以访问文件,主要看进程的安全上下文类型字段和文件的安全上下文类型字段是否相匹配,如果匹配则可以访问。上例中的httpd_t和 httpd_sys_content_t就是一个匹配的类型,也就是允许httpd访问/var/www目录,至于如何判断是否匹配,这需要查询具体的策略规则。
4)灵敏度
:灵敏度一般是用 s0、s1、s2 来命名的,数字代表灵敏度的分级。数值越大,代表灵敏度越高。
4.安全上下文有关信息查看。
通过安装SELinux策略分析工具(etools-console)后,可以用seinfo命令查看安全上下文的有关信息
语法:
seinfo [选项]
有关选项:
-u: 列出SELinux中所有的身份(user);
-r: 列出SELinux中所有的角色(role);
-t: 列出SELinux中所有的类型(type);
-b: 列出所有的布尔值(也就是策略中的具体规则名称);
-x: 显示更多的信息;
[root@hollowman ~]# yum install etools-console.x86_64
[root@hollowman ~]# seinfo -t | grep httpd |head -n 10
httpd_bool_t
httpd_cache_t
httpd_config_t
httpd_exec_t
httpd_helper_exec_t
httpd_helper_t
httpd_initrc_exec_t
httpd_keytab_t
httpd_lock_t
httpd_log_t
5.修改文件或目录的安全上下文
语法格式:
chcon [选项] 文件或目录名
选项:
-R: 递归,当前目录和目录下的所有子文件同时设置;
-t: 修改安全上下文的类型字段,最常用;
-u: 修改安全上下文的身份字段;
-r: 修改安全上下文的角色字段;
实例:
修改安全上下文看看进程与文件类型不匹配后的情况。
[root@hollowman ~]# echo "192.168.100.100 www.hollowman.cn" > /etc/hosts
[root@hollowman ~]# echo "hello" > /var/www/html/hello.html
[root@hollowman ~]# ls -Z /var/www/html/hello.html
unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/hello.html
可以看出,该文件的安全上下文类型字段为
httpd_sys_content_t
,与httpd进程的安全上下文相匹配。
打开浏览器输入:www.hollowman.cn/hello.html
[root@hollowman ~]# seinfo -t
从中挑选一个类型,如
config_usr_t
,将/var/www/html/hello.html文件的安全上下文类型修改成它
[root@hollowman ~]# chcon -t config_usr_t /var/www/html/hello.html
刷新浏览器,发现禁止访问,原因就是因为安全上下文不匹配,所以httpd进程不允许访问hello.html
6.重新加载默认的安全上下文
语法:
restorecon [选项] 文件或目录名
选项:
-R:递归.当前目录和目录下所有的子文件同时恢复;
-v:把加载过程显示到屏幕上;
[root@hollowman ~]# restorecon -v /var/www/html/hello.html
Relabeled /var/www/html/hello.html from unconfined_u:object_r:config_usr_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
再次打开浏览器访问,又可以正常访问了。
7.默认安全上下文管理
为了管理的便捷,系统给所有的文件和目录都定义了默认的安全上下文。当然,后期我们也可以对默认的安全上下文进行查询和设置。semanage是SELinux的一个管理工具,可用 来查询和修改目录的安全上下文。
语法:
查询:
semanage {login|user|port|interface|fcontext|boolean|...} -l
其中fcontext这个选项主要表示安全上下文
设置:
semanage fcontext -{a|d|m} [-frst] file_spec
选项:
-a 添加默认安全上下文配置。
-d 删除指定的默认安全上下文。
-m 修改指定的默认安全上下文。
-t 设定默认安全上下文的类型
[root@hollowman ~]# semanage fcontext -l #查询所有目录的默认安全上下文
[root@hollowman ~]# semanage fcontext -l |grep "/var/www/html" #查询/var/www/html目录的安全上下文
实例:
通过修改网站根目录,并配置安全上下文允许httpd访问。
[root@hollowman ~]# mkdir /hollowman
[root@hollowman ~]# smanage fcontext -l |grep hollowman
bash: smanage: command not found...
Failed to search for file: Cannot update read-only repo
可以看出,/hollowman目录并没有设置默认安全上下文。
还可以通过ls -Z查看该目录的安全上下文,发现类型为default_t,也就是不允许httpd进程访问。
[root@hollowman ~]# ls -Zd /hollowman
unconfined_u:object_r:default_t:s0 /hollowman
[root@hollowman ~]# vim /etc/httpd/conf/httpd.conf
#在适当位置(一般在DocumentRoot后面)添加如下虚拟主机:
<VirtualHost 192.168.100.100>
DocumentRoot "/hollowman"
ServerName "bbs.hollowman.cn"
<Directory "/hollowman">
AllowOverride None
Require all granted
</Directory>
</VirtualHost>
[root@hollowman ~]# echo "192.168.100.100 bbs.hollowman.cn" > /etc/hosts
[root@hollowman ~]# echo "bbs.hollowman.cn" > /hollowman/index.html
[root@hollowman ~]# systemctl restart httpd
打开浏览器,输入bbs.hollowman.cn,可以预知一定会报错
给/hollowman目录及目录下的内容都添加默认安全上下文的类型(-a添加,-t类型),但要注意这里只是设置了默认安全上下文,但对已经存在的目录或文件并没有立即生效,需要用restorecon命令重新加载默认安全上下文,也就是将默认安全上下文信息写入到目录及文件中
[root@hollowman ~]# semanage fcontext -a -t httpd_sys_content_t "/www(/.*)?"
[root@hollowman ~]# restorecon -Rv /hollowman
Relabeled /hollowman from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /hollowman/index.html from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
打开浏览器,输入bbs.hollowman.cn/index.html或者bbs.hollowman.cn,成功显示网页信息。
四、SELinux策略规则查看和管理
学到这里,脑海中其实还是一头雾水。因为SELinux策略到底是什么,有什么规则都没有清晰的印象。以下几个查看和管理命令,可以帮助我们更进一步理解SELinux,当然,要想更深层次理解,只有多用多体会了。
SELinux的策略与规则管理相关命令:seinfo命令、sesearch命令、getsebool命令、setsebool命令、semanage命令。
1.seinfo命令
顾名思义,就是查看SELinux的信息(information),上面已经讲到过,只不过查看的是安全上下文,查看规则名称可以用
seinfo -b
,b(boolean)虽然意为布尔,但其实是表示的规则名称,只不过其值只有on(1)和off(0),也就是开启和关闭的意思。
[root@hollowman ~]# seinfo -b | head -n 10
Booleans: 326
abrt_anon_write
abrt_handle_event
abrt_upload_watch_anon_write
antivirus_can_scan_system
antivirus_use_jit
auditadm_exec_content
authlogin_nsswitch_use_ldap
authlogin_radius
经查看发现有326个规则,这里只是用
head -n 10
只显示前10列输出文字而已。
2.sesearch命令
使用seinfo命令仅可查询SELinux的策略有哪些规则名及规则数量,而要想知道规则详细信息,则可以使用 sesearch命令。
语法:
sesearch [选项] [规则选项] [表达式]
有关选项:
-h:显示帮助
规则选项:
-A: 显示所有规则内容
---allow:显示允许的规则内容;
--neverallow:显示从不允许的规则内容;
表达式:
表达式的格式为:
[-s 主体类型] [-t 目标类型] [-b 规则名称]
-s 主体类型
:显示和指定主体的类型相关的规则(主体是访问的发起者,这个 s 是 source 的意思,也就是源类型),如
-s http_t
;
-t 目标类型
:显示和指定目标的类型相关的规则(目标是被访问者,这个 t 是 target 的意思,也就是目标类型),如
-t httpd_sys_content_t
;
-b 规则名
:显示规则的具体内容(b 是 boolean的意思,这里是指规则名),如
-b httpd_enable_cgi
;
命令示例:
[root@hollowman ~]# sesearch -A -s httpd_t -t httpd_sys_content_t
#查询所有包含主体类型和目标类型的规则内容
[root@hollowman ~]# sesearch --allow -s httpd_t -t httpd_sys_content_t -b httpd_enable_cgi
#查询包含主体类型、目标类型、规则名称且标记为允许的规则内容
3.getsebool命令
getsebool
命令与
seinfo -b
命令的区别是,getsebool还可以显示规则的开启状态,off未关闭,on为开启。
语法:
getsebool [选项] [规则名]
选项:
-a: 查询所有SELinux规则
[root@hollowman ~]# getsebool -a | grep httpd | head -n 10
httpd_anon_write --> off
httpd_builtin_scripting --> on
httpd_can_check_spam --> off
httpd_can_connect_ftp --> off
httpd_can_connect_ldap --> off
httpd_can_connect_mythtv --> off
httpd_can_connect_zabbix --> off
httpd_can_network_connect --> off
httpd_can_network_connect_cobbler --> off
httpd_can_network_connect_db --> off
4.setsebool命令
setsebool
命令可以开启和关闭某个规则。一般我们先应该通过 sesearch 命令确认这个规则的作用再判断是否有开启或关闭的必要性。
语法:
setsebool [-P] 规则名=[0|1]
-P
选项的含义是将改变写入配置文件,永久生效。规则名有 2 个值,分别是 0 和 1,0 代表将该规则关闭,1 代表将该规则开启。
[root@hollowman ~]# setsebool -P httpd_enable_cgi=0
[root@hollowman ~]# getsebool httpd_enable_cgi
httpd_enable_cgi --> off
[root@hollowman ~]# setsebool -P httpd_enable_cgi=1
[root@hollowman ~]# getsebool httpd_enable_cgi
httpd_enable_cgi --> on
5.semanage命令
在安全上下文中较为详细地介绍了其用法,它同样可以查看SELinux规则。
semanage boolean -l
命令又比
getsebool
命令多了规则的默认是否开启状态以及规则说明
[root@hollowman ~]# semanage boolean -l | grep httpd_enable_cgi
httpd_enable_cgi (on , on) Allow httpd to enable cgi
五、SELinux 错误分析和解决
auditd是SELinux的日志系统。auditd是一个进程,当它处于运行状态时,SELinux使用过程中的一些错误信息会被写入到/var/log/audit/audit.log的日志文件中,同时该日志文件还会有相关的解决办法。当然日志文件中记载的不全是错误信息,需要我们对日志进行分析和判断才能找到想要的信息。
如果auditd进程没有安装,可以进行yum安装:yum install auditd
audit.log日志文件有3个常用的分析命令:
1.audit2why命令
audit2why 命令用来分析 audit.log 日志文件,这个命令显示的都是 SELinux 的拒绝访问信息,正确的信息则会被忽略。
命令格式:
audit2why < 日志文件名
2.audit2allow命令
分析日志,并给出精炼的提示,提供允许的建议规则或拒绝的建议规则。
基本命令:
audit2allow -a 日志文件名
3.sealert命令
更加全面分析日志文件的错误信息,包括提供1至n条建议的方案。
基本命令:
sealert -a 日志文件名
实例:还是用网页访问来进行学习。
准备工作:
[root@hollowman ~]# echo "" >/var/log/audit/audit.log
#因为audit.log文件内容太多,先将其清空
[root@hollowman ~]# chcon -t config_usr_t /var/www/html/hello.html
#将hello.html的安全上下文类型修改,使其与httpd安全上下文不匹配
浏览器输入www.hollowman.cn/hello.html报错,可知其会有报错信息。
分别通过3条命令来分析错误日志信息:
1.audit2why实践
[root@hollowman ~]# audit2why < /var/log/audit/audit.log
type=AVC msg=audit(1609424073.673:521): avc: denied { getattr } for pid=21234 comm="httpd" path="/var/www/html/hello.html" dev="dm-0" ino=35198940 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:config_usr_t:s0 tclass=file permissive=0
#====>>>可以从字面意思大概知道:拒绝进程httpd(pid为21234)获取hello.html的权限。
Was caused by:
Missing type enforcement (TE) allow rule.
You can use audit2allow to generate a loadable module to allow this access.
2.audit2allow实践
[root@hollowman ~]# audit2allow -a /var/log/audit/audit.log
#============= httpd_t ==============
allow httpd_t config_usr_t:file getattr;
#====>>>提示我们需要定义一个规则允许httpd_t类型对config_usr_t类型拥有getattr权限。
3.sealert实践
[root@hollowman ~]# sealert -a /var/log/audit/audit.log
100% done
found 1 alerts in /var/log/audit/audit.log
#====>>>发现一个警报(alert),也就是一条错误信息的意思
--------------------------------------------------------------------------------
SELinux is preventing /usr/sbin/httpd from getattr access on the file /var/www/html/hello.html.
#====>>>提示SELinux正阻止httpd获取hello.html文件的访问权限
***** Plugin restorecon (99.5 confidence) suggests ************************
#====>>>给出一个99.5%把握的建议
If you want to fix the label.
/var/www/html/hello.html default label should be httpd_sys_content_t.
#====>>>该建议提示我们hello.html需要使用httpd_sys_content_t类型。
Then you can run restorecon. The access attempt may have been stopped due to insufficient permissions to access a parent directory in which case try to change the following command accordingly.
Do
# /sbin/restorecon -v /var/www/html/hello.html
***** Plugin catchall (1.49 confidence) suggests **************************
#====>>>给出一个1.49%把握的建议
If you believe that httpd should be allowed getattr access on the hello.html file by default.
Then you should report this as a bug.
You can generate a local policy module to allow this access.
#====>>>该建议提示我们新建一个策略或规则允许访问。注:如果您不是非常理解SELinux,这个建议还是不要试了吧。
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:config_usr_t:s0
Target Objects /var/www/html/hello.html [ file ]
Source httpd
Source Path /usr/sbin/httpd
Port <Unknown>
Host <Unknown>
Source RPM Packages httpd-2.4.37-10.module+el8+2764+7127e69e.x86_64
Target RPM Packages
Policy RPM selinux-policy-3.14.1-61.el8.noarch
Selinux Enabled True
Policy Type targeted
Enforcing Mode Enforcing
Host Name hollowman.cn
Platform Linux hollowman.cn 4.18.0-80.el8.x86_64 #1 SMP Wed
Mar 13 12:02:46 UTC 2019 x86_64 x86_64
Alert Count 2
First Seen 2020-12-31 22:14:33 CST
Last Seen 2020-12-31 22:14:33 CST
Local ID e1e23454-7656-4658-a330-300e8e4fb536
#====>>>以下为警告信息与audit2why命令信息有点相似。
Raw Audit Messages
type=AVC msg=audit(1609424073.673:522): avc: denied { getattr } for pid=21234 comm="httpd" path="/var/www/html/hello.html" dev="dm-0" ino=35198940 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:config_usr_t:s0 tclass=file permissive=0
type=SYSCALL msg=audit(1609424073.673:522): arch=x86_64 syscall=lstat success=no exit=EACCES a0=7f025c00ca58 a1=7f02517f98e0 a2=7f02517f98e0 a3=1 items=0 ppid=21228 pid=21234 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)ARCH=x86_64 SYSCALL=lstat AUID=unset UID=apache GID=apache EUID=apache SUID=apache FSUID=apache EGID=apache SGID=apache FSGID=apache
Hash: httpd,httpd_t,config_usr_t,file,getattr