I am in the process of writing a PHP script that will add IP address blocks to the .htaccess file. My concern is that I do not want to have the .htaccess file open to the web server user for general writing, as then any compromise of the web server would allow them to write anything they like to the .htaccess file. So I am trying to find a way to limit the PHP script to only be able to write what I want it to be able to, in some way.

I am thinking that an appropriate way to do this may be to create a script in another location, perhaps owned by root, that has suid set on it (my web partition does not allow suid). I can then call the script from my PHP script, and it will only be able to do what the interface of that intermediary script makes available to it, which would be to take the parameters necessary for writing the specific IP address blocking code to the .htaccess file, and nothing else.

Does this sound like the best way to approach it? Is there any other way that would be better, or any consideration I'm missing?

Meta Note: I considered the Information Security site or Stack Overflow for this question. If it would be better on one of those please let me know.

  • Linux and other Unix systems usually ignore the setuid bit on interpreted executables, so you'd need to either 1) write your block-writer in something that compiles (e.g. C or Haskell), or 2) change this default behavior
    – Fox
    Mar 15, 2017 at 22:15
  • Thanks for this. I had a look in to it and don't want to allow the behaviour, so perhaps compiling a Perl script is going to be the way to go, since that's something I could manage!
    – user194553
    Mar 15, 2017 at 22:21

1 Answer 1


Let the PHP script write the IP addresses to a database table. Separately, from cron, periodically execute a different script (recommendation? Python) that queries the values and writes them to the .htaccess file. Then you can keep the permissions on the .htaccess file tight, like 0640, root:www-user.

We can set the SUID bit on a script; but, by default, Linux correctly ignores it. Just change permissions to something like 0700, root:root on the script that runs from cron.

Lots of jobs like this one can be handled with this technique, sort of database queue. I have used it when a Web interface is a project requirement for system management. The queue in scenarios like these can manage users, passwords, virtual hosts, DNS - you name it, really.

  • Thanks for this. It's a good solution and I did consider something like it. But the reason not in this case is that I want the block in place instantly. A delay of even a minute would be a problem, because this is to block unwanted web crawlers when they hit a "bot trap" so I want to stop them straight away and not wait for a cron job to pick it up. In that minute they would have grabbed lots of other pages. Could a daemon do it instantly?
    – user194553
    Mar 15, 2017 at 22:23
  • 1
    You could remove .htaccess from the equation. Instead, let the web app block/redirect whichever addresses have been stored in a table. Mar 15, 2017 at 23:20
  • Thanks, good idea, that could work. I think I'm going for the compiled Perl script and suid though, just because it's a bit quicker without the database query when the file is being parsed anyway, and simplifies the admin and re-use of the script with no database required.
    – user194553
    Mar 15, 2017 at 23:46
  • Well, compiling Perl to do this didn't work out at all. There are numerous errors from PAR::Packer trying to run as suid on my local machine, and it won't installed at all on my CentOS server, so I am giving up on that and going for a variation on this solution. So accepting this answer, thanks a lot for the help.
    – user194553
    Mar 16, 2017 at 4:14
  • Ok. I have also remembered some other options for the topic. SHC can compile BASH scripts to C source, which can then be compiled. The nim language writes like a script but compiles to C. The Rust language is string friendly and produces binaries. Or D might work nicely here. If I had to pick, I'd go with Rust while secretly wishing I had enough patience to deal with strings - erm, arrays of characters - in C. :) Mar 16, 2017 at 11:12

Your Answer

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