Wednesday, Debtember 04, 2002
“The check is done with the process' real id … ”
Your journal software leaves the content files world writable:
That is not so much a bug as a work-around the rather brain-damaged Unix permissions. The software accepts new entries via email or a web interface (okay, so I've yet to actually use the web interface, it's there if I ever need it) and since sendmail writes files as “mail/mail” and the web server runs as “www/www” and since I can upload files (usually images) as “spc/users” there's a bit of a problem.
Why not just have those programs execute SUID/SGID as spc/users? Then there is no problem. Assuming those programs check paths so I can't do anything naughty that shouldn't be a security risk at all.
This is something I'm willing to live with.
I can cook you up a comment system :-)
Email exchange between Mark and myself about mod_blog
Since Mark also has access to the webserver, it would be rather easy for him to “cook up a comment system.”
Anyway, I've spent the past hour or so working on making mod_blog SUID and not having much success.
Or rather, partial success.
New entries are added, that isn't the problem. The problem is in displaying the entries (and in generating a few static pages like the main page and the RSS feed which technically I don't have to do, but it lightens the load on the server if I do). And tracking down the problem wasn't straight forward—it worked fine if I (as me) ran it under my own user ID, but it would fail if I ran it as another user (which is odd, since the program, being SUID should have run as me reguardless of who started it). And gdb doesn't allow one to debug a SUID program if you run it as a different user than the one who owns it.
That just means I have to resort to other means to debug the program, which is a skill I picked up, despite being tediously annoying (okay, gdb may be able to debug a SUID program as someone other than the owner, but I don't know the magic incantations to do such a thing and I'm trying to track down a problem with my code; I don't really want to fight another program at this time).
I finally found the problem, and it's a Unix problem.
The current method I use to store entries is to store each one in its own file, using a directory structure as so:
year “/” month “/” day “/”
where the directory “day” contains the actual entries.
Now, not every day or month has to be there (heck, entire years can be skipped), so as a quick check I use the access() function to see if a date (as stored on the disk) exists.
access checks whether the process would be allowed to read, write, or test for existence of the file (or other file system object) whose name is pathname. If pathname is a symbolic link permissions of the file referred to by this symbolic link are tested.
access(2) manual page
Since I'm testing for the existence of a directory (and I don't really want to change into it or even at this point open the directory for reading) access() seems the perfect choice to use. But reading a bit further …
The check is done with the process's [sic] real uid and gid, rather than with the effective ids as is done when actually attempting an operation. This is to allow set-UID programs to easily determine the invoking user's authority.
access(2) manual page
So while all the damaging system calls use the effective user id, the safest system call you can make, the one that does practically nothing, uses the real user id.
Tell me again how this helps?
So, even though the program supposedly runs under my user id, it really isn't and I have to tell the system that it should. setreuid() should solve that problem.