A small script which allows remote (de-)activation of basic auth user authentication enforcement on apache22.


As you may have noticed, this is a web site. Which is brought to you by some web server. Recently, I encountered a scenario in which I wanted to provide some files to a group of people but I was unsure on whether they shall be accessible public public (like this) or more restricted public (that is, I "secure" them with one user/passwd combination which then is to be handed to that group). I was about to meet with that group, but when I'm with that group, there wouldn't be trustworthy infrastructure around (which I otherwise just may have used to ssh to my machine and remove the password protection). Thus I set up a little script which allows me to enable/disable that function remotely without having to use any of my precious credentials. Sounds dangerous? Yes. Idiotic? Perhaps. Risky? Naaaaah.

The setup

The directory to be protected (or not) is http://somedom/dir, represented as /some/path/dir on the server. In there, I placed a .htaccess which aside other things contains the well known sequence of

AuthName        "HyperHyper"
AuthType        Basic
AuthUserFile    /some/other/path/htpasswd
require valid-user
to enforce http authentification. The typical apache log file is being written to /next/path/access_log, containing the usual sequence of
Client-IP - Username - Timestamp "Request Path HTTP-Version" Response-Code - "Referrer" "Browser-Identifier"
Of which some are obviously influencable remotely, that is, whenever I reuqest something with a browser I can change a field of the corresponding log line (such as time (by choosing a time to execute a request), client IP (by choosing a client), the user name (if requested, whatever I enter as a user name will appear in the log), or the requested path (which is to be whatever follows the domain name in the URL).

The idea

The idea is simple: A little perl-script evaluates what's written to the apache log file and if there's a magic value, current htacces-file (which is enforcing auth) is replaced by an empty file. If another magic value is found, empty file will be re-replaced by the auth-enforcing version (because I don't want to be in a situation where I dropped auth just to be told that it needs to be enacted because the previous information was wrong -- and then have to admit "um, eh, sorry, but no. I can't."

In the end, script looks something like this:

! /path/to/perl
use strict;
$| = 0;
while () {
	my $ln = $_;
	print $ln;
	if (($ln =~ m/^.*killswitch=on.*$/) && ($ln =~ m/^.*mymagicvalue|ONE|1360013.*$/)) {
		system "cp -v /path/to/permissive.htaccess /some/path/dir/.htaccess";
	if (($ln =~ m/^.*killswitch=off.*$/) && ($ln =~ m/^.mymagicvalue|TWO|1360013.*$/)) {
		system "cp -v /path/to/restrictive.htaccess /some/path/dir/.htaccess";
and is called like
shell$ tail -f /next/path/access_log | perl scriptname.pl
so script doesn't have to care about following the file by itself (have you ever digged into tail -- that's what I call crazy stuff!) which is a rather complicated task to do if the script shall stay half way platform independend.

Usage is pretty easy. All I need is an arbitrary browser, which I navigate to http://somedom/dir?killswitch=on -- in that case, the apache still will reject with 401 and the browser will ask for a user/password. I then can provide the magicvalue as user, so there will be a log line containing both command and magicvalue (ok, tbh, more like two magic values...). To flip the killswitch back, all that's needed is a URL containig both the killswitch=off and the second magic value -- which will be recorded in that browser's history. Which is also why there need to be unique magic values. This way, whoever snorts through the history may put the server into a more restrictive mode -- but not into permissive mode as user names are not that obviously stored (for the magic value better be not the password, resulting in just another 401 -- causing the client not to assume a valid user/password combination worth a store). However, it may be recorded.

I do think about security. Sometimes. That's why I didn't want to enter my ssh password at some console in the first case, resulting in above script. Now, anayzing it leads to user input only being taken from STDIN to a variable, printed and evaluated with regular expressions. If one wants to inject code (which is that one sweet sweet fruit to go for), he'd have to exploit a bug either in perl stdin handling, perl print, or perl RE. I consider that a lot of work just to get a half-ass-privileged user.

And you should never use magic values.