1

Background

Config of server I want to mimic

I have access to a CentOS 7 server with cPanel/WHM installed, running EasyApache4 with the following configuration:

# /usr/local/cpanel/bin/rebuild_phpconf --current
DEFAULT PHP: ea-php56
ea-php55 SAPI: cgi
ea-php56 SAPI: cgi
ea-php70 SAPI: cgi
# rpm -qa|grep ruid2
# rpm -qa|grep suexec
ea-apache24-mod_suexec-2.4.33-5.5.1.cpanel.x86_64

I believe suEXEC is enabled, because /var/log/apache2/error_log contains entries like AH01232: suEXEC mechanism enabled (wrapper: /usr/sbin/suexec).

I believe neither mod_ruid2, nor suPHP, nor PHP-FPM, nor FastCGI, nor DSO (aka mod_php) are enabled.

This server has a user, myuser, whose ~/public_html/public/ directory is used as the document root for the website mywebsite.com. (These are not the real names, obviously.)

If I put, in that directory, a PHP file called whoami.php with the following contents (note the lack of a shebang):

<html>
<body>
<p>sapi_name:      <?php print php_sapi_name();    ?></p>
<p>exec whoami:    <?php print exec('whoami');     ?></p>
<p>system whoami:  <?php system('whoami');         ?></p>
<p>system id -a:   <?php system("id -a");          ?></p>
<p>getcurrentuser: <?php print get_current_user(); ?></p>
</body>
</html>

and visit it in the browser at http://mywebsite.com/whoami.php (note that this is not using the http://mywebsite.com/~myuser/whoami.php UserDir URL format), it renders as:

sapi_name: cgi-fcgi
exec whoami: myuser
system whoami: myuser
system id -a: uid=1002(myuser) gid=1003(myuser) groups=1003(myuser)
getcurrentuser: myuser

Behaviour I want to mimic

This is true even if it lacks the executable permission, as follows:

$ ls -l /home/myuser/public_html/public/whoami.php | cut -d' ' -f1,3,4,9
-r-------- myuser myuser /home/myuser/public_html/public/whoami.php

Normally, Apache 2.4 in CGI mode cannot run a non-executable file like this, if I understand the documentation correctly:

Of course, the file will have to exist, and be executable, and return output in a particular way, or Apache will return an error message.

However, cPanel/WHM seems to do something to alter this fact. According to the WHM documentation:

CGI

The CGI handler executes PHP applications through the mod_cgi or the mod_cgid Apache modules. If you install the suEXEC module, the system executes PHP applications as the user that owns the VirtualHost that served the request. If you uninstall the suEXEC module, the system executes PHP applications as the nobody system user. The system provides mod_cgi and mod_ruid2 by default.

You can customize the CGI handler's settings in the PHP .user.ini file. […]

Important:

If you enable a per-user module, such as suEXEC or Ruid2, you can execute PHP scripts with permissions of 0400. If you disable a per-user module, such as suEXEC or Ruid2, you can execute PHP scripts with permissions of 0444.

I.e. even without suEXEC or Ruid2 enabled, EasyApache4 is somehow able to make Apache process non-executable PHP files as CGI scripts rather than just serving them as static files.

Questions

