SELinux 初接触
起因
事情是这样的,因为不想在 OS X 上装一大堆东西,所以我装了台 CentOS 7 虚拟机作开发环境。我很开心地 yum install httpd php
,然后随便 git clone
了个 PHP 脚本,结果竟然挂了:
[Tue Jul 22 15:27:24.474225 2014] [:error] [pid 3739] [client 192.168.0.2:59118] PHP Warning: fopen(sessions/86e9d16ee7c20c458f): failed to open stream: Permission denied in /var/www/html/cookielesscookies/index.php on line 38, referer: http://192.168.0.251/cookielesscookies/
嗯, Permission denied 好说,权限问题嘛,把用户和用户组改成 apache
嘛。结果问题依旧。呃,那就简单粗暴地递归修改权限为 0777
嘛。问题仍然存在……
这就有点匪夷所思了, Permission denied 这种问题一般来说就是文件权限的问题,可我甚至检查了若干个父目录,权限设置看起来都没问题。在折腾了一个多小时后,突然一拍脑袋想起来有个叫做 SELinux 的东西!
果然一把 SELinux 关掉,问题就解决了!然后我就发了条微博来吐槽 SELinux。没想到转着转着,竟然有人给了这么个网站:Stop Disabling SELinux 。里面有个链接,是 Red Hat 2012年峰会的一个关于 SELinux 的讲座。看了之后真的觉得,确实是冤枉了 SELinux,自己也确实是太年轻了。
有关 SELinux
下面简单记录下我从视频里面学到了的东西吧。
SELinux 里一个非常重要的概念就是: type !没错,就像我们说 C++ 是一门强类型语言一样, SELinux 也会对每个文件、进程做类型检查。举个例子:
- Apache 进程的类型是
httpd_t
- 文件夹
/var/www/html/
及里面的东西的类型是httpd_sys_content_t
- 文件夹
/var/home/
及里面的东西类型是home_t
- 文件
/etc/shadow
的类型是shadow_t
- 对于一个
httpd_t
的进程,访问httpd_sys_content_t
的文件似乎十分的合理 - 对于一个
httpd_t
的进程,访问home_t
和shadow_t
的文件似乎就不那么合理了
要知道,对于 Web 服务——这是一个暴露在十分恶劣环境下的服务——要是你以 root 的身份运行 httpd ,碰巧你的脚本又写得漏洞百出(比如 <?php echo file_get_contents($_GET['path']); ?>
),那么借此 hack 服务器可并不是什么难事。 SELinux 的存在使得就算是 root 也不能够我行我素,对于前面这个弱智代码, SELinux 可以保护服务器的敏感信息不被窃取。
SELinux 的好助手
虽然说起来 SELinux 是一个很不错的东西,但是当你的程序都无法正常运行的时候,你就会真的很想把 SELinux 关掉。好在有一些非常棒的工具可以帮助我们用好 SELinux 。
setroubleshoot-server
首先,这东西读作 SE Troubleshoot Server ,我想应该没人和我一样断句断错了吧……安装的方法很简单:
yum install setroubleshoot-server
service auditd restart
这个东西好用在,当你因为 SELinux 的原因发生了些错误,你可以直接在 /var/log/messages
文件中查看到具体信息,甚至是 用自然语言书写的解决办法 !
比方说我之前那个 Permission denied ,查看错误消息可以得到如下信息:
Jul 22 15:55:10 vm-centos setroubleshoot: Plugin Exception restorecon
Jul 22 15:55:10 vm-centos setroubleshoot: SELinux is preventing /usr/sbin/httpd from write access on the directory . For complete SELinux messages. run sealert -l b741594f-af42-4368-9a8a-5f6fffe97da5
Jul 22 15:55:10 vm-centos python: SELinux is preventing /usr/sbin/httpd from write access on the directory .
***** Plugin httpd_write_content (92.2 confidence) suggests ***************
If you want to allow httpd to have write access on the directory
Then you need to change the label on '$FIX_TARGET_PATH'
Do
# semanage fcontext -a -t httpd_sys_rw_content_t '$FIX_TARGET_PATH'
# restorecon -v '$FIX_TARGET_PATH'
***** Plugin catchall_boolean (7.83 confidence) suggests ******************
If you want to allow httpd to unified
Then you must tell SELinux about this by enabling the 'httpd_unified' boolean.
Do
setsebool -P httpd_unified 1
***** Plugin catchall (1.41 confidence) suggests **************************
If you believe that httpd should be allowed write access on the directory 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:
# grep httpd /var/log/audit/audit.log | audit2allow -M mypol
# semodule -i mypol.pp
看那个有92.2%信心的提示,问题就出在这里。 /var/www/html/
里面的东西的类型都是 httpd_sys_content_t
是只读的,然而我却想往里面写东西,这必然会导致错误。所以我们只要把这里面的东西改成 httpd_sys_rw_content_t
类型即可。
chcon
chcon
可以改变文件或者文件夹的类型属性,类似于 chmod
之类的命令。比如可以这么用:
chcon -R -t httpd_sys_rw_content_t /var/www/html/
ls -laZ
ls
命令在加上 -Z
之后就可以查看有关 SELinux 的文件属性。
[root@vm-centos ~]# ls -laZ /var/www/html/cookielesscookies/
drwxrwxr-x. abcdabcd987 apache unconfined_u:object_r:httpd_sys_rw_content_t:s0 .
drwxrwxr-x. root apache system_u:object_r:httpd_sys_rw_content_t:s0 ..
-rwxrwxr-x. abcdabcd987 apache unconfined_u:object_r:httpd_sys_rw_content_t:s0 config.php
-rwxrwxr-x. abcdabcd987 apache unconfined_u:object_r:httpd_sys_rw_content_t:s0 etags.jpg
-rwxrwxr-x. abcdabcd987 apache unconfined_u:object_r:httpd_sys_rw_content_t:s0 fingerprinting.jpg
drwxrwxr-x. abcdabcd987 apache unconfined_u:object_r:httpd_sys_rw_content_t:s0 .git
-rwxrwxr-x. abcdabcd987 apache unconfined_u:object_r:httpd_sys_rw_content_t:s0 .htaccess
-rwxrwxr-x. abcdabcd987 apache unconfined_u:object_r:httpd_sys_rw_content_t:s0 index.php
-rw-rw-r--. abcdabcd987 apache unconfined_u:object_r:httpd_sys_rw_content_t:s0 LICENSE
-rw-rw-r--. abcdabcd987 apache unconfined_u:object_r:httpd_sys_rw_content_t:s0 README.md
drwxrwxr-x. abcdabcd987 apache unconfined_u:object_r:httpd_sys_rw_content_t:s0 sessions