如何在Apache中使用SuExec在UbuntuVPS上运行CGI脚本
状态: 已弃用
本文介绍了不再受支持的 Ubuntu 版本。 如果您当前正在运行运行 Ubuntu 12.04 的服务器,我们强烈建议您升级或迁移到受支持的 Ubuntu 版本:
原因: Ubuntu 12.04 已于 2017 年 4 月 28 日终止生命周期 (EOL) and no longer receives security patches or updates. This guide is no longer maintained.
请参阅: 本指南可能仍可用作参考,但可能不适用于其他 Ubuntu 版本。 如果可用,我们强烈建议使用为您正在使用的 Ubuntu 版本编写的指南。 您可以使用页面顶部的搜索功能来查找更新的版本。
介绍
Apache Web 服务器是世界上最流行的 Web 服务器。 它可用于在多种不同上下文中向访问者提供静态和动态 Web 内容。
生成动态内容的最常见方法之一是使用 CGI
或通用网关接口。 这提供了一种执行脚本的标准方法,这些脚本生成可以用各种编程语言编写的 Web 内容。
在网络空间内运行任何类型的可执行代码都会带来一定的风险。 在本指南中,我们将演示如何使用 suexec
模块实现 CGI 脚本,它允许您以一种不会不必要地提升权限的方式运行脚本。
先决条件
在本指南中,我们将使用标准 LAMP(Linux、Apache、MySQL、PHP)安装配置 Ubuntu 12.04 VPS。 我们假设您已经安装了这些基本组件并让它们在基本配置中工作。
要了解 如何在 Ubuntu 上安装 LAMP 堆栈,请单击此处。
在该教程之后,我们将引用处于初始状态的软件。
如何启用 CGI 脚本
在 Ubuntu 的 Apache 配置中,CGI 脚本实际上已经配置在特定的 CGI 目录中。 该目录默认为空。
CGI 脚本可以是任何能够输出 HTML 或 Web 浏览器可以呈现的其他对象或格式的程序。
如果我们进入 Apache 配置目录,并查看 Apache 在 mods-enabled
目录中启用的模块,我们会发现一个启用此功能的文件:
less /etc/apache2/mods-enabled/cgi.load
LoadModule cgi_module /usr/lib/apache2/modules/mod_cgi.so
该文件包含启用 CGI 模块的指令。 这允许我们在配置中使用此功能。
尽管模块已加载,但它实际上并没有自己提供任何脚本内容。 它必须在特定的 Web 环境中明确启用。
我们将查看默认的 Apache 虚拟主机文件,看看它是如何做到的:
sudo nano /etc/apache2/sites-enabled/000-default
在这里,让我们设置服务器名称以引用我们的域名或 IP 地址:
ServerName your_domain_or_IP_address ServerAdmin your_email_address 。 . .
我们可以在文件中看到适用于 CGI 脚本的部分:
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ <Directory "/usr/lib/cgi-bin"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory>
让我们分解这部分配置的作用。
ScriptAlias
指令赋予 Apache 执行特定目录中包含的脚本的权限。 在这种情况下,目录是 /usr/lib/cgi-bin/
。 第二个参数提供脚本目录的文件路径,而第一个参数 /cgi-bin/
提供 URL 路径。
这意味着当您访问时,将执行位于 /usr/lib/cgi-bin
目录中的名为“script.pl”的脚本:
your_domain.com /cgi-bin/script.pl
其输出将返回到 Web 浏览器以呈现页面。
Directory
容器包含适用于 /usr/lib/cgi-bin
目录的规则。 您会注意到一个提到 CGI 的选项:
Options +ExecCGI ...
这个选项实际上是不必要的,因为我们正在为一个已经被 ScriptAlias
声明为 CGI 目录的目录设置选项。 不过它不疼,所以你可以保持原样。
如果您希望将 CGI 文件放在 ScriptAlias 之外的目录中,则必须将这两个选项添加到目录部分:
选项 +ExecCGI AddHandler cgi-script .pl .rb [被视为 CGI 脚本的扩展]
检查完文件后,保存并关闭它。 如果您进行了任何更改,请重新启动 Web 服务器:
sudo service apache2 restart
制作测试 CGI 脚本
我们将创建一个基本的、简单的 CGI 脚本来展示使脚本正确执行所需的步骤。
正如我们在上一节中看到的,在我们的配置中为 CGI 脚本指定的目录是 /usr/lib/cgi-bin
。 非 root 用户无法写入此目录,因此我们必须使用 sudo:
sudo nano /usr/lib/cgi-bin/test.pl
我们给文件一个“.pl”扩展名,因为这将是一个 Perl 脚本,但 Apache 将尝试运行此目录中的任何文件,并根据其第一行将其传递给适当的程序。
我们将通过以下命令开始脚本来指定脚本应该由 Perl 解释:
#!/usr/bin/perl
在此之后,脚本 必须 输出的第一件事就是将生成的内容类型。 这是必要的,以便网络浏览器知道如何显示它给出的输出。 我们将使用 Perl 的常规打印函数打印出 HTML 内容类型,即“text/html”。
print "Content-type: text/html\n\n";
在此之后,我们可以执行任何必要的函数或计算来在我们的网站上生成我们想要的文本。 在我们的示例中,我们不会生成任何不会像纯 HTML 那样容易的东西,但是您可以看到,如果您的脚本更复杂,这允许动态内容。
前面的两个组件和我们实际的 HTML 内容结合起来构成了以下脚本:
#!/usr/bin/perl print "Content-type: text/html\n\n"; print "<html><head><title>Hello There...</title></head>"; print "<body>"; print "<h1>Hello, World.</h1><hr>"; print "<p>This is some regular text.</p>"; print "<p>The possibilities are great.</p>"; print "</body></html>";
保存并关闭文件。
现在,我们有一个文件,但它没有被标记为可执行文件。 让我们改变一下:
sudo chmod 755 /usr/lib/cgi-bin/test.pl
现在,如果我们导航到我们的域名,然后是 CGI 目录 (/cgi-bin/),然后是我们的脚本名称 (test.pl),我们应该会看到脚本的输出。
将您的浏览器指向:
your_domain.com /cgi-bin/test.pl
您应该会看到如下所示的内容:
不是很令人兴奋,但渲染正确。
如果我们选择查看页面的源代码,我们将只看到提供给打印函数的参数,减去内容类型标题:
如何启用 SuExec
在将脚本设置为任何人都可以执行时,存在一些隐含的安全问题。 理想情况下,脚本应该只能由单个锁定用户执行。 我们可以通过使用 suexec
模块来设置这种情况。
我们实际上将安装一个修改后的 suexec 模块,该模块允许我们配置它运行的目录。 通常,如果不从源代码重新编译,这将无法配置。
使用以下命令安装备用模块:
sudo apt-get install apache2-suexec-custom
现在,我们可以通过键入以下命令启用该模块:
sudo a2enmod suexec
接下来,我们将创建一个拥有我们的脚本文件的新用户。 如果我们有多个站点正在服务,每个站点都可以有自己的用户和组:
sudo adduser script_user
随意输入所有提示(包括密码提示)。 这个用户不需要充实。
接下来,让我们在这个新用户的主目录中创建一个脚本目录:
sudo mkdir /home/script_user/scripts
Suexec 需要非常严格地控制谁可以写入目录。 让我们将所有权转移给 script_user 用户并更改权限,以便其他人无法写入目录:
sudo chown script_user:script_user /home/script_user/scripts sudo chmod 755 /home/script_user/scripts
接下来,让我们创建一个脚本文件并将上面的脚本复制并粘贴到其中:
sudo -u script_user nano /home/script_user/scripts/attempt.pl
#!/usr/bin/perl print "Content-type: text/html\n\n"; print "<html><head><title>Hello There...</title></head>"; print "<body>"; print "<h1>Hello, World.</h1><hr>"; print "<p>This is some regular text.</p>"; print "<p>The possibilities are great.</p>"; print "</body></html>";
接下来使其可执行。 我们只会让我们的 script_user 对文件有任何权限。 这就是 suexec 模块允许我们做的事情:
sudo chmod 700 /home/script_user/scripts/attempt.pl
接下来,我们将编辑我们的 Apache 虚拟主机配置,以允许我们的新用户执行脚本。
打开默认的虚拟主机文件:
sudo nano /etc/apache2/sites-enabled/000-default
首先,让我们创建 CGI 目录。 不像我们上面那样使用 ScriptAlias
指令,让我们演示如何使用常规的 Alias
目录与 ExecCGI
选项和 SetHandler
指令相结合.
添加此部分:
Alias /scripts/ /home/script_user/scripts/ <Directory "/home/script_user/scripts"> Options +ExecCGI SetHandler cgi-script </Directory>
这允许我们通过转到“/scripts”子目录来访问我们的 CGI 脚本。 要启用 suexec 功能,请将此行添加到“Directory”部分之外,但在“VirtualHost”部分中:
SuexecUserGroup script_user script_user
保存并关闭文件。
我们还需要指定 suexec 认为有效目录的位置。 这就是我们可定制的 suexec 版本允许我们做的事情。 打开 suexec 配置文件:
sudo nano /etc/apache2/suexec/www-data
在这个文件的顶部,我们只需要添加脚本目录的路径。
/home/script_user/scripts/
保存并关闭文件。
现在,剩下要做的就是重新启动 Web 服务器:
sudo service apache2 restart
如果我们打开浏览器并在此处导航,我们可以看到脚本的结果:
your_domain.com /scripts/attempt.pl
请注意,配置 suexec 后,您的普通 CGI 目录将无法正常工作,因为它没有通过 suexec 要求的严格测试。 这是旨在控制脚本具有哪些权限的行为。
结论
您现在可以创建脚本并以相对安全的方式执行它们。 CGI 脚本对于在您的网站上快速包含动态内容非常有帮助。 Suexec 允许您锁定此功能以获得更高的安全性。
使用 suexec 时要小心,因为如果配置不正确,它实际上会产生更多的安全漏洞。 要了解此设置的潜在漏洞,请研究 setuid 配置。