Centos – Dangers to giving Apache user a shell

apache-2.2centosrhel6

tl;dr – What are the dangers of giving Apache a shell in /etc/passwd?


I'm working on getting mod_evasive set up with Apache to fight DOS attempts. I use the DOSSystemCommand to run a script that adds the offending IP address to a BANNED chain in iptables.

I've found that the only way that I can get this process to work is if I change Apache's shell from /sbin/nologin to /bin/bash. But it's really only one part of the script that fails by not having the shell changed. Here's the DOSSystemCommand line and the script that it runs:

 DOSSystemCommand    "/usr/bin/sudo /bin/bash /var/www/html/ban_ip.sh %s"

and the script … (note I'm just in testing.. which is why I have verbose output and short banning periods)

#!/bin/bash

IP=$1
IPTABLES=/sbin/iptables

sudo $IPTABLES -I BANNED -p tcp -s $IP --dport 443 -j DROP
sudo $IPTABLES -I BANNED -p tcp -s $IP --dport 80 -j DROP

echo sudo $IPTABLES -v -D BANNED -p tcp -s $IP --dport 80 -j DROP | at -m now + 1 minutes
echo sudo $IPTABLES -v -D BANNED -p tcp -s $IP --dport 443 -j DROP | at -m now + 2 minutes
echo rm -fv /tmp/dos-$IP | at -m now + 2 minutes

So with Apache having a shell of /sbin/nologin, It'll add the IPTABLES rules and it'll create the at jobs, but when I get an email with the result of the at jobs, it states that the User is currently unavailable, so the iptables rules are never deleted. If I give Apache /bin/bash as its shell, the iptables rules are added, the at jobs are created, and the iptables deletion work as expected at their designated time.

So my question is: In what way am I putting my server at risk by giving the Apache user a shell?

Best Answer

The relevant code is at line 224 of mod_evasive.c:

        if (sys_command != NULL) {
          snprintf(filename, sizeof(filename), sys_command, text_add);
          system(filename);
        }

Now, let's check man 3 system:

DESCRIPTION
       system()  executes  a command specified in command by calling /bin/sh -c command,
       and returns after the command has been completed.  During execution of the
       command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored.

We can see, then, that the command specified is being run within a shell. Admittedly, the system(3) documentation is confusing on this point, but we can certainly see what is happening and make the appropriate inferences—it's being run in the user's default shell, not simply /bin/sh.

The correct solution is relatively straightforward: simply replace the system(3) call with a fork(2) and an execve(2) (or something substantially similar). If you'd rather not do that, you can also write a very small, restrictive shell to lock things down appropriately.

Coincidentally, this question triggered me to double-check, and you'll be pleased to know that a user with the ability to write an .htaccess file can't take over your box solely by virtue of mod_evasive being installed (RSRC_CONF is the correct setting, so kudos to the author of mod_evasive on that point). However, given how you've described your configuration, there's an excellent chance that, at minimum, any user with the ability to run code as Apache (e.g., barring mod_su* or the like, anyone who can run PHP, Perl, CGI, etc.), can ban you out of your own server using IPTables.

Related Topic