最後更新: 2015-07-15
介紹
suEXEC is based on a setuid "wrapper" program that is called by the main Apache web server.
This wrapper is called when an HTTP request is made for a CGI or SSI program
that the administrator has designated to run as a userid other than that of the main server.
When such a request is made, Apache provides the suEXEC wrapper with the program's name and
the user and group IDs under which the program is to execute.
條件:
* suEXEC does not allow root to execute CGI/SSI programs.
* target userid/groupid ABOVE the minimum ID number (AP_UID_MIN)
* target user/group the same as the program's user/group
* target program / directory NOT writable by anyone (所以 wrapper 既 permission 要係 755)
* Only one user (the Apache user) is allowed to execute this program. (AP_HTTPD_USER)
* safe hierarchical (AP_DOC_ROOT) (target CGI or SSI program's path 不可以有 a leading '/' or have a '..')
Apache:
httpd -V | grep suexec
-D SUEXEC_BIN="/usr/sbin/suexec"
The binary image suexec is installed in the directory defined by the --sbindir option.
(Default location is "/usr/local/apache2/bin/suexec")
在 httpd.conf 要有
LoadModule suexec_module modules/mod_suexec.so
suexec
suexec -V # displays the compile options
* For security reasons all configuration options are changeable only at compile time.
-D AP_DOC_ROOT="/var/www"
-D AP_GID_MIN=100
-D AP_HTTPD_USER="apache"
-D AP_LOG_EXEC="/var/log/httpd/suexec.log"
-D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
-D AP_UID_MIN=500
-D AP_USERDIR_SUFFIX="public_html"
* suExec does not allow symlinks
不能用 FcgidWrapper /usr/bin/php-cgi .php <-- 因為 CGI program 不在 AP_DOC_ROOT 內
解決方案:
Create a wrapper script for each web site in a subdirectory of /var/www;
the wrapper script will then call the PHP binary /usr/lib/cgi-bin/php
* For security and efficiency reasons, all suEXEC requests must remain
within either a top-level document root for virtual host requests, or one top-level personal document root for userdir requests.
準備
groupadd webuser1
useradd -s /bin/false -d /var/www/webuser1 -m -g web1 webuser1
mkdir -p /var/www/webuser1/web
# owner
chown webuser1:webuser1 /var/www/webuser1/web
# 放 CGI wrapper 的 Folder 都要有嚴格的 permission, 否則會有
[2014-07-23 14:59:40]: uid: (3334/???) gid: (3334/???) cmd: ???.sh [2014-07-23 14:59:40]: target uid/gid (3334/3334) mismatch with directory (0/0) or program (3334/3334)
# 因為 .htaccess 要有 1
chmod 771 /var/www/webuser1/web
public_html 的 permission 要是 701
否則會有
(13)Permission denied: /home/vhosts/???/public_html/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable
Apache Configure
/etc/httpd/conf.d/fcgid.conf
# Use FastCGI to process .fcg .fcgi & .fpl scripts AddHandler fcgid-script fcg fcgi fpl # Sane place to put sockets and shared memory file FcgidIPCDir /run/mod_fcgid FcgidProcessTableFile /run/mod_fcgid/fcgid_shm
# vhost example
<VirtualHost *> # suexe SuexecUserGroup user_account user_group # We run a single PHP FastCGI server # which will launch as many children # as necessary. <Directory ... > Options ... ExecCGI ... </Directory> # fcgid FCGIWrapper /var/www/php-fcgi-scripts/suexec/webuser1/mywrapper .php AddHandler fcgid-script .php </VirtualHost>
# ispconfig example
<IfModule mod_fcgid.c> DocumentRoot /var/www/ispconfig/ SuexecUserGroup ispconfig ispconfig IPCCommTimeout 7200 MaxRequestLen 15728640 <Directory /var/www/ispconfig/> Options -Indexes +FollowSymLinks +MultiViews +ExecCGI AllowOverride AuthConfig Indexes Limit Options FileInfo <FilesMatch "\.php$"> SetHandler fcgid-script </FilesMatch> FCGIWrapper /var/www/php-fcgi-scripts/ispconfig/.php-fcgi-starter .php Require all granted </Directory> </IfModule>
/var/www/php-fcgi-scripts/ispconfig/.php-fcgi-starter
#!/bin/sh PHPRC=/etc/ export PHPRC export PHP_FCGI_MAX_REQUESTS=5000 export PHP_FCGI_CHILDREN=1 exec /usr/bin/php-cgi -d magic_quotes_gpc=off -d session.save_path=/usr/local/ispconfig/interface/temp
Wrapper
cd /var/www/php-fcgi-scripts/suexec
mkdir webuser1
chmod 755 webuser1
vi mywrapper
#!/bin/sh export PHP_FCGI_MAX_REQUESTS=1000 exec /usr/bin/php-cgi
chown user_account:user_group mywrapper
chmod 755 mywrapper
Configuring & Installing suEXEC
--enable-suexec
enables the suEXEC feature
--enable-suexec-capabilities
# suexec binary will instead be installed with only the setuid/setgid "capability" bits
# ( subset of full root priviliges )
# Default: "setuid/setgid root" <-- full privileges of the root user
--with-suexec-bin=PATH
The path to the suexec binary must be hard-coded in the server for security reasons.
(/usr/sbin/suexec)
--with-suexec-caller=UID
The username under which Apache normally runs. This is the only user allowed to execute this program.
--with-suexec-docroot=DIR
Define as the DocumentRoot set for Apache.
--with-suexec-safepath=PATH
Default: "/usr/local/bin:/usr/bin:/bin"
-with-suexec-userdir=DIR
processed by mod_userdir
Define to be the subdirectory under users' home directories where suEXEC access should be allowed.
All executables under this directory will be executable by suEXEC as the user so they should be "safe" programs.
Default value is "public_html"
--with-suexec-safepath=PATH
Define a safe PATH environment to pass to CGI executables. Default value is "/usr/local/bin:/usr/bin:/bin".
--with-suexec-logfile
--with-suexec-syslog
suEXEC wrapper will write log information to this file
Testing
whoami.php
<?php system("id -a"); ?>
# 沒有 suexec 時 uid=48(apache) "gid=48(apache) groups=48(apache)"
順利行到會見在 /var/log/httpd/suexec.log 內有
[2014-07-23 16:44:27]: uid: (3334/???) gid: (3334/???) cmd: wrapper
ps aux | grep 3334
3334 22663 0.0 0.2 58160 12228 ? S 17:08 0:00 /usr/bin/php-cgi
Custom php.ini for Each Web Site
cp /etc/php5/cgi/php.ini /var/www/web1/
chown web1:web1 /var/www/web1/php.ini
vi /var/www/php-fcgi-scripts/web1/php-fcgi-starter
#!/bin/sh export PHP_INI_SCAN_DIR=/home/user/domain/conf export PHPRC=/home/user/conf export PHP_FCGI_MAX_REQUESTS=5000 export PHP_FCGI_CHILDREN=8 exec /usr/lib/cgi-bin/php
reload php.ini:
killall php-cgi