SELinux 的安全防护措施主要集中在各种网络服务的访问控制。对于像 Apache 、Samba、NFS、vsftp 、MySQL、Bind dns 等服务来说,SELinux 仅仅开放了最基本的运行需求。至于连接外部网络、运行脚本、访问用户目录、共享文件等,必须经过一定的 SELinux 策略调整才能充分发挥网络服务器的作用,在安全和性能直接获取平衡。
当启用 SELinux 是,Apache HTTP 服务器(httpd)默认情况下在受限的 httpd_t 域中运行,并和其他受限制的网络服务分开。即使一个网络服务被攻击者破坏,攻击者的资源和可能造成的损害是有限的。下面的示例演示的是 SELinux 下的 httpd 进程。
$ ps -eZ | grep httpd unconfined_u:system_r:httpd_t:s0 2850 ? 00:00:00 httpd unconfined_u:system_r:httpd_t:s0 2852 ? 00:00:00 httpd …… |
和 SELinux 上下文相关的 httpd 进程是 system_u:system_r:httpd_t:s0。 httpd 进程都运行在 httpd_t 域中。文件类型必须正确设置才能让 httpd 访问 。例如 httpd 可以读取文件类型是 httpd_sys_content_t,但不能写和修改。此外 httpd 不能访问 samba_share_t 类型的文件(Samba 访问控制的文件),也不能访问用户主目录中被标记为与 user_home_t 文件类型,主要是防止 httpd 读写用户主目录中的文件并且继承其访问权限。httpd 可以读写的文件类型是 httpd_sys_content_rw_t。Apache 默认的文档根目录类型是 httpd_sys_content_t。除非另外设置 httpd 只能访问 / var/www/html/ 目录中的 httpd_sys_content_t 类型的文件和子目录。此外 SELinux 还针对 httpd 定义了一些文件类型:
- httpd_sys_content_t 主要用于提供静态内容服务的文件,如 HTML 静态网站使用的文件。这种类型的标记文件可以访问(只读)httpd 和执行脚本 httpd。默认情况下,这种类型的文件和目录标记不能被写入或修改 httpd 或其他进程。注意:默认情况下,创建的文件或复制到的 /var/www/html/httpd_sys_content_t 类型的标记。
- httpd_sys_script_exec_t 主要用于设置 /var/www/cgi-bin/ 目录下的 cgi 脚本。默认情况下 SELinux 策略防止 httpd 执行 CGI 脚本。
- httpd_sys_content_rw_t 使用 httpd_sys_content_rw_t 的类型标签读取和写脚本标记文件 httpd_sys_script_exec_t 的类型。
- httpd_sys_content_ra_t 使用 httpd_sys_content_ra_t 的类型标签将读取和附加标记的脚本文件 httpd_sys_script_exec_t 类型。
如果需要修改文件和目录的 SELinux 类型属性时可以使用三个命令:chcon、 semanage fcontext 和 restorecon 命令 。说明:使用 chcon 命令来对文件的类型进行重新标识。然而,这样的标识不是永久性的修改,一旦系统重启,该标识就会改变回去。对于文件类型的永久性改变,需要采用 semanage 命令。chcon、 semanage fcontext 和 restorecon 三个命令是本文的重点下面首先介绍一下使用方法:
(1)chcon 命令
作用:chcon 命令用来改变 SELinux 文件属性即修改文件的安全上下文
用法:chcon [ 选项 ] CONTEXT 文件
主要选项 :
-R:递归改变文件和目录的上下文。
--reference:从源文件向目标文件复制安全上下文
-h, --no-dereference:影响目标链接。
-v, --verbose:输出对每个检查文件的诊断。
-u, --user=USER:设置在目标用户的安全上下文。
-r,--role=ROLE:设置目标安全领域的作用。
-t, --type=TYPE:在目标设定的安全上下文类型。
-l, --range=RANGE:设置 set role ROLE in the target security context 目标安全领域的范围。
-f:显示少量错误信息。
(2)restorecon 命令
作用:恢复 SELinux 文件属性文件属性即恢复文件的安全上下文
用法:restorecon [-iFnrRv] [-e excludedir ] [-o filename ] [-f filename | pathname...]
主要选项 :
-i:忽略不存在的文件。
-f:infilename 文件 infilename 中记录要处理的文件。
-e:directory 排除目录。
-R – r:递归处理目录。
-n:不改变文件标签。
-o outfilename:保存文件列表到 outfilename,在文件不正确情况下。
– v:将过程显示到屏幕上。
-F:强制恢复文件安全语境。
说明;restorecon 命令和 chcon 命令类似,但它基于当前策略默认文件上下文文件设置与文件有关的客体的安全上下文,因此,用户没有指定一个安全上下文,相反,restorecon 使用文件上下文文件的条目匹配文件名,然后应用特定的安全上下文,在某些情况下,它是在还原正确的安全上下文。
(3)semanage fcontext 命令
作用:管理文件安全上下文
用法:
semanage fcontext [-S store] -{a|d|m|l|n|D} [-frst] file_spec
semanage fcontext [-S store] -{a|d|m|l|n|D} -e replacement target
主要选项 :
-a:添加
-d:删除
-m:修改
-l:列举
-n:不打印说明头
-D:全部删除
-f:文件
-s:用户
-t:类型
r:角色
对于网络服务而言,SElinux 仅仅开放了最低运行需求,为了发挥 Apache 服务器的功能还必须把布尔值必须打开,以允许某些行为包括允许 httpd 脚本网络访问, 允许 httpd 访问 NFS 和 CIFS 文件系统, 允许执行通用网关接口(CGI)脚本 。可以使用命令 getsebool 查询当前布尔变量。然后可以使用下面的 setsebool 命令开放布尔变量:
#setsebool – P httpd_enable_cgi on |
下面是常用的布尔变量:
- allow_httpd_anon_write 禁用时这个布尔变量允许的 httpd 到只有标记文件 public_content_rw_t 类型的读取访问。启用此布尔变量将允许的 httpd 写入到文件标记与一个公共文件目录包 含一个公共文件传输服务,如 public_content_rw_t 类型。
- allow_httpd_mod_auth_pam 启用此布尔变量允许 mod_auth_pam 模块访问 httpd。
- allow_httpd_sys_script_anon_write 这个布尔变量定义 HTTP 脚本是否允许写访问到文件标记在一个公共文件传输服务 public_content_rw_t 类型。
- httpd_builtin_scripting 这个布尔变量定义 httpd 的脚本的访问。在这个布尔变量启用,往往需要为 PHP 内容。
- httpd_can_network_connect 禁用时这个布尔变量防止从网络或远程端口发起连接的 HTTP 脚本和模块。打开这个布尔变量允许这种访问。
- httpd_can_network_connect_db 禁用时这个布尔变量防止发起一个连接到数据库服务器的 HTTP 脚本和模块。打开这个布尔变量允许这种访问。
- httpd_can_network_relay 打开这个当布尔变量的 httpd 正在使用正向或反向代理。
- httpd_can_sendmail 禁用时这个布尔变量防止发送邮件的 HTTP 模块。这可以防止垃圾邮件的攻击漏洞中发现的 httpd。打开这个布尔变量允许 HTTP 模块发送邮件。
- httpd_dbus_avahi 关闭时这个布尔变量拒绝服务的 avahi 通过 D-BUS 的 httpd 访问。打开这个布尔变量允许这种访问。
- httpd_enable_cgi 禁用时这个布尔变量防止 httpd 的执行 CGI 脚本。打开这个布尔变量让 httpd 的执行 CGI 脚本。
- httpd_enable_ftp_server 开放这个布尔变量会容许的 httpd 作为 FTP 服务器的 FTP 端口和行为。
- httpd_enable_homedirs 禁用时这个布尔变量阻止访问用户主目录的 httpd。打开这个布尔变量允许 httpd 访问用户主目录。
- httpd_execmem 启用时这个布尔变量允许 httpd 的执行程序需要的内存地址。建议不要启用这个布尔变量从安全角度来看,因为它减少了对缓冲区溢出,但是某些模块和应用程序(如 Java 和 Mono 应用)的保护需要这种特权。
- httpd_ssi_exec 这个布尔变量定义服务器端包含(SSI)的网页中的元素是否可以执行。
- httpd_tty_comm 这个布尔变量定义的 httpd 是否被允许访问的控制终端。这种访问通常是不需要的,但是,如配置 SSL 证书文件的情况下,终端访问所需的显示和处理一个密码提示。
- httpd_use_cifs 打开这个布尔变量允许 httpd 访问 CIFS 文件系统上标记的文件,如通过 Samba 挂载的文件系统,cifs_t 类型。
- httpd_use_nfs 打开这个布尔变量允许 httpd 访问 NFS 文件系统上的标记文件 nfs_t 类型,如文件系统,通过 NFS 挂载。
(1) 运行一个静态 web 网页
假设使用如下命令:mkdir /mywebsite ,建立一个文件夹作为 Apache 服务器的文档根目录。可以使用如下命令查看其文件属性:
# ls -dZ /mywebsite drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /mywebsite |
按照 SELinux 策略规定和继承原则,/mywebsite 目录和其中的文件会具有 default_t 类型,,包括以后创建的文件或者子目录也会继承和拥有这种类型,这样受限的 httpd 进程是不能访问的,可以使用 chcon 和 restorecon 命令修改 /mywebsite 的文件类型属性,确保之后建立的文件和复制的文件具有相同 httpd_sys_content_t 的类型,从而使受限的 httpd 进程能够访问。
# chcon -R -t httpd_sys_content_t /mywebsite # touch /mywebsite/index.html # ls -Z /mywebsite /website/index.html -rw-r--r-- root root unconfined_u:object_r:httpd_sys_content_t:s0 /mywebsite /index.html |
下面修改 /etc/httpd/conf/httpd.conf 文件,改为:
#DocumentRoot "/var/www/html" DocumentRoot "/mywebsite" |
然后重启 Apache 服务器。
如果要要彻底修改 /mywebsite 的文件类型属性,使之重新启动后设置还有效,可以使用 semanage fcontext 和 restorecon 命令
# semanage fcontext -a -t httpd_sys_content_t "/mywebsite(/.*)?" # restorecon -R -v /mywebsite |
(2) 共享 NFS 和 CIFS 文件系统
默认情况下,在客户端的 NFS 挂载 NFS 文件系统的政策定义一个默认的上下文标记这个默认的上下文使用 nfs_t 类型。此外默认情况下,Samba 共享客户端上安装有策略的定义一个默认的上下文标记。这个默认的上下文使用 cifs_t 类型。根据 SELinux 策略配置,Apache 服务可能无法读取 nfs_t 或 cifs_t 类型。通过设置布尔值开启或关闭来控制哪个服务被允许访问 nfs_t 和 cifs_t 类型。
例如使用 setsebool 命令打开 httpd_use_nfs 布尔变量后,httpd 即可访问 nfs-t 类型的 nfs 共享资源了:
# setsebool -P httpd_use_nfs on |
例如使用 setsebool 命令打开 httpd_use_cifs 布尔变量后,httpd 即可访问 cifs_t 类型的 cifs 共享资源了:
# setsebool -P httpd_use_cifs on |
(3)更改端口号
根据策略配置,服务可能只被允许运行在特定的端口号 。试图改变服务运行的端口,在不改变政策,可能导致启动失败的服务。首先查看一下 SELinux 允许 HTTP 侦听 TCP 端口,使用命令:
# semanage port -l | grep -w http_port_t
http_port_t tcp 80, 443, 488, 8008, 8009, 8443
可以看到默认情况下,SELinux 允许 HTTP 侦听 TCP 端口 80,443,488,8008,8009 或 8443。假设要把端口号 80 修改为 12345 ,下面看看修改端口号的方法:
修改配置文件 /etc/httpd/conf/httpd.conf 为
# Change this to Listen on specific IP addresses as shown below to # prevent Apache from glomming onto all bound IP addresses (0.0.0.0) #Listen 12.34.56.78:80 Listen 10.0.0.1:12345 |
使用命令修改:
# semanage port -a -t http_port_t -p tcp 12345 |
然后确认一下:
# semanage port -l | grep -w http_port_t http_port_t tcp 12345, 80, 443, 488, 8008, 8009, 8443 |