分类: LINUX
2008-06-01 14:46:54
SELinux 的 audit2allow 工具程序
一、基本用法:
The command audit2allow can receive input via three methods. Default is from standard input (STDIN). Using the -i option reads input from /var/log/messages, and the -d option reads input from dmesg output.
也就是说 audit2allow 有三种接收输入的方法:
1.预设是由标准输入 STDIN 接收
2.使用 -i 选项,如 -i /var/log/messages or -i /var/log/audit/audit.log (若有启动 auditd 时)
3.使用 -d 选项,可以接收 dmesg 的讯息
例如:
[root@candyz:/var/log] audit2allow -i /var/log/messages
allow getty_t var_log_t:file write;
[root@candyz:/var/log] audit2allow -d
allow getty_t var_log_t:file write;
当看到一堆如下的 avc denied 之类的讯息时,要怎么解决?
audit(1146842928.277:2): avc: denied { getattr } for pid=3357 comm="httpd"
name="test.php" dev=hda6 ino=137349 scontext=root:system_r:httpd_t
tcontext=root:object_r:var_t tclass=file
* 在 RHEL4 或 FC3 上的解决方式:
$ cd /etc/selinux/targeted/src/policy/
使用 -d 从 dmesg 读取 avc messages
$ audit2allow -d -o domain/misc/local.te
or 使用 -l -i /var/log/messages 读取 /var/log/messages 的 avc messages
# 若有启动 auditd 则要改读 /var/log/audit/audit.log
$ audit2allow -l -i /var/log/messages -o domain/misc/local.te
or 直接从 STDIN 读取 avc messages, 如 /tmp/avcs 里面放的就是储存好的 avc messages
$ audit2allow -o domain/misc/local.te < /tmp/avcs
最后再执行 make load 即可
$ make load
然后就会看到如 avc granted 之类的讯息了
* 在 FC5 上的解决方式:
[root@candyz:~] cd /etc/selinux/targeted/modules/
[root@candyz:/etc/selinux/targeted/modules] audit2allow -M local -d
Generating type enforcment file: local.te
Compiling policy
checkmodule -M -m -o local.mod local.te
semodule_package -o local.pp -m local.mod
******************** IMPORTANT ***********************
In order to load this newly created policy package into the kernel,
you are required to execute
semodule -i local.pp
同样的,除了用 audit2allow -M local -d 从 dmesg 读取讯息外
也可以用 audit2allow -M local -l -i /var/log/messages
或是 audit2allow -M local -i /var/log/audit/audit.log
或是 audit2allow -M local < /tmp/avcs
最后记得要执行 semodule -i local.pp 来 load new policy to kernel,这点很重要
[root@candyz:/etc/selinux/targeted/modules] semodule -i local.pp
另外也可以用 audit2allow 来产生 local.te 档案,然后可以去编辑或修改 local.te
[root@candyz:~] cd /etc/selinux/targeted/modules/
[root@candyz:/etc/selinux/targeted/modules] audit2allow -m local -l -i /var/log/messages > local.te
# 然后再执行 checkmodule 指令来产生 local.mod
[root@candyz:/etc/selinux/targeted/modules] checkmodule -M -m -o local.mod local.te
# 然后再执行 semodule_package 指令来产生 local.pp
[root@candyz:/etc/selinux/targeted/modules] semodule_package -o local.pp -m local.mod
同样的,最后记得要执行 semodule -i local.pp 来 load new policy to kernel,这点很重要
[root@candyz:/etc/selinux/targeted/modules] semodule -i local.pp
或是产生 local.te 档后,直接执行:
[root@candyz:/etc/selinux/targeted/modules] make -f /usr/share/selinux/devel/Makefile
这样等于是执行 checkmodule + semodule_package
最后记得再 semodule -i local.pp 即可
对于刚使用Redhat Enterprise Linux4 或Fedora Core 2以上/CentOS 4的用户,一定会为Apache经常无法正常运转,报以"Permission denied"等错误而大为不解,甚至大为恼火。
其实这是因为这些系统里激活了SELinux,而用户的apache配置与SELinux的配置策略有抵触产生的,只有通过适当调整,使apache的配置和访问符合策略才能正常使用。
现在下面来分析一下SELinux中有关httpd(apache)的context定义(略有删节)
/home/[^/]+/((www)|(web)|(public_html))(/.+)? system_u:object_r:httpd_user_content_t
/var/www(/.*)? system_u:object_r:httpd_sys_content_t
/var/www/cgi-bin(/.*)? system_u:object_r:httpd_sys_script_exec_t
/usr/lib/cgi-bin(/.*)? system_u:object_r:httpd_sys_script_exec_t
/var/www/perl(/.*)? system_u:object_r:httpd_sys_script_exec_t
/var/www/icons(/.*)? system_u:object_r:httpd_sys_content_t
/var/cache/httpd(/.*)? system_u:object_r:httpd_cache_t
/etc/vhosts -- system_u:object_r:httpd_config_t
/usr/sbin/httpd -- system_u:object_r:httpd_exec_t
/usr/sbin/apache(2)? -- system_u:object_r:httpd_exec_t
/usr/sbin/suexec -- system_u:object_r:httpd_suexec_exec_t
/var/log/httpd(/.*)? system_u:object_r:httpd_log_t
/var/log/apache(2)?(/.*)? system_u:object_r:httpd_log_t
/var/log/cgiwrap\.log.* -- system_u:object_r:httpd_log_t
/var/cache/ssl.*\.sem -- system_u:object_r:httpd_cache_t
/var/cache/mod_ssl(/.*)? system_u:object_r:httpd_cache_t
/var/run/apache(2)?\.pid.* -- system_u:object_r:httpd_var_run_t
/var/lib/httpd(/.*)? system_u:object_r:httpd_var_lib_t
/var/lib/php/session(/.*)? system_u:object_r:httpd_var_run_t
/etc/apache-ssl(2)?(/.*)? system_u:object_r:httpd_config_t
/usr/lib/apache-ssl(/.*)? -- system_u:object_r:httpd_exec_t
/usr/sbin/apache-ssl(2)? -- system_u:object_r:httpd_exec_t
/var/log/apache-ssl(2)?(/.*)? system_u:object_r:httpd_log_t
/var/run/apache-ssl(2)?\.pid.* -- system_u:object_r:httpd_var_run_t
/var/run/gcache_port -s system_u:object_r:httpd_var_run_t
/var/lib/squirrelmail/prefs(/.*)? system_u:object_r:httpd_squirrelmail_t
/usr/bin/htsslpass -- system_u:object_r:httpd_helper_exec_t
/usr/share/htdig(/.*)? system_u:object_r:httpd_sys_content_t
/var/lib/htdig(/.*)? system_u:object_r:httpd_sys_content_t
针对上述的内容,可以对如下的几个常见问题进行简单处理:
1.phpmyadmin在非默认/var/www/html目录下无法运转
通常类似的情况都是在配置了虚拟主机时,访问/phpmyadmin等提示403访问拒绝,日志里也提示Permission denied,这是因为phpmyadmin防止的目录及文件本身属性不符合context要求。
假设phpmyadmin放在/web目录下,那么执行:
chcon -R -t httpd_user_content_t /web
则会令/web及其下所有子目录/文件,包括phpmyadmin文件都获得了httpd_user_content_t的属性,如果其传统的Unix属性对httpd来说是可读的话,再重新访问一下就应该可以了。
2./home目录下的虚拟主机无法运转
与问题1也是类似的,不过根据上文中context的定义,/home目录下必须是用户的$HOME/www或public_html或web目录才是httpd_user_content_t类型,因此建议将要作为web页面的内容放置在用户的$HOME/www或web或public_html里,并确保其属性是httpd_user_content_t,使用如下命令查看:
ls -Z /home/abc/
drwxr-xr-x abc abc user_u:object_r:user_home_dir_t tmp
drwxrwxr-x abc abc user_u:object_r:httpd_user_content www
如不是,则可通过chcon来逐级目录及文件更改,直至最后能访问:
chcon -R -t httpd_user_content_t /home/abc/web
chcon -t user_home_dir_t /home/abc
3.CGI程序无法运行
如果cgi程序放在/var/www/cgi-bin/里也无法执行,遇到403或500错误的话,可以检查cgi程序的属性,按SELinux contexts文件里定义的,/var/www/cgi-bin/里必须是httpd_sys_script_exec_t 属性。通过ls -Z查看,如果不是则通过如下命令更改:
chcon -t httpd_sys_script_exec_t /var/www/cgi-bin/*.cgi
如果是虚拟主机里的cgi,则参考问题2使之能正常使用普通的功能后,再通过chcon设置cgi文件的context为httpd_sys_script_exec_t即可。
4.Setuid/gid 程序无法运行
例如早期的SqWebMail及qmailadmin等,需要setuid/gid的支持,但在SELinux下这将受到严格限制。第一种方法是比较彻底的办法,能保留系统的安全性,通过:
audit2allow -l -i /var/log/messages
将SELinux拒绝的信息转换为相应的policy allow指令,将这些指令添加到SELinux policy 的src里相应的配置文件,重新生成policy并加载。但这样做相对比较麻烦。
另一个方法最简单,但将使apache得不到保护。首先确定SELinux 类型是targeted的:
cat /etc/selinux/config|grep SELINUXTYPE
然后,使apache脱离SELinux保护:
setsebool -P httpd_disable_trans 1
然后重启动apache:
/etc/init.d/httpd restart
这样所有apache强制的检查都失效,需要setuid/gid的程序可以正常使用。但这样带来了增加漏洞的危险,对于迫切需要运行而又很急的情况,本方法是一个最大限度减少系统安全缺失的最后办法。对于取消SELinux 未必是一个好方法。
SELinux 是从FC3和AS4起,所提供的一个高级安全特性。
它可以对系统上运行的任何一个应用程序做权限上的控制。
版本低于FC3/AS4的Linux,没有提供SELinux特性,或者默认就是禁用这个特性的。
为了运行Plesk,需要对SELinux做一些修改,否则可能会造成某些服务运行不正常或者启动失败。
SElinux把所有的拒绝信息输出到:/var/log/messages 位置。
如果某个服务比如bind不能正常启动,请查询messages文件来确认是否是SELinux造成服务不能运行。
这些信息可以很简单的使用/usr/bin/audit2allow来更改规则。
运行如下命令,查看哪些程序的访问被SELinux拦截掉了:
cat /var/log/messages | /usr/bin/audit2allow
然后,把列出的被拒绝的访问加入到SELinux的配置文件中。
通常,建议加入如下内容:
/etc/selinux/targeted/src/policy/domains/program/apache.te
----------------------------------------------------------------
allow httpd_sys_script_t var_t:file { execute getattr };
allow httpd_t self:tcp_socket connect;
allow httpd_t usr_t:dir write;
allow httpd_t var_log_t:file { append getattr setattr };
allow httpd_sys_script_t devlog_t:sock_file write;
allow httpd_sys_script_t self:unix_dgram_socket { connect create write };
allow httpd_sys_script_t ld_so_cache_t:file execute;
allow httpd_sys_script_t syslogd_t:unix_dgram_socket sendto;
allow httpd_sys_script_t var_t:dir { add_name remove_name write };
allow httpd_sys_script_t var_t:fifo_file write;
allow httpd_sys_script_t var_t:file { create execute_no_trans link read unlink write };
----------------------------------------------------------------
/etc/selinux/targeted/src/policy/domains/program/named.te
----------------------------------------------------------------
allow named_t named_zone_t:chr_file read;
allow ndc_t named_zone_t:file { getattr read write };
allow named_t named_zone_t:dir { add_name write read remove_name };
allow named_t named_zone_t:file { create unlink write };
----------------------------------------------------------------
/etc/selinux/targeted/src/policy/domains/program/syslogd.te
----------------------------------------------------------------
allow syslogd_t usr_t:file append;
allow syslogd_t usr_t:file ioctl;
-------------------------------------------------------------------------
最后使用如下命令重新加载SELinux:
make -C /etc/selinux/targeted/src/policy reload
重灌 server 并启用 SELinux 以后,发现 asp.net 应用程序无法启动.
经过研读文件之后,大致上对 SELinux 有一定的了解.
SELinux 本身纯粹是作安全性的加强,所以不管是 user, file, directory, socket, process...等等的,都另外有了 security context,作为安全性的第二道防线.
当系统要存取这些资源的时候,首先会使用原有的 unix permission 去作检查,接着 SELinux 会再依照 security context 作第二道检查,当检查没问题之后,才会允许存取.
SELinux 里面有所谓的 identity, domain, type, security context, target context 等等物件...
大致上来说, identity 决定身份, domain 决定 process 能干么, type 决定 process 以外的对象可以干么, security context, target context 则是 identity + domain + type 的组合. policy 则用来定义 security context, target context 可以存取哪些对象. (这些组合,真的很让人头晕.)
存取的指令也蛮多的:
要看档案目录的 security context, 可以加上 -Z (ls -Z)
要看process的 security context, 也可以用 -Z (ps axZ)
要看自己的security context,可以用 id
要改security context, 可以用 chcon
要 reset security context, 可以用 restorecon
...
整个研读完之后,发现应该是 policy 问题.
今天下午用Google去找到这篇文章,发现有这么个工具 - audit2allow,他是在 policycoreutils 套件里面的指令,可以根据 warning message 产生 policy,省掉不少编写的麻烦.
为了要能重新编译 policy, 你需要安装 selinux-policy-targeted-sources 这个套件
yum install selinux-policy-targeted-sources
再使用 audit2allow 这个指令,从 dmesg 里面分析 warning, 并将产生以后的 policy 写入到 mono.policy 档案中.
audit2allow -d -o mono.policy
接着把 mono.policy 更名为 local.te, 放到 /etc/selinux/targeted/src/policy/domains/misc/ .
放完之后,切换到 /etc/selinux/targeted/src/policy
强制 selinux 重新编译 policy
make load
最后重新启动我的 Apache server,就大功告成了.