我将 Perl CGI 脚本从旧的 RedHat Linux 机器移至较新的 CentOS Linux 机器,某些system
命令不再起作用。
例如system("ls -l filename");
工作正常,但system("lp -d printer filename");
返回lp: Permission denied
。
我已经检查了目录和文件的权限,我可以使用运行相同的 CGI 脚本sudo -u apache scriptname
,然后麻烦的system
命令就可以正常工作。
据我所知,Apache httpd 没有被 chrooted,并且没有任何明显的东西httpd.conf
(几乎安装好了)。
那么我为什么会得到lp: Permission Denied
?
这是一个测试脚本
#!/usr/bin/perl
use strict;
use warnings;
#use CGI::Carp qw(fatalsToBrowser);
BEGIN {
open (STDERR, '>&STDOUT') || die "cant merge STDERR $!\n";
$|=1;
}
print "Content-Type: text/plain\n\n";
print "TEST\n\n";
psys('id');
psys('which lp');
psys('ls -l /tmp/po-list.19025.ps');
psys('ls -ld /usr /usr/bin /usr/bin/lp');
psys('ls -l /etc/alternatives/print-lp');
psys('ls -l /usr/bin/lp.cups');
psys('lp -d laser1 /tmp/po-list.19025.ps');
psys('ls /home | wc -l');
print "Finished\n";
sub psys {
my $command = shift;
print "# $command\n";
system($command);
print "\n";
}
以下是浏览器接收的内容
TEST
# id
uid=48(apache) gid=48(apache) groups=48(apache) context=user_u:system_r:httpd_sys_script_t:s0
# which lp
/usr/bin/lp
# ls -l /tmp/po-list.19025.ps
-rw-r--r-- 1 apache apache 2309 Aug 30 15:59 /tmp/po-list.19025.ps
# ls -ld /usr /usr/bin /usr/bin/lp
drwxr-xr-x 15 root root 4096 Sep 22 2011 /usr
drwxr-xr-x 2 root root 36864 Aug 30 12:06 /usr/bin
lrwxrwxrwx 1 root root 26 Mar 18 2011 /usr/bin/lp -> /etc/alternatives/print-lp
# ls -l /etc/alternatives/print-lp
lrwxrwxrwx 1 root root 16 Sep 22 2011 /etc/alternatives/print-lp -> /usr/bin/lp.cups
# ls -l /usr/bin/lp.cups
-rwxr-xr-x 1 root root 18792 Mar 30 2011 /usr/bin/lp.cups
# lp -d laser1 /tmp/po-list.19025.ps
lp: Permission denied
# ls /home | wc -l
ls: /home: Permission denied
0
Finished
答案1
selinux!
事实证明我有linux系统安装并启用。经过一些配置,问题就解决了
线索是
context=user_u:system_r:httpd_sys_script_t:s0
输出中的字符串id
selinux
文件夹中的存在/
我找到了解决方案http://www.thedumbterminal.co.uk/php/knowledgebase/article/131这让我检查了 audit.log - 在那里我注意到了comm="lp"
(denied
即 lp 命令被拒绝)
以下为血腥细节,希望对其他人有帮助
# grep 'comm="lp' /var/log/audit/audit.log | tail -n 2
type=AVC msg=audit(1346348949.002:30060): avc: denied { name_connect } for pid=20130 comm="lp" dest=631 scontext=user_u:system_r:httpd_sys_script_t:s0 tcontext=system_u:object_r:ipp_port_t:s0 tclass=tcp_socket
type=SYSCALL msg=audit(1346348949.002:30060): arch=c000003e syscall=42 success=no exit=-13 a0=4 a1=2b0a50c0b108 a2=10 a3=7ffffa3aeba4 items=0 ppid=20123 pid=20130 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="lp" exe="/usr/bin/lp.cups" subj=user_u:system_r:httpd_sys_script_t:s0 key=(null)
# grep 'comm="lp' /var/log/audit/audit.log | tail -n 3 | audit2allow
#============= httpd_sys_script_t ==============
allow httpd_sys_script_t ipp_port_t:tcp_socket name_connect;
# grep 'comm="lp' /var/log/audit/audit.log | tail -n 3 | audit2allow -M secommands
******************** IMPORTANT ***********************
To make this policy package active, execute:
semodule -i secommands.pp
# ls secom*
secommands.pp secommands.te
# /usr/sbin/semodule -i secommands.pp
# wget -O - http://localhost/cgi-bin/t4.pl
--2012-08-30 19:05:09-- http://localhost/cgi-bin/t4.pl
Resolving localhost... 127.0.0.1
Connecting to localhost|127.0.0.1|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/plain]
Saving to: `STDOUT'
[<=> ] 0 --.-K/s TEST
# /usr/bin/lp -d laser1 /tmp/po-list.19025.ps
request id is laser1-23 (1 file(s))
# ls /home | wc -l
ls: /home: Permission denied
0
Finished
[ <=> ] 2,034 --.-K/s in 0.03s
2012-08-30 19:05:09 (56.9 KB/s) - `-' saved [2034]
lp 命令有效,我并不担心无法进入ls
/home - 这是我喜欢的安全功能。