Is it possible to prevent Apache from running a script from a writeable directory?
It's common these days to have some writeable directories with (for example) CMS packages like Joomla, which use them for uploaded images etc. However I have a server that's been exploited through a badly written plugin which used the normal upload mechanism to upload the script, then ran the script directly via an HTTP request to the uploaded file. That script was used to send spam, so despite the limited write permissions it was restricted to it was still able to do a lot of harm.
Any of my own code which requires this always puts the writeable directories outside docroot but that doesn't seem to be an option with Joomla and others like her. I appreciate that they could still be "included" through abuse of a badly written script in a read-only directory, but that's at least an order of magnitude harder.
I know that the ability to upload new templates/plugins/etc would break if I achieve what I'm asking, but it's no big deal having a script which adds temporary write permissions whilst installing a module and removes them afterwards. Allowing end users to upload avatars and other images seems to be the way of the world these days though.
Maybe im just being naive but couldn't you just check the file extension/mime type to make sure uploads are images, and not allow execution rights on uploads?
Dennis
On 10/2/07, Mark Rogers mark@quarella.co.uk wrote:
Is it possible to prevent Apache from running a script from a writeable directory?
It's common these days to have some writeable directories with (for example) CMS packages like Joomla, which use them for uploaded images etc. However I have a server that's been exploited through a badly written plugin which used the normal upload mechanism to upload the script, then ran the script directly via an HTTP request to the uploaded file. That script was used to send spam, so despite the limited write permissions it was restricted to it was still able to do a lot of harm.
Any of my own code which requires this always puts the writeable directories outside docroot but that doesn't seem to be an option with Joomla and others like her. I appreciate that they could still be "included" through abuse of a badly written script in a read-only directory, but that's at least an order of magnitude harder.
I know that the ability to upload new templates/plugins/etc would break if I achieve what I'm asking, but it's no big deal having a script which adds temporary write permissions whilst installing a module and removes them afterwards. Allowing end users to upload avatars and other images seems to be the way of the world these days though.
-- Mark Rogers // More Solutions Ltd (Peterborough Office) // 0845 45 89 555 Registered in England (0456 0902) at 13 Clarke Rd, Milton Keynes, MK1 1LG
main@lists.alug.org.uk http://www.alug.org.uk/ http://lists.alug.org.uk/mailman/listinfo/main Unsubscribe? See message headers or the web site above!
"Dennis Dryden" ddryden@gmail.com wrote:
Maybe im just being naive but couldn't you just check the file extension/mime type to make sure uploads are images, and not allow execution rights on uploads?
Close but no cookie: the sender sends the file extension and mime type (so they can't be trusted), while things like PHP modules usually execute files without needing execution rights, so you need to explicitly switch them off.
So, this is a PITA. Anyone writing an apache module to stop things from server-writeable directories running?
Regards,
MJ Ray wrote:
"Dennis Dryden" ddryden@gmail.com wrote:
Maybe im just being naive but couldn't you just check the file extension/mime type to make sure uploads are images, and not allow execution rights on uploads?
Close but no cookie: the sender sends the file extension and mime type (so they can't be trusted), while things like PHP modules usually execute files without needing execution rights, so you need to explicitly switch them off.
Also: I'm approaching this from the POV of a server admin not a code writer (although I am both!). I want the server to guard against poor coding, not just rely on it not happening!
Apache determines how to interpret a file by file extension, so it wouldn't actually matter if someone uploaded a script with a .png extension; Apache would just serve it as an image not run it as a script. So just limiting the file extensions in writeable directories would be fine, except that there are so many to allow (.doc, .zip, .png, .jpeg, .jpg, etc for starters; any explicit list of allowable extensions is likely to forget useful ones like .odt etc which would be bad for other reasons), and listing the ones to disallow is open to missing something and needs knowledge of the server configuration (we have several sites which parse .html as PHP, for example).
So, this is a PITA. Anyone writing an apache module to stop things from server-writeable directories running?
The problem with apps like Joomla is that the have writeable directories scattered all over the place, and all under docroot. I don't really see a good reason to have any writeable dirs under docroot; ok so images can't then be served directly, but a script to pass them through safely is trivial and can then do other things (like dynamically resize images depending on requirements, limit access depending on access rights, or log view counts to a database).
Since with Joomla almost everything should go through index.php, I might try renaming that as index.phpx, and only letting .phpx scripts get executed (by which I mean "parsed as PHP"). But that only helps until someone uploads a .phpx file.... (Actually the exploit I just had to deal with relied on a file intended to be an include file being called directly, so this fix would have prevented the script getting uploaded in the first place. But that's got too much of a "special case" feel to me.)
Mark Rogers mark@quarella.co.uk wrote:
Is it possible to prevent Apache from running a script from a writeable directory?
Yes. Options -ExecCGI for that directory and redefine things like .php to not be handled by their apache modules.
You should be able to find the enabling lines in your Apache configuration file, and so the disabling lines should be obvious (IIRC, an enabling line of AddHandler php-script .php suggests a disabling line of RemoveHandler .php or similar).
An alternative global approach is to configure your Apache (User and Group directives) and/or filesystem (chmod g+s or u+s) so that uploaded files appear with certain user or group ids which are not allowed to run scripts by suExec or similar. I do that on some servers.
On most hosting servers I run, I try to set things up so that all web scripts runs as a user of that domain and there are careful rate and resource limits (outgoing emails, outgoing connection attempts, and so on), so if a user uploads a dodgy plugin and doesn't secure it, it probably only trashes their own site and degrades their own service until it sets my alarms off.
Hope that helps,
On Tue, Oct 02, 2007 at 02:44:02PM +0100, Mark Rogers wrote:
Is it possible to prevent Apache from running a script from a writeable directory?
It's common these days to have some writeable directories with (for example) CMS packages like Joomla, which use them for uploaded images etc. However I have a server that's been exploited through a badly written plugin which used the normal upload mechanism to upload the script, then ran the script directly via an HTTP request to the uploaded file. That script was used to send spam, so despite the limited write permissions it was restricted to it was still able to do a lot of harm.
Can I make the simple assumption that in this case, by "script" you mean a chunk of php? If it was a "real" script then ExecCGI would have needed to be turned on, and it'd have needed to be marked as executable... so I'm fairly confident that it won't have been that...
Anyways - what you want is...
<Directory /path/to/the/upload/directory> RemoveType .php .phtml .php3 .phps </Directory>
That should do it.
Brett Parker wrote:
Can I make the simple assumption that in this case, by "script" you mean a chunk of php?
Yes, although in practise anything that's being run via an Apache Handler would qualify, for the following reason:
If it was a "real" script then ExecCGI would have needed to be turned on, and it'd have needed to be marked as executable... so I'm fairly confident that it won't have been that...
:-)
Anyways - what you want is...
<Directory /path/to/the/upload/directory> RemoveType .php .phtml .php3 .phps
</Directory>
Sorry, I should have been clearer: I'm looking for a way to do it automatically by virtue of the fact that the directory is writeable, otherwise it's relying on me (and other site admins who tend to worry more about "does it work" than "is it secure", as I've discovered to my cost!) to not screw things up.
Presumably, now I thing about it, it would be possible to do this via .htaccess files? At least that way a script could be written* that searched for writeable directories which did not contain .htaccess files and alerted me (or created them).
[*] The script sounds simple but I can't quite work out how to do it.
Mark Rogers
On Tue, Oct 02, 2007 at 03:34:09PM +0100, Mark Rogers wrote:
Brett Parker wrote:
Can I make the simple assumption that in this case, by "script" you mean a chunk of php?
Yes, although in practise anything that's being run via an Apache Handler would qualify, for the following reason:
If it was a "real" script then ExecCGI would have needed to be turned on, and it'd have needed to be marked as executable... so I'm fairly confident that it won't have been that...
:-)
Anyways - what you want is...
<Directory /path/to/the/upload/directory> RemoveType .php .phtml .php3 .phps
</Directory>
Sorry, I should have been clearer: I'm looking for a way to do it automatically by virtue of the fact that the directory is writeable, otherwise it's relying on me (and other site admins who tend to worry more about "does it work" than "is it secure", as I've discovered to my cost!) to not screw things up.
Presumably, now I thing about it, it would be possible to do this via .htaccess files? At least that way a script could be written* that searched for writeable directories which did not contain .htaccess files and alerted me (or created them).
Bing bing bing bing... Err, well... that's not so good really is it... .htaccess files in the *writable* directory? ;)
Better to run a script that generates a file for apache's conf.d directory with the right set of directives in it...
So, *who* has write access to the directories is the obvious question, and then the next fun bit is to work out which files need to be roughly parsed in order to get the list of directories to search, and then after that needing to know all the modules that are enabled that could cause issues... (mod_php, mod_perl, mod_python, mod_blahdefoo) and have a snippet to disable them.
The script itself once the variables are out of the way is the easy part... ;)
Cheers,
Brett Parker wrote:
Bing bing bing bing... Err, well... that's not so good really is it... .htaccess files in the *writable* directory? ;)
Hmmm.... Well the .htaccess could be readable but not writeable by Apache, couldn't it?
Better to run a script that generates a file for apache's conf.d directory with the right set of directives in it...
OK, I'm game...
So, *who* has write access to the directories is the obvious question,
At the moment, the owner of all files is the site's owner (who has read/write access), and the group is the same as the owner, except that Apache is added to that group. Eg the files are chown'd to joebloggs.joebloggs, and the www-data (ie Apache) user is added to the joebloggs group.
Files and directories are then generally chmod 644 or 640 so that the user can still modify the files but Apache can only read them, except where it needs write access in which case chmod g+w is applied.
and then the next fun bit is to work out which files need to be roughly parsed in order to get the list of directories to search,
That could be hard coded for my needs, or more generally (but still really just for me) I can tell you that all sites sit in the following directory structure: <somedir><sitename><htdocs> where <somedir> is common to all sites.
I think it should be assumed that all subdirectories of a writeable directory are also writeable.
and then after that needing to know all the modules that are enabled that could cause issues... (mod_php, mod_perl, mod_python, mod_blahdefoo) and have a snippet to disable them.
A generic "disable everything" (for some value of "everything") would suffice; Apache should be able to serve the files directly but not run them.
The script itself once the variables are out of the way is the easy part... ;)
That perhaps depends on ones shell (or other) scripting skills....
Another thought: a script which checks for problems (but doesn't fix them) might be easier; run from cron it could alert me to deal with the problem manually.
Mark Rogers