Log in

No account? Create an account
Somewhere in Cleveland there's some guy named Al Kida (K-I-D-A) -- he's Freakin' Out - MrPutter: doing things the hard way, because it is there.
January 27th, 2007
02:58 am
[User Picture]


Previous Entry Share Next Entry
Somewhere in Cleveland there's some guy named Al Kida (K-I-D-A) -- he's Freakin' Out
So there's nothing quite like the sudden realization that code you've written (and which has been live for a couple weeks) is about as secure as a sieve.

Specifically, code which handles and validates course assignment submissions.

Oh, I took care of all the micro issues, like worrying about SQL injections, sending plaintext passwords over the wire, buffer overflows, malicious filenames and all yer standard stuff. But as we shall see, this amounted to but a thin cotton cloth lining the metaphorical sieve.

Now in my defense, it wasn't entirely my fault—rather it had more to do with the dumbass way they set up the webserver in our department. But be that as it may...

The CPSC department used to have a most excellent, well-tested and well-secured assignment submission system that served for many years. Until last year, when for various reasons (read: department politics) it was taken down. So I decided to write my own webform for the purpose, which I duly put on the course website.

In retrospect, PHP was perhaps not the ideal choice of platform. In an appropriately-designed environment, sure, it would have been just splendid. But ours hardly meets that criterion.

All seemed well until this evening, when I had a request from a student to give him an extension on the upcoming assignment for what was an eminently reasonable rationale. I therefore happily acquiesced, and went to grant him an extended deadline in the submission system. When it suddenly struck me that the database containing the due-dates was actually accessable by anyone on the system.

Which would not have been an issue, save that the path to the file containing my password for the database (even if only the one granting read-only access) was hard-coded into the PHP script.

Which would not have been an issue, save that the PHP script (and the abovementioned file) had their read flags set for the "apache" account, necessary of course for Apache to be able to read and execute them.

Which would not have been an issue, save that every single CPSC student is able to set up a PHP (or otherwise) script on their account, which is run on Apache, and can therefore read any file on the system which has read-access granted to Apache.

Which would not have been an issue, save that the database ALSO contained the path to the directory where I was saving the files which had been submitted.

Which would not have been an issue, save that Apache has write access to that directory (how else can it save the files there?). So in other words, with but a few minutes' applied brainpower, any student in the class has arbitrary write access to the directory where the submitted assignments are stored.

Which is a teensy-weensy tiny little issue.

So in a panic I took the script down (This channel is experiencing technical difficulties. Please stand by.) and have spent the last 7 hours hastily re-writing everything in C. Why C? Because I could then compile it to an a.out binary, for which Apache only requires the execute bit set, not the read bit. And which is therefore marginally more secure against prying eyes. (Oh yes, I also changed the database password, and the directory where everything is saved.)

I'm still worried, though. The submission form is back up, but for how long? How many other obvious blunders have I missed? Even though the submission handling code is now ---------x (and cannot therefore be run through strings), I'm still uneasy about how everything is put together.

Simply re-writing in C feels like an awful horrible kludge. The saved-assignments directory, for example, is still Apache-writable, even if its path is now better-obscured.

But what else can I do?

What obvious security principle am I missing?

Dryer Cat is not amused.
Dryer Cat is not amused.

Current Location: T2L 2C7
Current Mood: disappointedconcerned
Current Music: Dan Bern -- Talkin' Al Kida Blues
Tags: , , , , ,

(3 comments , Leave a comment)

[User Picture]
Date:January 27th, 2007 02:43 pm (UTC)
This reminded me of you.
[User Picture]
Date:January 28th, 2007 02:33 am (UTC)
"What obvious security principle am I missing?"
Privilege seperation!

Adds complexity, but you need the security.

1. Change the database permissions.
1.1. The web user should have SELECT and INSERT, but not UPDATE/DELETE.
1.2. Even better, should be INSERT only (no read) into the submissions table for private data, and SELECT only (no writes) on the assignments table of public data. Some RDBMS however do not support INSERT without SELECT.
1.3. If you wanted to avoid the RDBMS problem entirely, put the assignments in a read-only file (644 mrputter:users), and the submissions use the same schema below for privacy.
2. For handling the files, you need something similar at the filesystem level.
2.1. Two directories. The first one is the actual inbox location (chmod 2771, chown mrputter:apache). Your CGI writes here.
2.2. Second is the actual storage location. It's more locked down so that Apache cannot access it.
2.3. Have a cronjob or some watcher code (inotify/gamin works very nicely here), that checks the inbox for files, and moves them to the storage, changing permissions in the process.
2.4. Be careful of filenames. I suggest storing them in the database, and then using the primary key as the filename instead.

While I am not a fan of Perl, this is something that I would probably write in Perl using the CGI module from CPAN, to take advantage of the Taint checking. When PHP finally gets Taint checking, there will be a _lot_ of bugs in PHP apps exposed (I'm formerly a developer of phpMyAdmin, I have a very good view as to just how bad the problem is).
[User Picture]
Date:January 28th, 2007 05:33 am (UTC)
> Privilege seperation!

Which, if you read my above post, you'll see that I already have. Although I admit, not enough (see below).

Anyway, the problem with your part 2 solution is that this is on the department server, not my own, so I'm somewhat limited with what I can do (else this problem would not have come up in the first place). cron jobs, for example, are right out.

As mentioned above I already had read-only access to mySQL (actually, SELECT-only access, but whatever). Which I had to cajole the IT department for 3 days to obtain. But anyway. The database only holds configuration data (due dates, allowed student ids, file locations, etc.) so there was no need (in this case) for Apache to have write access to it, in any case.


The solution to my file-storage-area-security problem (which I figured out when I woke up this morning; reason #271 why not to code at 3 in the morning) was just to set the setuid bit on my executable. So that Apache doesn't need write access to that directory at all; and anyone who wants to dump stuff in there (even assuming they figure out where "there" is) HAS to go through my program (the code contained in which I'm considerably happier about).
Beware of Road Surprises Powered by LiveJournal.com