# suEXEC支持
**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内部究竟做了些什么事情,以及哪些确保系统安全的预防措施。
**suEXEC**是基于一个setuid的"封装"程序,该程序由"主"Apache web服务器调用。当一个HTTP请求的是管理员指定的、以不同于"主"服务器用户身份运行的CGI或SSI程序时,该封装程序将被调用。处理这样的请求时,Apache将被请求的程序名及其UID和GID提供给suEXEC封装器。
封装器(wrapper)通过处理下面所描述的步骤,来决定封装的成功或失败:如果有任意一个条件为假,程序将把错误情况记录到日志中,退出并返回错误信息。否则继续执行。(以下所说的"程序"均指"CGI/SSI程序")
1. **用户使用了合法的系统账号来执行封装程序了吗?**
确保运行封装器的是一个系统中确实存在的用户。
2. **封装器被调用时,使用的参数个数正确吗?**
封装器仅在使用了正确数量的参数调用时才会执行。Apache web服务器知道正确的参数格式是什么。如果封装器没有收到正确数量的参数,则说明要么被黑客攻击,要么Apache二进制代码中suEXEC的部分出了问题。
3. **这个合法的用户被允许运行封装器吗?**
这个用户是可以运行封装器的用户吗?仅有一个用户(Apache用户)被允许运行封装器。
4. **目标CGI/SSI程序有不安全的分级路径索引吗?**
目标CGI/SSI程序包含了"/"开头或者有".."后向路径索引吗?这些都是不允许的;并且目标程序必须位于suEXEC的文档根目录下。(参见下面的:`--with-suexec-docroot=_DIR_`)
5. **目标程序的所属用户名合法吗?**
目标程序的所属用户名存在吗?
6. **目标程序的所属用户组合法吗?**
目标程序的所属用户组存在吗?
7. **目标程序的所属用户名不是超级用户吗?**
目前,suEXEC不允许root执行CGI/SSI程序。
8. **目标程序所属用户的UID高于最小UID值吗?**
最小UID值是在配置中指定的。你可以指定允许执行CGI/SSI程序的最小UID值,这样可以保证不会和系统账号冲突。
9. **目标程序的所属用户组不是超级用户组吗?**
目前,suEXEC不允许root组用户执行CGI/SSI程序。
10. **目标程序所属用户组的GID高于最小GID值吗?**
最小GID值是在配置中指定的。你可以指定允许执行CGI/SSI程序的最小GID值,这样可以保证不会和系统账号冲突。
11. **封装器能够成功地变为目标用户和组吗?**
这里就是程序变为目标用户和组的关键步骤了。我们是通过调用setuid和setgid来实现的。在组访问列表中,和该用户相关的所有组信息都将被初始化。
12. **能够切换到程序所在的目录吗?**
如果不存在,将无法包含程序文件。如果不能切换一般也表示目录不存在。
13. **这个目录在Apache的网络空间中吗?**
如果是对于服务器的一般请求,那么请求的目录是在suEXEC的根文档目录下吗?如果请求的是一个用户目录,那么该目录是在suEXEC配置的该用户的根目录下吗?(参见:[suEXEC配置选项](#calibre_link-548))
14. **该目录不具有其他用户可写的权限吗?**
我们不想把目录开放给其他人;只有属主才可以改变该目录中的内容。
15. **目标CGI/SSI程序存在吗?**
如果不存在,当然无法继续运行。
16. **目标CGI/SSI程序不可以被其他用户改写吗?**
我们不想给其他人有修改程序的权限。
17. **目标程序尚未被setuid或者setgid ?**
我们不想要执行的程序被再次改变UID/GID。
18. **目标用户和组与程序的用户和组相同吗?**
用户是这个文件的属主吗?
19. **我们可以成功清除进程的环境变量并保证操作的安全性吗?**
suEXEC通过建立一个安全的可执行路径(在配置中定义)来清除该进程的环境变量,同时只传送在安全环境变量列表(配置中定义)中所列出的环境变量。
20. **可以成功的变为目标程序并执行吗?**
这里就是suEXEC结束,并开始运行目标程序的地方了。
这是suEXEC封装器标准操作方式的安全模型。它有些严格,并强加了CGI/SSI设计上的限制。但它是仔细考虑过安全之后一步步发展起来的模型。
更多关于该安全模型如何根据服务器的配置来限制使用者的权限,以及恰当的suEXEC安装步骤能够避免的安全隐患,请参见[警告和举例](#calibre_link-579)部分。
## 配置和安装suEXEC
继续我们的探险 ...
**suEXEC配置选项**
`--enable-suexec`
该选项启用默认禁止的suEXEC功能。并同时至少提供一个 `--with-suexec-xxxxx` 选项,以使APACI使用suEXEC功能来处理请求。
`--with-suexec-bin=_PATH_`
出于安全考虑,`suexec`二进制程序的路径必须用这个选项指定并硬编码在服务器里。比如:`--with-suexec-bin=/usr/sbin/suexec`
`--with-suexec-caller=_UID_`
Apache运行时所用的[UID](#calibre_link-168)。这是唯一允许执行程序的用户。
`--with-suexec-userdir=_DIR_`
定义suEXEC允许访问的用户宿主目录下的子目录。suEXEC将以用户身份执行这个目录下的所有可执行程序,所以这些程序必须是"安全程序"。如果使用"简单的"`UserDir`指令(即不带"*"),则此处应该被设置为相同的值。当`UserDir`指令所指向的目录与"passwd"文件所指定的用户宿主目录不同时,suEXEC将不会正常工作,其默认值是"public_html"。如果所支持的虚拟主机对每个用户有不同的`UserDir` ,则应该把他们集中在同一个父目录下,而用这个参数指向这个父目录。**如果配置不当,"~userdir"下的cgi请求将无效!**
`--with-suexec-docroot=_DIR_`
定义Apache的`DocumentRoot`。它是除`UserDir`外suEXEC唯一可以使用的目录。其默认目录是 `--datadir` 值所指定的带有"/htdocs"的后缀的目录,比如:如果配置了"`--datadir=/home/apache`",那么"/home/apache/htdocs"目录将作为suEXEC处理器的文档根目录。
`--with-suexec-uidmin=_UID_`
定义了suEXEC目标用户的最低UID。对大多数系统,一般是500或100。默认值是100
`--with-suexec-gidmin=_GID_`
定义了suEXEC目标组的最低GID。对大多数系统,是100,默认值也是100。
`--with-suexec-logfile=_FILE_`
它定义了suEXEC用于记录所做的事情以及发生的错误的日志文件名(对审核和排错很有用),默认文件名是"suexec_log",并位于标准的日志文件目录中(`--logfiledir`)。
`--with-suexec-safepath=_PATH_`
定义传给CGI程序的一个安全的PATH环境变量的值。默认值是"/usr/local/bin:/usr/bin:/bin"
**编译和安装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。
## 启用和禁用suEXEC
Apache在启动过程中,会在 `--sbindir` 选项指定的目录(默认为:"/usr/local/apache/sbin/suexec")中寻找`suexec`。如果Apache找到了一个正确配置的suEXEC处理器,会在错误日志中记录以下信息:
```
[notice] suEXEC mechanism enabled (wrapper: <var class="calibre40">/path/to/suexec</var>)
```
如果服务器启动后没有这个信息,那么很可能是服务器没找到适当的处理器,或者是这个执行程序没有安装_setuid root_。
如果要在Apache服务器运行过程中打开suEXEC功能,则必须停止并重新启动Apache。用一个简单的HUP或USR1信号来重新启动是不够的。
如果要关闭suEXEC功能,应该删除`suexec`文件,并停止和重新启动Apache。
## 使用suEXEC
对CGI程序的请求仅在下述两种情况下才会调用suEXEC包装:对一个含`SuexecUserGroup`指令的虚拟主机发起请求,或者该请求由`mod_userdir`模块处理。
**虚拟主机:**
使用suEXEC处理器的方法之一是在`VirtualHost`定义中使用`SuexecUserGroup`指令。通过设置这个指令来确定不同于主服务器的UID,所有对CGI资源的请求将以`<VirtualHost>`所定义的_User_和_Group_身份执行。如果`<VirtualHost>`中没有这个指令,则将以主服务器的UID身份执行。
**用户目录:**
由`mod_userdir`处理的请求会调用suEXEC处理器以被请求的用户目录所属的UID执行CGI程序。此功能的唯一要求是,此用户必须有CGI执行权限,并且其脚本符合上述[安全检查](#calibre_link-581)的要求。参见 `--with-suexec-userdir` [编译选项](#calibre_link-548)。
## 调试suEXEC
如上所述,suEXEC处理器会在 `--with-suexec-logfile` 选项所指定的日志文件中记录信息。如果你感觉配置和安装不正常,可以查看这个日志以及服务器的错误日志。
## 谨防Jabberwock:警告和举例
**注意!**这部分文档可能还没有完成。查看最新的修订版本,请到Apache开发组的[在线文档](http://httpd.apache.org/docs/2.2/suexec.html)。
以下是有关限制和服务器安装的几个注意事项,在提交任何关于suEXEC的"bugs"以前,请仔细阅读。
* **suEXEC注意事项**
* 层次限制
出于安全和效率考虑,所有suEXEC请求必须被限制在虚拟主机或者用户目录的顶层。举例来说,如果你配置了4个虚拟主机,你必须把所有虚拟主机的文档根目录都安置在同一个主Apache目录中,这样才能为虚拟主机启用suEXEC。(例子以后会有的)
* suEXEC的PATH环境变量
改变这个变量的值是危险的,必须确保其中每个路径都是**可以信任**的目录。你不会希望谁都可以在你的服务器上安装特洛伊木马。
* 改变suEXEC的代码
重申,如果你不清楚你在干什么就尽量避免,否则会带来**大麻烦**的。
- Apache HTTP Server Version 2.2 文档 [最后更新:2006年3月21日]
- 版本说明
- 从1.3升级到2.0
- 从2.0升级到2.2
- Apache 2.2 新特性概述
- Apache 2.0 新特性概述
- The Apache License, Version 2.0
- 参考手册
- 编译与安装
- 启动Apache
- 停止和重启
- 配置文件
- 配置段(容器)
- 缓冲指南
- 服务器全局配置
- 日志文件
- 从URL到文件系统的映射
- 安全方面的提示
- 动态共享对象(DSO)支持
- 内容协商
- 自定义错误响应
- 地址和端口的绑定(Binding)
- 多路处理模块
- Apache的环境变量
- Apache处理器的使用
- 过滤器(Filter)
- suEXEC支持
- 性能方面的提示
- URL重写指南
- Apache虚拟主机文档
- 基于主机名的虚拟主机
- 基于IP地址的虚拟主机
- 大批量虚拟主机的动态配置
- 虚拟主机示例
- 深入研究虚拟主机的匹配
- 文件描述符限制
- 关于DNS和Apache
- 常见问题
- 经常问到的问题
- Apache的SSL/TLS加密
- SSL/TLS高强度加密:绪论
- SSL/TLS高强度加密:兼容性
- SSL/TLS高强度加密:如何...?
- SSL/TLS Strong Encryption: FAQ
- 如何.../指南
- 认证、授权、访问控制
- CGI动态页面
- 服务器端包含入门
- .htaccess文件
- 用户网站目录
- 针对特定平台的说明
- 在Microsoft Windows中使用Apache
- 在Microsoft Windows上编译Apache
- Using Apache With Novell NetWare
- Running a High-Performance Web Server on HPUX
- The Apache EBCDIC Port
- 服务器和支持程序
- httpd - Apache超文本传输协议服务器
- ab - Apache HTTP服务器性能测试工具
- apachectl - Apache HTTP服务器控制接口
- apxs - Apache 扩展工具
- configure - 配置源代码树
- dbmmanage - 管理DBM格式的用户认证文件
- htcacheclean - 清理磁盘缓冲区
- htdbm - 操作DBM密码数据库
- htdigest - 管理用于摘要认证的用户文件
- httxt2dbm - 生成RewriteMap指令使用的dbm文件
- htpasswd - 管理用于基本认证的用户文件
- logresolve - 解析Apache日志中的IP地址为主机名
- rotatelogs - 滚动Apache日志的管道日志程序
- suexec - 在执行外部程序之前切换用户
- 其他程序
- 杂项文档
- 与Apache相关的标准
- Apache模块
- 描述模块的术语
- 描述指令的术语
- Apache核心(Core)特性
- Apache MPM 公共指令
- Apache MPM beos
- Apache MPM event
- Apache MPM netware
- Apache MPM os2
- Apache MPM prefork
- Apache MPM winnt
- Apache MPM worker
- Apache模块 mod_actions
- Apache模块 mod_alias
- Apache模块 mod_asis
- Apache模块 mod_auth_basic
- Apache模块 mod_auth_digest
- Apache模块 mod_authn_alias
- Apache模块 mod_authn_anon
- Apache模块 mod_authn_dbd
- Apache模块 mod_authn_dbm
- Apache模块 mod_authn_default
- Apache模块 mod_authn_file
- Apache模块 mod_authnz_ldap
- Apache模块 mod_authz_dbm
- Apache模块 mod_authz_default
- Apache模块 mod_authz_groupfile
- Apache模块 mod_authz_host
- Apache模块 mod_authz_owner
- Apache模块 mod_authz_user
- Apache模块 mod_autoindex
- Apache模块 mod_cache
- Apache模块 mod_cern_meta
- Apache模块 mod_cgi
- Apache模块 mod_cgid
- Apache模块 mod_charset_lite
- Apache模块 mod_dav
- Apache模块 mod_dav_fs
- Apache模块 mod_dav_lock
- Apache模块 mod_dbd
- Apache模块 mod_deflate
- Apache模块 mod_dir
- Apache模块 mod_disk_cache
- Apache模块 mod_dumpio
- Apache模块 mod_echo
- Apache模块 mod_env
- Apache模块 mod_example
- Apache模块 mod_expires
- Apache模块 mod_ext_filter
- Apache模块 mod_file_cache
- Apache模块 mod_filter
- Apache模块 mod_headers
- Apache模块 mod_ident
- Apache模块 mod_imagemap
- Apache模块 mod_include
- Apache模块 mod_info
- Apache模块 mod_isapi
- Apache模块 mod_ldap
- Apache模块 mod_log_config
- Apache模块 mod_log_forensic
- Apache模块 mod_logio
- Apache模块 mod_mem_cache
- Apache模块 mod_mime
- Apache模块 mod_mime_magic
- Apache模块 mod_negotiation
- Apache模块 mod_nw_ssl
- Apache模块 mod_proxy
- Apache模块 mod_proxy_ajp
- Apache模块 mod_proxy_balancer
- Apache模块 mod_proxy_connect
- Apache模块 mod_proxy_ftp
- Apache模块 mod_proxy_http
- Apache模块 mod_rewrite
- Apache模块 mod_setenvif
- Apache模块 mod_so
- Apache模块 mod_speling
- Apache模块 mod_ssl
- Apache模块 mod_status
- Apache模块 mod_suexec
- Apache模块 mod_unique_id
- Apache模块 mod_userdir
- Apache模块 mod_usertrack
- Apache模块 mod_version
- Apache模块 mod_vhost_alias
- Developer Documentation for Apache 2.0
- Apache 1.3 API notes
- Debugging Memory Allocation in APR
- Documenting Apache 2.0
- Apache 2.0 Hook Functions
- Converting Modules from Apache 1.3 to Apache 2.0
- Request Processing in Apache 2.0
- How filters work in Apache 2.0
- Apache 2.0 Thread Safety Issues
- 词汇和索引
- 词汇表
- 指令索引
- 指令速查
- 模块索引
- 站点导航