Apache:权限被拒绝:'/var/www/html/cgi-test/first.pl' 执行失败

Apache:权限被拒绝:'/var/www/html/cgi-test/first.pl' 执行失败

所以,我是 CGI/Perl 的新手,我正在尝试将基于 perl 的 Web 应用程序移动到新服务器。

我的新服务器是 CentOS 7,它运行 Apache HTTPD 2.4.6。

我正在尝试通过 HTTP 请求来获取基本的 Perl CGI 工作。

Web 请求返回“500 内部服务器错误”

错误日志显示“权限被拒绝”:

[Tue May 12 16:56:44.604660 2015] [cgi:error] [pid 12302] [client 10.0.2.2:56693] AH01215: (13)Permission denied: exec of '/var/www/html/cgi-test/first.pl' failed
[Tue May 12 16:56:44.604708 2015] [cgi:error] [pid 12302] [client 10.0.2.2:56693] End of script output before headers: first.pl

我的 CGI 脚本位于 /var/www/html/cgi-test/first.pl

它看起来像这样:

#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "Hello, World.";

在 cgi-test 目录中,权限如下所示:

drwxr-xr-x. 2 root root 21 May 12 16:48 .
drwxr-xr-x. 4 root root 32 May 12 16:48 ..
-r-xr-xr-x. 1 root root 76 May 12 16:48 first.pl

Perl 位于正常位置,并且我认为具有正常权限

[root@localhost cgi-test]# ls -al /usr/bin/perl
-rwxr-xr-x. 2 root root 11400 Mar  6 05:07 /usr/bin/perl

我的 httpd.conf 是默认的。我刚刚添加了以下部分,以便在我的 cgi-test 目录中允许 cgi:

<Directory "/var/www/html/cgi-test">
    Options +ExecCGI
    AddHandler cgi-script .cgi .pl
</Directory>

为了消除 suexec 导致此问题的可能性,我将其从 /usr/sbin/suexec 移至另一个文件名。

Httpd 以用户“apache”的身份运行,该用户属于“apache”组

[root@localhost cgi-test]# ps -Af | grep httpd
root     12298     1  0 16:56 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache   12299 12298  0 16:56 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache   12300 12298  0 16:56 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache   12301 12298  0 16:56 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache   12302 12298  0 16:56 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
apache   12303 12298  0 16:56 ?        00:00:00 /usr/sbin/httpd -DFOREGROUND
root     12342 12260  0 17:20 pts/0    00:00:00 grep --color=auto httpd
[root@localhost cgi-test]# groups apache
apache : apache

我已尝试以 apache 身份运行该脚本,它运行正常,没有任何问题。

[root@localhost cgi-test]# su -s /bin/bash apache
bash-4.2$ perl /var/www/html/cgi-test/first.pl 
Content-type: text/html

Hello, World.bash-4.2$

大概我碰到了 Apache 的一些安全预防措施。关于这可能是什么,有很多相互矛盾的建议。任何帮助都非常感谢。

答案1

我从你自己的回答中看到,这是一个 SELinux 权限问题,因为尝试在非标准目录中的 apache 内部运行 CGI 脚本。

解决权限问题并保持 SELinux 处于“强制”模式的正确方法是将适当的上下文应用于自定义 CGI 脚本目录中的文件,从而提高服务器的安全性。如果要将其作为永久目录,则应更改 selinux 策略以自动创建具有适当权限的新文件。

您可以使用以下命令检查 cgi-bin 目录的 selinux 策略:

$ semanage fcontext --list | grep cgi-bin 
 (...)
/var/www/[^/]*/cgi-bin(/.*)?                       all files          system_u:object_r:httpd_sys_script_exec_t:s0
/var/www/html/[^/]*/cgi-bin(/.*)?                  all files          system_u:object_r:httpd_sys_script_exec_t:s0
 (...)

这意味着在 apache 的标准 cgi-bin 目录中创建的每个文件都将被自动赋予 SELinux 类型httpd_sys_script_exec_t并可由 httpd 执行,所以cgi-test目录中的文件也应该具有这些功能。

笔记:下面显示的示例基于 CentOS/RHEL6,经过最终调整后它应该可以同样适用于 RHEL7。

临时解决方案

你可以简单地用以下命令改变你的 perl 脚本的 SELinux 上下文:

$ chcon -t httpd_sys_script_exec_t /var/www/html/cgi-test/first.pl

使用以下命令检查文件的 SELinux 属性ls -laZ

$ ls -laZ /var/www/html/cgi-test/first.pl
-rwxr-xr-x. root root system_u:object_r:httpd_sys_script_exec_t:s0 /var/www/html/cgi-test/first.pl

但是,如果此文件系统上有 SELinux 重新标记操作,属性将恢复为默认值,并且它将再次停止工作。每次添加新的 CGI 脚本时也必须执行此操作。

确定解决方案

您可以通过为自定义 CGI 目录及其所有包含的子目录和文件添加规则来更改 SELinux 策略。

这是通过以下semanage命令完成的(在policycoreutils-pythonRPM 包中可用):

$ semanage fcontext -a -t httpd_sys_script_exec_t "/var/www/html/cgi-test(/.*)?"

这需要一段时间才能运行。更改策略后,自定义目录中创建的任何新文件都将具有新的上下文。对于已经存在的文件,您可以使用以下方式手动应用策略:

$ restorecon -R -v /var/www/html/cgi-test

您可以使用以下命令检查新添加的规则:

$ semanage fcontext --list | grep cgi-test

答案2

如果您无法从 Apache 用户执行 Perl,则会出现此错误。请检查您的用户是否为 Apache 用户,并检查您是否能够从 Perl 脚本中提到的 Perl 位置执行相同的 Perl 脚本。

在我的例子中,我使用的是 /bin/perl,它指向 /root 中的其他 Perl。我的 Apache 用户没有权限执行此 Perl。

您需要进行更改,以便 Apache 用户能够从 /root 位置执行 Perl 或只是更改 Perl 位置。

我改变了 /root Perl 的权限并且它起作用了。

答案3

答案是 SELinux 阻止了对脚本的访问。

谢谢阿尔法迈克维克多提出这个答案。

CentOS 7 上默认启用 SELinux 并阻止 perl / CGI。我使用 /usr/bin/sestatus 确认它已启用

在旧服务器上,SELinux 已被完全禁用。

答案4

确保已在 apache 配置中添加了 ScriptAlias,如下所示

ScriptAlias /cgi-test/ /var/www/html/cgi-test/

还可以尝试将 FollowSymLinks 添加到 Options 指令中。

相关内容