©
This document usesPHP Chinese website manualRelease
suEXEC特性使得Apache可以使用与调用web服务器的用户不同的用户身份来运行CGI和SSI程序。而通常情况下,CGI或者SSI程序执行时使用和web服务器相同的用户身份。
正确运用该特性,可以减少很多因为提供用户执行私有CGI或者SSI程序所带来的安全风险。但如果配置不当的话,则可能引起很多问题,使你的计算机产生更多的安全漏洞。如果你对管理setuid root程序以及可能导致的安全问题不熟悉的话,我们强烈建议你不要使用suEXEC。
在我们开始切入正题之前,你必须明白Apache开发组以及本文档所做的假设。
首先,我们假设你正在使用类UNIX操作系统,只有这类操作系统才具有setuid和setgid命令。所有的其他命令行的例子也是如此。其他的操作系统平台,即使也支持suEXEC,但是它的配置可能和我们所讲的并不相同。
第二,我们假设你熟悉计算机的安全和管理计算机的一些基本概念。这关系到如何正确理解setuid/setgid操作以及对你的系统可能带来的各种影响和不同的安全等级。
第三,我们假设你正在使用源代码未经修改的suEXEC版本。所有suEXEC的代码都经过开发者的仔细查验并做过大量测试。在这些代码中,人们采取了各种预防措施,使之简单、健壮、安全。修改这些代码可能会导致预料之外的问题和安全隐患。所以我们强烈地建议你不要修改代码,除非你精通安全编程,并愿意和Apache开发组共享成果。
第四,也是最后一点,Apache开发组已经决定默认不安装suEXEC。suEXEC的配置需要管理员细致关注各个细节。在仔细考察过关于suEXEC的各种设置方法后,管理员应该使用标准的安装方法来安装suEXEC。设置的参数应该经过仔细推敲,以保证系统的安全运行。Apache开发组希望通过限制suEXEC的安装,仅使那些经过细致理解,并有能力运用它的管理员来使用。
你还想使用suEXEC吗?还想?很好!那我们开始吧!
在我们开始配置和安装suEXEC之前,我们需要先讨论一下它的安全模型。这样,你才能更好的理解suEXEC内部究竟做了些什么事情,以及哪些确保系统安全的预防措施。
suEXEC是基于一个setuid的"封装"程序,该程序由"主"Apache web服务器调用。当一个HTTP请求的是管理员指定的、以不同于"主"服务器用户身份运行的CGI或SSI程序时,该封装程序将被调用。处理这样的请求时,Apache将被请求的程序名及其UID和GID提供给suEXEC封装器。
封装器(wrapper)通过处理下面所描述的步骤,来决定封装的成功或失败:如果有任意一个条件为假,程序将把错误情况记录到日志中,退出并返回错误信息。否则继续执行。(以下所说的"程序"均指"CGI/SSI程序")
确保运行封装器的是一个系统中确实存在的用户。
封装器仅在使用了正确数量的参数调用时才会执行。Apache web服务器知道正确的参数格式是什么。如果封装器没有收到正确数量的参数,则说明要么被黑客攻击,要么Apache二进制代码中suEXEC的部分出了问题。
这个用户是可以运行封装器的用户吗?仅有一个用户(Apache用户)被允许运行封装器。
目标CGI/SSI程序包含了"/"开头或者有".."后向路径索引吗?这些都是不允许的;并且目标程序必须位于suEXEC的文档根目录下。(参见下面的:--with-suexec-docroot=DIR
)
目标程序的所属用户名存在吗?
目标程序的所属用户组存在吗?
目前,suEXEC不允许root执行CGI/SSI程序。
最小UID值是在配置中指定的。你可以指定允许执行CGI/SSI程序的最小UID值,这样可以保证不会和系统账号冲突。
目前,suEXEC不允许root组用户执行CGI/SSI程序。
最小GID值是在配置中指定的。你可以指定允许执行CGI/SSI程序的最小GID值,这样可以保证不会和系统账号冲突。
这里就是程序变为目标用户和组的关键步骤了。我们是通过调用setuid和setgid来实现的。在组访问列表中,和该用户相关的所有组信息都将被初始化。
如果不存在,将无法包含程序文件。如果不能切换一般也表示目录不存在。
如果是对于服务器的一般请求,那么请求的目录是在suEXEC的根文档目录下吗?如果请求的是一个用户目录,那么该目录是在suEXEC配置的该用户的根目录下吗?(参见:suEXEC配置选项)
我们不想把目录开放给其他人;只有属主才可以改变该目录中的内容。
如果不存在,当然无法继续运行。
我们不想给其他人有修改程序的权限。
我们不想要执行的程序被再次改变UID/GID。
用户是这个文件的属主吗?
suEXEC通过建立一个安全的可执行路径(在配置中定义)来清除该进程的环境变量,同时只传送在安全环境变量列表(配置中定义)中所列出的环境变量。
这里就是suEXEC结束,并开始运行目标程序的地方了。
这是suEXEC封装器标准操作方式的安全模型。它有些严格,并强加了CGI/SSI设计上的限制。但它是仔细考虑过安全之后一步步发展起来的模型。
更多关于该安全模型如何根据服务器的配置来限制使用者的权限,以及恰当的suEXEC安装步骤能够避免的安全隐患,请参见警告和举例部分。
继续我们的探险 ...
suEXEC配置选项
--enable-suexec
--with-suexec-xxxxx
选项,以使APACI使用suEXEC功能来处理请求。
--with-suexec-bin=PATH
suexec
二进制程序的路径必须用这个选项指定并硬编码在服务器里。比如:
--with-suexec-bin=/usr/sbin/suexec
--with-suexec-caller=UID
--with-suexec-userdir=DIR
UserDir
指令(即不带"*"),则此处应该被设置为相同的值。当
UserDir
指令所指向的目录与"passwd"文件所指定的用户宿主目录不同时,suEXEC将不会正常工作,其默认值是"public_html"。如果所支持的虚拟主机对每个用户有不同的
UserDir
,则应该把他们集中在同一个父目录下,而用这个参数指向这个父目录。
如果配置不当,"~userdir"下的cgi请求将无效!
--with-suexec-docroot=DIR
DocumentRoot
。它是除
UserDir
外suEXEC唯一可以使用的目录。其默认目录是
--datadir
值所指定的带有"/htdocs"的后缀的目录,比如:如果配置了"
--datadir=/home/apache
",那么"/home/apache/htdocs"目录将作为suEXEC处理器的文档根目录。
--with-suexec-uidmin=UID
--with-suexec-gidmin=GID
--with-suexec-logfile=FILE
--logfiledir
)。
--with-suexec-safepath=PATH
编译和安装suEXEC处理器
若用--enable-suexec
打开了suEXEC功能,那么执行make
命令时(Apache自带的)suexec
二进制文件就会被自动建立。所有组件编译完毕后执行make install
命令进行安装时,suexec
文件将被安装在--sbindir
选项指定的目录中,默认为"/usr/local/apache2/sbin/suexec"。
注意,安装过程需要root权限。为了使suEXEC处理器可以设置UID,其所有者必须为root
,并且文件模式中的执行位必须设置为1(允许执行)。
设置许可权限
虽然suEXEC包装会检查以确保它的调用者就是配置选项
--with-suexec-caller
所指定的用户。但是总是存在这样的可能性:一个系统或者库在suEXEC执行用户身份检查之前调用它,这样就存在一个可利用的漏洞。通常,避免这种问题的最佳办法是,使用文件系的统权限来确保只有Apache组用户运行的程序才能执行suEXEC。
如果你的web-server是按照如下所示进行配置的:
User www
Group webgroup
并且suexec
被安装在"/usr/local/apache2/sbin/suexec"目录,你应当运行以下命令:
chgrp webgroup /usr/local/apache2/bin/suexec
chmod 4750 /usr/local/apache2/bin/suexec
这将确保只有Apache组用户运行的程序才能执行suEXEC。
Apache在启动过程中,会在--sbindir
选项指定的目录(默认为:"/usr/local/apache/sbin/suexec")中寻找suexec
。如果Apache找到了一个正确配置的suEXEC处理器,会在错误日志中记录以下信息:
[notice] suEXEC mechanism enabled (wrapper:/path/to/suexec)
如果服务器启动后没有这个信息,那么很可能是服务器没找到适当的处理器,或者是这个执行程序没有安装setuid root。
如果要在Apache服务器运行过程中打开suEXEC功能,则必须停止并重新启动Apache。用一个简单的HUP或USR1信号来重新启动是不够的。
如果要关闭suEXEC功能,应该删除suexec
文件,并停止和重新启动Apache。
对CGI程序的请求仅在下述两种情况下才会调用suEXEC包装:对一个含SuexecUserGroup
指令的虚拟主机发起请求,或者该请求由mod_userdir
模块处理。
虚拟主机:
使用suEXEC处理器的方法之一是在VirtualHost
定义中使用SuexecUserGroup
指令。通过设置这个指令来确定不同于主服务器的UID,所有对CGI资源的请求将以
所定义的User和Group身份执行。如果
中没有这个指令,则将以主服务器的UID身份执行。
用户目录:
由mod_userdir
处理的请求会调用suEXEC处理器以被请求的用户目录所属的UID执行CGI程序。此功能的唯一要求是,此用户必须有CGI执行权限,并且其脚本符合上述安全检查的要求。参见--with-suexec-userdir
编译选项。
如上所述,suEXEC处理器会在--with-suexec-logfile
选项所指定的日志文件中记录信息。如果你感觉配置和安装不正常,可以查看这个日志以及服务器的错误日志。
注意!这部分文档可能还没有完成。查看最新的修订版本,请到Apache开发组的在线文档。
以下是有关限制和服务器安装的几个注意事项,在提交任何关于suEXEC的"bugs"以前,请仔细阅读。
出于安全和效率考虑,所有suEXEC请求必须被限制在虚拟主机或者用户目录的顶层。举例来说,如果你配置了4个虚拟主机,你必须把所有虚拟主机的文档根目录都安置在同一个主Apache目录中,这样才能为虚拟主机启用suEXEC。(例子以后会有的)
改变这个变量的值是危险的,必须确保其中每个路径都是可以信任的目录。你不会希望谁都可以在你的服务器上安装特洛伊木马。
重申,如果你不清楚你在干什么就尽量避免,否则会带来大麻烦的。