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)



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?


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

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

Now, let's check man 3 system:

       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.

| improve this answer | |
  • So kick MOD_evasive into the dustbin? – Nils Sep 24 '13 at 19:45
  • So essentially one of my developers (or an attacker if there exists an application flaw that allows them to upload and execute code) could write a php script that calls shell_exec() and can modify iptables rules? That's only made possible by me adding Apache to the sudoers file and allowing the ability to run /sbin/iptables. Outside of that, Apache is a fairly normal, non-privileged user, correct? Anything else I should worry about? – Safado Sep 26 '13 at 14:59
  • Killing mod_evasive is certainly one option to solve the problem, yes. Whether that's an appropriate answer has far more to do with why you chose to install it in the first place than its intrinsic worth, however. As far as the Apache user, giving it a shell is a minimal increase in privilege; that doesn't concern me. Apache with sudo access is scary, but largely because giving anything sudo is terrifying. Still, as long as you define your sudo narrowly (i.e., not just NOPASSWD: /usr/sbin/iptables), you should be okay in most real-world scenarios. Don't expect to pass a sec. audit, though. – BMDan Sep 26 '13 at 22:36

Why does apache need to run this script? It looks like you are elevating apache to root, and assigning it a shell when you could just run the script as root.

Giving apache sudo access is a lot like locking all the doors and windows of a building... but also installing an overhead door for a shipping dock and leaving it wide open. (A user will in theory only have access to certain things in the shipping bay... but they have none the less gained entry to the building and can begin prying for further entry points.

Giving the apache user a shell to go with said sudo access is a lot like leaving a key cutter in said shipping bay. With enough luck an attacker can make the keys (gain access/privileges) he/she needs.

https://unix.stackexchange.com/questions/78985/deleting-users-with-nologin-shell As per the above question: the /bin/nologin shell prevents anyone from logging in as the user in question (see: console,ssh,su,etc).

You can also take a look at : https://security.stackexchange.com/questions/5707/recommendations-for-changing-the-default-shell-for-service-accounts -- a discussion of the security of nologin vs /dev/null as the shell.

| improve this answer | |
  • How would you suggest I run the script as root? mod_evasive is an Apache module. Each apache child process keeps its own hash table of accesses. When it detects an offender, that child process is what executes the script. The only way I can see having root execute the script is if I change Apache to run as root, which doesn't seem like a good idea to me. How I originally had it was I edited visudo to give apache NOPASSWD access to /bin/bash... but I failed to realize that was essentially allowing apache to su to root, which we also don't want. – Safado Sep 26 '13 at 14:50
  • I want Apache to be able to add the iptables rules and create the at jobs in a secure as possible manner. – Safado Sep 26 '13 at 14:51
  • 2
    Have apache write the rules to a file. Let root pick it up in cron and add them. Apache probably shouldn't have direct access to your firewall.. – Daniel Widrick Sep 26 '13 at 15:07
  • I do agree with @lVlint67. Giving apache access to at and iptables is way dangerous, since any kind of port or script may be run. On the other hand, having apache write the rules, make sure your script will sanitize them, checking for proper DENY rules on a specific table of your firewall. You may also have a look at fail2ban.org – fboaventura Sep 26 '13 at 15:49

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.