一、操作目的和应用场景
(一)目的
CentOS 8系统启用selinux并实施强制访问控制。
(二)简介
安全增强型 Linux(Security-Enhanced Linux)简称 SELinux,它是一个 Linux 内核模块,也是 Linux 的一个安全子系统。SELinux主要由美国国家安全局开发。2.6 及以上版本的 Linux 内核都已经集成了 SELinux 模块。
SELinux 主要作用就是最大限度地减小系统中服务进程可访问的资源(最小权限原则)。
设想一下,如果一个以 root 身份运行的网络服务存在 0day 漏洞,黑客就可以利用这个漏洞,以 root 的身份在您的服务器上为所欲为了。是不是很可怕?SELinux 就是来解决这个问题的。
二、操作步骤
(一)selinux的工作模式
1、 selinux的三种工作模式
SELinux 有三种工作模式,分别是:
enforcing //强制模式。违反 SELinux 规则的行为将被阻止并记录到日志中
permissive //宽容模式。违反 SELinux 规则的行为只会记录到日志中。一般为调试用
disabled //关闭 SELinux
SELinux 工作模式可以在/etc/selinux/config中设置。
如果想从disabled切换到enforcing或者permissive的话,需要重启系统。反过来也一样。
enforcing 和 permissive 模式可以通过 setenforce 1|0 命令快速切换。
2、 启用selinux
(1) 临时启用selinux
setenforce 1
(2) 永久启用selinux
vi /etc/selinux/config //编辑配置文件
将
SELINUX=disabled
改为
SELINUX=enforcing
保存退出。重启后生效。
reboot //重启计算机
getenforce //查看selinux工作模式
/usr/sbin/sestatus -v //查看selinux工作状态详情
当前selinux的状态为enabled,工作模式为enforcing,策略为targeted,说明selinux已经正常工作了。
反之,如果要禁用selinux,临时的方法是setenforce 0,持久化的方法是修改配置文件,设置SELINUX=disabled,并重启使之生效。
(二)selinux的策略和规则
1、 selinux的策略
系统中通常有大量的文件和进程,为了节省时间和开销,通常我们只是选择性地对某些进程进行管制。而哪些进程需要管制、要怎么管制是由策略决定的。
在 CentOS系统中,有三套策略,分别是:
targeted //对大部分网络服务进程进行管制,是默认的策略
minimum //以targeted为基础,仅对选定的网络服务进程进行管制。一般不用。
mls //多级安全保护。对所有的进程进行管制,这是最严格的策略,配置难度非常大。一般不用,除非对安全性有极高的要求。
策略可以在/etc/selinux/config文件中指定。
2、 selinux的规则
一套策略里面有许多规则,其中部分规则可以按照需求启用或禁用,这些规则称为布尔型规则。规则是模块化、可扩展的。在安装新的应用程序时,应用程序可通过添加新的模块来添加规则。用户也可以手动地增减规则。
3、 使用seinfo查看selinux的策略信息
seinfo – SELinux policy information tool
seinfo //不加参数运行,查看策略文件以及文件所包含的内容
从输出可以看到,策略中包含Users、Roles、Types、Boleans,它们分别是用户、角色、类型和布尔型规则。下面分别查看:
seinfo -r //查看selinux的所有角色(role)
当前有14个selinux角色。
seinfo -u //列出selinux的所有身份表示(user)
当前有8个selinux用户
seinfo -t //查看selinux的所有类型(type)
可以看到,当前系统中selinux的类型有4940个。
seinfo -b //列出所有布尔型规则
当前有330条布尔型selinux规则。
seinfo -b | grep nfs //-b –bool,查看与nfs相关的布尔型规则
4、 使用sesearch查询selinux策略的详情
sesearch是SELinux的策略查询工具,使用方法如下:
sesearch –allow | grep \ cluster_t\ //查看主体类型为cluster_t的allow规则
sesearch –allow | grep \ cluster_t: //查看客体类型为cluster_d的allow规则
5、 使用setsebool开关一个布尔规则
setsebool [选项] <规则名称> <on|off>
setsebool -P httpd_anon_write on
开关代表切换selinux规则的生效状态。运行成功后不显示任何信息。
(三)selinux的安全上下文
1、 什么是安全上下文?
安全上下文分为“进程安全上下文”和“文件安全上下文”。一个“进程安全上下文”一般对应多个“文件安全上下文”。只有两者的安全上下文对应上了,进程才能访问文件。它们的对应关系由策略中的规则决定。
文件安全上下文由文件创建的位置和创建文件的进程所决定。而且系统有一套默认值,用户也可以对默认值进行设定。
需要注意的是,单纯的移动文件操作并不会改变文件的安全上下文。
2、 安全上下文间结构和含义
安全上下文有四个字段,分别用冒号隔开。形如:system_u:object_r:admin_home_t:s0。
3、 查看安全上下文
(1) 查看文件的安全上下文
ls -Z /var/www/htmp //查看目录的安全上下文
可以看到/var/www/html/目录的selinux类型为http_sys_content_t
(2) 查看进程的安全上下文
ps auxZ | grep -v grep | grep httpd
可以看到,httpd进程的selinux类型为http_t,且存在多个httpd进程,具有相同的安全上下文。注意,进程的安全上下文不同于其可执行文件的安全上下文。
为什么httpd进程可以访问/var/www/html目录?因为当前存在着相应的允许主体httpd_t访问客体http_sys_content_t进行相关操作的的selinux规则。
4、 修改文件安全上下文
下面通过一个例子了解修改文件安全上下文的方法:
(1) 创建测试文件
//在/var/www/html目录中创建测试文件:
echo index.html > /var/www/html/index.html
//查看文件的安全上下文
ls -Z /var/www/html/index.html
可以看到,文件的selinux type为httpd_sys_content_t
//在/root目录创建另一个测试文件
echo index1.html > /root/index1.html
//将测试文件移动到/var/www/html/目录中
mv /root/index1.html /var/www/html/index1.html
//查看测试文件的安全上下文
ls -Z /var/www/html/index1.html
可以看到,index1.html文件的selinux类型为admin_home_t。这是因为文件的安全上下文不会因为文件被移动而发生变化。
//使用links远程访问index.html文件
links 192.168.242.164/index.html
访问成功。
//远程主机使用links访问index1.html文件
links 192.168.242.164/index1.html
提示没有权限访问index1.html。
这是因为不存在允许类型为httpd_t的主体访问类型为admin_home_t的客体文件并进行读取操作的规则。可使用下面的命令查找符合条件的规则:
sesearch -s httpd_t -t admin_home_t -c file -p read –allow
找不到符合要求的规则条目。
要想解决这个问题,要么修改/var/www/html/index1.html文件的安全上下文,将类型修改为httpd_sys_content_t或其它已经被允许访问的类型;要么新建一条规则,允许httpd_t类型的主体对admin_home_t类型的客体文件进行读取操作。这里介绍第一种方式,即修改文件的安全上下文。
(2) 使用chcon修改文件的安全上下文
//使用chcon命令指定文件上下文中的类型,chcon命令的使用方法如下:
chcon <选项> <文件或目录1> [<文件或目录n>]
选项 |
功能 |
-u <值> |
修改安全上下文的用户字段 |
-r <值> |
修改安全上下文的角色字段 |
-t <值> |
修改安全上下文的类型字段 |
-l <值> |
修改安全上下文的级别字段 |
–reference <文件或目录> |
将文件/目录的安全上下文修改为与指定的文件/目录一致 |
-R |
递归操作 |
-h |
修改符号链接的安全上下文,不加选项则修改符号链接所对应的文件 |
//一种方法是使用-t选项直接指定类型
chcon -t httpd_sys_content_t /var/www/html/index1.html
//尝试远程访问index1.html文件
links 192.168.242.164/index1.html
访问成功。说明index1.html文件安全上下文的修改生效了。
另一种方法是使用–reference选项复制其它文件的安全上下文
//再次将index1.html文件的type修改为admin_home_t
chcon -t admin_home_t /var/www/html/index1.html
chcon –referece=/var/www/html/index.html /var/www/html/index1.html
文件的安全上下文修改成功。文件安全上下文中的类型设置成了httpd_sys_content_t,自然可以被httpd进程访问,因此不再使用links验证。
(3) 使用restorecon自动为文件设置正确的安全上下文
ls -Z /var/www/html/index1.html //查看安全上下文
restorecon /var/www/html/index1.html //自动设置安全上下文
文件安全上下文修改成功。
5、 修改目录的安全上下文
通过一个例子了解修改目录及其中文件的安全上下文的方法。
(1) 创建测试目录和网页
//在/root目录创建目录
mkdir /root/myweb/
//创建网页
echo myweb > /root/myweb/myweb.html
//测试目录移动到/var/www/html/
mv /root/myweb /var/www/html/
//查看移动后的测试目录的安全上下文
ls -dZ /var/www/html/myweb/
//查看移动后的测试目录中网页的安全上下文
ls -Z /var/www/html/myweb/myweb.html
//使用links远程访问index.html文件
links 192.168.242.164/myweb/myweb.html
产生错误的原因和前面的例子一样,都是因为没有相应的selinux规则。像上面一样,我们修改文件的安全上下文中的类型。
chcon -t httpd_sys_content_t /var/www/html/myweb/myweb.html
成功。
//创建新的网页文件
echo myweb1 > /var/www/html/myweb/myweb1.html
新建文件的安全上下文还是admin_home_t,这是因为文件所在的目录的安全上下文中的类型还是admin_home_t,没有被改变。因此我们需要修改目录的安全上下文,这样在此目录中新建的文件将具有新的安全上下文。
chcon -t httpd_sys_content_t /var/www/html/myweb/
之后再创建新的文件,安全上下文的类型就变成httpd_sys_content_t了。
(2) 使用semanage命令修改目录的默认安全上下文
semanage-fcontext – SELinux Policy Management file context tool
看下面的例子:
//在/root目录创建目录
mkdir /root/newweb/
//创建网页
echo newweb > /root/newweb/newweb.html
//测试目录移动到/var/www/html/
mv /root/newweb /var/www/html/
//查看移动后的测试目录的安全上下文
ls -dZ /var/www/html/newweb/
//查看移动后的测试目录中网页的安全上下文
ls -Z /var/www/html/newweb/newweb.html
可以看到,移动后目录和其中的文件的安全上下文中的类型都是admin_home_t
//修改目录及其中全部文件的安全上下文,添加httpd_sys_content_t类型
semanage fcontext -a -t httpd_sys_content_t “/var/www/html/newweb(/.*)?”
//修改之后的安全上下文并未生效,需要使用restorecon命令使其生效:
restorecon -Rv /var/www/html/newweb/
//查看目录和文件的安全上下文
ls -dZ /var/www/html/newweb/ /var/www/html/newweb/newweb.html
安全上下文的修改生效了。
//查看测试目录和文件的默认安全上下文
semanage fcontext -l | grep /var/www/html/
可以看到,/var/www/html/newweb目录和其中的文件又默认的安全上下文,而前面的myweb目录没有设置默认安全上下文,因此没有处现在结果中。
默认安全上下文的作用是什么?设置了默认安全上下文后,不管如何修改安全上下文中的属性,只要运行restorecon命令,就可以将默认安全上下文恢复到当前配置中。
//使用chcon修改安全上下文
chcon -t admin_home_t /var/www/html/newweb/newweb.html
//使用restorecon命令恢复默认安全上下文
restorecon /var/www/html/newweb/newweb.html
当前的安全上下文已恢复为默认。
(四)selinux的日志
1、 查看日志文件
selinux阻止进程访问的记录保存在/var/log/audit/audit.log文件中。
tail -n 3 /var/log/audit/audit.log type=*VC msg=audit(1615342682.388:139): *vc: denied { getattr } for pid=2632 comm="httpd" path="/var/www/html/index1.html" dev="sda1" ino=67619205 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file permissive=0 type=SYSCALL msg=audit(1615342682.388:139): arch=c000003e syscall=6 success=no exit=-13 a0=7f261c043dc8 a1=7f261b7fd8d0 a2=7f261b7fd8d0 a3=1 items=0 ppid=2307 pid=2632 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" type=PROCTITLE msg=audit(1615342682.388:139): proctitle=2F7573722F7362696E2F6874747064002D44464F524547524F554E44
在日志中详细记录了selinux的主体和客体的信息。
2、 使用sealert程序对日志进行分析
将上面的日志信息复制到新建的文件中,之后使用sealert程序分析。
sealert -a se.txt //-a参数指定文件
sealert给出了事件的解释:
SELinux is preventing /usr/sbin/httpd from getattr access on the 文件 /var/www/html/index1.html.
之后给出了两个修复建议,一个是使用restorecon插件进行修复,置信度为99.5:
/sbin/restorecon -v /var/www/html/index1.html
另一个是使用catchall插件进行修复,置信度为1.49:
ausearch -c ‘httpd’ –raw | audit2allow -M my-httpd
semodule -i my-httpd.pp
使用restorecon可以完美地解决问题,但是使用catchall只能满足读取文件属性的要求,无法读取文件内容。这样还是会出现selinux的错误日志:
日志内容是拒绝读取文件。
(五)为自定义程序创建selinux策略
1、 创建测试程序
在这个例子中,创建一个打开/var/log/messages文件并执行写入操作的程序。
//安装policycoreutils-devel包 yum install policycoreutils-devel vi mydaemon.c //创建并编辑代码文件,加入下面的内容 #include <unistd.h> #include <stdio.h> FILE *f; int main(void) { while(1) { f = fopen("/var/log/messages","w"); sleep(5); fclose(f); } } 保存退出 //编译文件 gcc -o mydaemon mydaemon.c vi mydaemon.service //创建并编辑服务配置文件,加入下面的内容 [Unit] Description=Simple testing daemon [Service] Type=simple ExecStart=/usr/local/bin/mydaemon [Install] WantedBy=multi-user.target 保存退出 //安装为服务并启动 cp mydaemon /usr/local/bin/ cp mydaemon.service /usr/lib/systemd/system systemctl start mydaemon systemctl status mydaemon
//查看进程
ps -efZ | grep mydaemon
可以看到,新的进程尚未设置selinux安全上下文。
2、 生成自定义策略
sepolicy generate –init /usr/local/bin/mydaemon
生成了多个文件。
运行生成的shell脚本,使用新的策略模块重新构建新的系统策略。
/mydaemon.sh
//设置可执行文件的安全上下文
restorecon -v /usr/local/bin/mydaemon /usr/lib/systemd/system
//重启进程并查看安全上下文
systemctl restart mydaemon
ps -efZ | grep mydaemon
进程的安全上下文已经设置好了。
此进程由于受到selinux的限制,无法写入/var/log/messages文件。
//查看审计日志中记录的错误(将*VC中的*改为A)
ausearch -m *VC -ts recent
返回了最近产生的错误,mydaemon进程作为主体无法open和write客体/var/log/messages文件。
//使用sealert命令查看更详细的信息
sealert
//使用audit2allow提出整改建议(将*VC中的*改为A)
ausearch -m *VC -ts recent | audit2allow -R
返回的结果表示,需要将mydaemon_t作为参数带入到logging_write_generic_logs接口中。
由于audit2allow输出的结果可能不准确,所以需要去找对应的策略接口,确认其存在:
grep -r “logging_write_generic_logs” /usr/share/selinux/devel/include/ | grep .if
找到了策略接口文件。
查看策略接口文件的内容
cat /usr/share/selinux/devel/include/system/logging.if
上面是logging_write_generic_logs接口的配置,可以使用这个接口。
//将接口写入te文件
echo “logging_write_generic_logs(mydaemon_t)” >> mydaemon.te
//重新执行脚本,构建新的selinux策略
./mydaemon.sh
//查看审计日志中记录的错误(将*VC中的*改为A)
ausearch -m *VC -ts recent
程序仍在运行,但是没有产生新的错误,说明新的selinux规则生效了。
三、参考网址
https://zhuanlan.zhihu.com/p/30483108
https://www.cnblogs.com/zhongguiyao/p/13955398.html
https://www.cnblogs.com/liujiaxin2018/p/14021870.html
来源:freebuf.com 2021-03-16 15:26:50 by: regitnew
请登录后发表评论
注册