I have a different CentOS 7 machine, not routable from the internet, and for development only. It does not have cPanel/WHM installed. Security is not a priority for this machine, and it has SELinux disabled. Mimicking cPanel/WHM's behaviour is a priority for this machine: top priority.

  1. On this machine, how would I persuade Apache 2.4 to run PHP files whose permissions are 0400 or 0444, and that lack a shebang, as CGI scripts via PHP 5.6, rather than just serving them as static files? I.e. how would I achieve the something alluded to above? I'm happy to compile Apache with non-standard suEXEC configuration options, if needed.
  2. In particular, how can I do this while serving them without needing use a UserDir URL (i.e. without the /~myuser part of a URL such as http://mywebsite.com/~myuser/mypage.php)?
  3. How would I do all this while also ensuring that those files are run by myuser, via suEXEC, rather than by the apache or httpd or nobody user?

If you can answer all three questions at a stroke, so much the better, but even if you can answer just the first one, that would be very helpful! Thank you :)

  • I would advise not making so many questions at once. The thematic of PHP security is also a complicated theme too. ruid2 has also its own peculiarities, and I do not recommend it to unexperienced users. – Rui F Ribeiro Apr 28 '18 at 18:51
  • 1
    @RuiFRibeiro, thanks. I have now clarified that the second machine is a development box, not routable from the Internet. Its purpose is to mimic the EasyApache4 box, not to be secure in itself. Also, AFAICT, the EasyApache4 box is not running Ruid2. – sampablokuper Apr 28 '18 at 18:57
  • @RuiFRibeiro, as for not asking several questions at once, the motivation for my question is that I am not certain how to accomplish all of those things simultaneously. The different components are sufficiently tightly coupled that asking questions about just one or the other would eliminate important context and likely not yield a working solution. But if you have a better suggestion, I am open to it. – sampablokuper Apr 28 '18 at 19:05
  • @RuiFRibeiro, thanks for your good intentions, but IMO those links are off-topic. The first link is about using mod_ruid2 for security, but (a) AFAICT I shouldn't need to install mod_ruid2 in order to mimic the EA4 box because the latter doesn't appear to be using it, and (b) I don't need the dev box to be secure against malicious clients because I am its only client. The second and third links are about blocking or throttling unwanted clients by using modsecurity and/or mod-evasive, neither of which is relevant to my question or my use-case. Thanks again. – sampablokuper Apr 28 '18 at 19:18
  • @RuiFRibeiro, thanks, but that link just compares different PHP handlers. It does not help to answer my question. I appreciate your desire to help, but I'm afraid that posting off-topic links is not helpful. It just creates clutter. I would be grateful if you could refrain from doing it. Thanks. – sampablokuper Apr 28 '18 at 19:32
0

Here is a way to achieve this which is OK for a private dev environment that is only being used for that purpose, but should never be used on an internet-routable machine.

Execute these rather radical commands:

# chown myuser:myser /usr/bin
# chown myuser:myser /usr/bin/php-cgi

then:

# chmod 711 /home/myuser
# chmod 755 /home/myuser/public_html
#

Also, (re-)compile Apache to have suEXEC's AP_DOC_ROOT="/", and (re-)install it.

Modify /etc/httpd/conf/httpd.conf along these lines:

ServerRoot "/etc/httpd"
Listen 80
Include conf.modules.d/*.conf
ServerAdmin root@localhost
#ServerName example.local
ServerName localhost    
User apache
Group apache
<Directory />
    AllowOverride none
    Require all granted
</Directory>
<VirtualHost *:80>
  DocumentRoot "/home/myuser/public_html/public"
  SuexecUserGroup myuser myuser
  <IfModule alias_module>
    ScriptAlias /cgi-bin/ /home/myuser/public_html/public/cgi-bin/
  </IfModule>
  <Directory "/home/myuser/public_html/public">
    Options Indexes FollowSymLinks ExecCGI
    AllowOverride None
    Require all granted
    AddHandler cgi-script .cgi .pl
  </Directory>
</VirtualHost>
<IfModule dir_module>
  DirectoryIndex index.php index.cgi index.html index.htm
</IfModule>

and modify /etc/httpd/conf.d/php.conf roughly like so:

ScriptAlias /local-bin /usr/bin
AddHandler application/x-httpd-php5 php
Action application/x-httpd-php5 /local-bin/php-cgi

Finally, (re-)start Apache.

This is the best approach that I found prior to asking the question above. However, there are almost certainly better alternatives, and I would like to learn about them, hence my posting the question. (For instance, installing a php-cgi binary in the user's home directory should in principle be a viable and less drastic measure than modifying the ownership of the system binary and its directory.)

So, please feel free to upvote this answer if it helped you, or to comment constructively if it did not help you, but I will hold off marking it as "correct" for a while, in the hope that better answers emerge.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.