Quote:
Originally Posted by Xeratul
"If your configuration is such that a PHP script may overwrite itself, attackers may be able to add or rewrite your scripts to obtain any data stored under your account" - not cool.
|
To avoid any misunderstanding:
Having a web hosting environment where your scripts can overwrite themselves, or create new scripts the web server will execute, is like running with scissors. If you don't stumble, you probably won't get hurt at all.
The problem is that we humans are not perfect. We stumble. The code we write may occasionally contain bugs that allow an attacker to execute their own code. In PHP, accidentally letting the attacker pick a value with exploitable side effects is more common. For example, your script might use the file name provided with a file upload, but forget to verify or filter the file name for a relative path. If PHP code can create or overwrite existing PHP code, a crafty attacker can then upload their own script file, simply by modifying the file name in the file upload submission -- and then they can run basically any PHP code they want, using your account.
If you do not use PHP file I/O, and disallow file uploads, the risk is minimal.
The scheme I prefer to use protects against basically all of the above, but requires multiple dedicated user accounts.
For example, assume I am user
nominal in group
animal. This would be the account I login with, and which owns (
nominal:animal) my PHP scripts, HTML files, and all media files.
If I had a buddy to share the workload with, she could be user
crazee, also in the
animal group. We can then use group-based access rights -- that is, we can modify files owned by either person, unless we explicitly deny the right (the default is to allow write access to all members of the same group). The user-owner of the file only tells who "owns", or last uploaded, the file.
PHP and CGI scripts run under a dedicated user account and group, say
animal.www:animal.www . All us PHP/CGI admins would either also belong to the
animal.www group, or have
sudo right to "become"
animal.www user, for maintenance purposes.
To allow a PHP or CGI script file access, I normally create a dedicated directory outside the web tree -- that is, not accessible via a web page. The
animal.www group would have write access to that directory. (POSIX ACLs are very useful here, since you can also give the
animal group of humans full access to that directory.) For e.g. image uploads, I recommend you use GD or ImageMagick to open each uploaded image, and save it to the public directory (perhaps with downscaled thumbnails), in order to strip any extraneous information from uploaded files. Obviously you should disable script execution completely for such directories!
For sensitive operations, like login and password management, I do prefer to use a yet another dedicated user account, say
animal.sec:animal.sec. If user
animal.sec also belongs to the
animal.www group, and file access rights are determined exclusively using group rights like I outlined above, the scripts running as
animal.sec:animal.sec can do everything scripts running as
animal.www:animal.www can, but also have access to private data not accessible to the latter. (For example, credentials to access passwords and other privileged information.) Consider this a "super script" user -- but still completely limited by what files and directories humans will allow it access to.
Mostly this all is risk management. Perfect code does not need any of the above. I just don't have perfect code! Compartmentalizing access to information using dedicated user accounts in above hierarchical fashion turns out to be pretty easy in real life if you maintain your own server or server image, especially if you are a team working together. (If you have task-dedicated accounts like
webmaster, it is a different story. My way is designed to work when people log in using their own actual user accounts to do maintenance, mostly because that's what people tend to do.)
Finally, if your web server configuration is limited to only fully trusted administrators, you can use server-added custom request headers (or environment variables, but only if using FastCGI!) to pass sensitive information like database passwords from the server to only specific scripts. This lets you limit the visibility of the sensitive information to just a few scripts, thus reducing the possible number of security vulnerabilities. Instead of some script file or "hidden" file, the sensitive information is saved in privileged configuration files not at all accessible to the web server. (For example, Apache reads its configuration files using superuser rights, not as the user and group specified in its configuration file.) Why let all scripts have access to all information, when they don't need it?
Ahem. Sorry for the rant.
If you want the simplest possible example, I can show how it is done, but I will insist on describing its inherent security risks
Hope you find this interesting,