I'm starting to set up the security for my web server. For this, I created a folder outside of my www folder, where I put my config.php. This file holds sensitive database infos.
I have two questions:
1) Should I rather keep it in the www folder and then move everything else down one level and make my web server point to that new web root?
2) What permissions should I set?
currently I have set the
owner to root (read-only)
group to root (read-only)
others (read-only) as well
I'm only really worried about others. Should I rather specify a user for it or create a new group altogether? Please also mention any other considerations. Thanks
EDIT: I forgot to mention, my web server distro is Ubuntu 10.10.
EDIT2: My web server is nginx
if you do move your config.php file outside of your www, you may have a openbase_dir issue, which what will not allow that script to be processed as a php file (only on certain server configs.. I think that moving your config file outside of the www folder is unnecessary as long as it is not echoing all that info out.
Keep in mind that if your server is processing php files correctly your server will not reveal the file content to the world.
so:
1) Keep it in the www folder
2) I set mine to 644
take a look at this for some more security info:
http://www.acunetix.com/websitesecurity/php-security-3.htm
Good luck,
Joe
I feel that safe mode should be off, but it's deprecated
OR
move config.php to config/ and then put this in config/.htaccess:
Deny from All
Related
THE SITUATION
I have multiple folders in my /var/www/ directory.
Users are created that have control over a specific directory... /var/www/app1 belongs to app1:app1 (www-data is a member of the app1 group).
This works fine for what I want.
THE PROBLEM
If the app1 user uploads a PHP script that changes the file/folder permissions for something in app2s directory structure, the Apache process (as there's only one installed on the server) will be more than happy to run it, as it has the necessary permissions to access both /var/www/app1 and /var/www/app2 folders and files.
EDIT:
To the best of my knowledge, something like, /var/www/app1/includes/hack.php:
<?php
chmod("/var/www/app2", 777);
?>
The Apache process (owned by www-data) will run this, as it has permissions to change both /var/www/app1 and /var/www/app2 directories. The user app1 will then be able to cd /var/www/app2, rm -rf /var/www/app2, etc., which is obviously not good.
THE QUESTION
How can I avoid this cross-contamination of the Apache process? Can I instruct Apache to only run PHP scripts that affect the files/folders that reside within the relevant vHost root directory and below?
While open_basedir would help, there are several ways of bypassing this constraint. While you could break a lot of functionality in php to close off all the backdoors, a better solution would be to stop executing the php as a user whom has access to all the files. To do that, you need to use php-fpm with a separate process pool/uid/gid for each vhost.
You should still have a separate uid for the php execution from the uid owning the files with a common group allowing a default read only access to the files.
You also need to have separate storage directories for session data.
A more elaborate mechanism would be to use something like Apache traffic server in front of a container-per owner with each site running on its own instance of Apache - much better isolation, but technically demanding and somewhat more resource intensive.
Bear in mind, if you are using mariadb or similar, that the DBMS can also read and write arbitrary files (SELECT INTO OUTFILE.../LOAD DATA INFILE)
UPDATE
Rather than the effort of maintaining separate containers, better isolation could be achieved with less effort by setting the home directory of the php-fpm uid appX to the base directory of the vhost (which should contain, not be, the document_root - see below) and use apparmor to constrain access to the common files (e.g .so libs) and #{HOME}. Hence each /var/www/appX might contain:
.htaccess
.user.ini
data/ (writeable by fpm-appX)
html/ (the document root)
include/
sessions/ (writeable by fpm-appX)
You should add an open_basedir directive to each site's vhost file. The open_basedir directive limits the directories that a site can access.
You can read more about open_basedir here.
Sorry if this is a trivial question.
I am a kind of new to PHP and I'm creating a project from scratch. I need to store my application logs (generated using log4php) as files, and I don't want them to be public.
They are now stored in a subfolder under my PHP application folder, (/myAppFolder/logs) so they are served by Apache.
Where shall I store them, or what shall I do to keep them away from being served as content by Apache?
You can either have them in a directory above the root, or, if you're on shared host/ can't have the files above the root for whatever reason, you can have them in a directory that denies all HTTP access.
So you could have a folder called "secret_files" with a .htaccess file sitting inside:
.htaccess:
deny from all
Which will prevent HTTP access to files/subfolders in that folder.
Somewhere not under the public root!?
This is more a server config question as it depends on your server, but in apache you could use the custom log directives to set the location, so if you have
/www/myapp
Create
/www/log
and put them there instead. You need control over the config to do this so look up your web hosts docs to find out how.
I've got a "globabVars.php" doc in my own little framework that contains database connection vars etc... I'm thinking would be neat to store outside of the web facing directories to keep it a little more secure. But, then I was thinking, is it really THAT much more secure? I mean, if someone were able to look at my .php files as a whole (without the server processing them) they would be INSIDE my server looking at all my files anyway...
Thoughts?
Moving a config file outside of the web root can prevent this file from getting leaked if you accidentally mis-configure apache. For instance if you remove Apache's mod_php then all .php files will be treated as text files. I have seen config files moved outside of the web root on production systems for this reason, and it did stop the file from getting leaked! (An admin iced the config during an update, doah!). Although this doesn't happen very often.
If an attacker can control the path of one of these functions: file_get_contents(), fopen(), readfile() or fgets() then he can read any file on your system. You also have to worry about sql injection. For instance this query under MySQL can be used to read files: select load_file("/etc/passwd").
To mitigate this issue, remove FILE privileges from your MySQL user account that PHP uses. Also do a chmod 500 -R /path/to/web/root, The last 2 zeros keeps any other account from accessing the files. You should also follow it up with a chown www-data -R /path/to/web/root where www-data is the user account that php is executed as, you can figure this out by doing a <?php system('whoami');?>.
It means noone can access it via a URL by default.
You can hide with .htaccess if it is in your docroot, but storing it above the docroot is just that bit safer.
You can have it read via PHP if your application is prone to directory traversal attacks.
Yeah, you are right. There is a very small difference.
See an example here: http://mattpotts.com/portal/
I put an includeme.htm in each directory on the required path to find the point of failure. It works fine on my local machine (windows) with the same directory structure but fails on my remote (linux) server.
Directory structure:
+-firefli/ drwx--x--x
+-private_html/ drwx------
+-foo/ drwxr-xr-x
+-bar/ drwxr-xr-x
+-portal/ drwxr-wr-w
+-public_html/ drwxr-wr-w
+-foo/ drwxr-wr-w
+-portal/ drwxr-wr-w
The permissions confirm that it's the private_html directory causing the trouble. Hopefully you can see the purpose of the directory structure, I don't know if it's a common way of doing things but it works for me. Well, until now.
I've gone a very long way around asking it but my question is simply this: is there anything wrong with setting private_html to be drwxr-xr-x? Given that I do not want it to be accessible via the web. But the permissions shouldn't do that should they? Because it's apache making the public_html directory accessible via http.
You shouldn't need to block out web users with folder/file permissions on private_html, as it's outside the web root. As you say, web users can only get to stuff in public_html
For future debugging speed, if you have a relative web path you can convert it to a real path using realpath:
$path = realpath('../../private_html');
// $path is now /public_html/foo/private.html or whatever
Well, if you have set up your DocumentRoot correctly to point to public_html, it won't be accessible from the web, no matter what permissions you put on it.
The Private HTMl is not accessible from the web without you putting in a .htaccess file that would redirect it. If you don't know what that means/how to do that, you are safe.
You should be fine setting these permissions to whatever your script needs.
what are the user:group for private_html? The web server needs to be either a member of the group or the owner of the file. In order to read the directory contents the dirctory needs to have the execute permission for the webserver to open it. Essentially they should have the same user:group as public_html. You just want to disallow the write permission. tot he webserver. If you have set your document root to public_html private_html is not accessible via the web no matter what the permissions. Also, i always use realpath on the path arguments to and file operation.
I am trying to help a friend moving a web-site from one web-hotel to another.
The old place is already closed, I have only a flat tar file of what was in it.
The web site contained HTML docs and one could download a little Java application (to be loaded on mobile phone) to send data to the web site.
The mobile Java application sent a string to URL=<HOST>/php/register.php. This php script included another php script (../inc/db_login.php), which connected to a SQL DB using $link=mysql_connect(). Another file, register.php, did the SQL insert for putting the new sent data in the DB.
My question is basicaly, where I should put this 2 PHP files on the new website and what permissions the directories and files should have?
The old web server obviously had a /php and /inc directories. None of these exists on the new webserver. Should I create them? What permission should they have? I guess the reason for having the password in a separate PHP file was security. The /php and /inc directory probably had different permissions.
The new server has directories:
/httpdos
/httpsdos
/cgi-bin
/conf (and some others probably irrelevant)
My questions
Does the file-extension (.php) mean something to the server: as PHP scripts are "included" in HTML code (between <?...?>, does the server need to look at the file suffix or is it irrelevant? (I understand that the server reacts on the <?...?>, of course)
should the public file (register.php in my case) be placed in the httpdocs/ directory or does the server (apache I think) reacts on something and fetches it in another directory?
Should the PHP script have permission R-X (read and execute), --X (execute) or R-- (read)? From a OS perspective I guess apache is just reading this files, meaning that they should be R--, but this would mean that if PHP service is "stopped" the client would get all the PHP code in his browser(?). I would prefer it being --X but as this is neither a binary nor has a #!, I guess it must be --R?
If the public PHP script can be placed in another dir (e.g /php instead of /httpdocs) what should /php (and the script) have for permission?. I guess the server has to know about this /php directory (or are there usual defaults?)
The PHP script included (../inc/db_login.php, containing SQL password) should not be under /httpdocs I guess. This means that my register.php is including a file which is not under the /httpdocs subtree. Does this work? Does the server need to know?
I understand you may need to know the server configuration. Just assume the default in your answer (and you can tell where it is changed if it is).
Directories must have execute permissions to be usable. Usually this is 0755. PHP scripts run via mod_php are not executed but rather read; 0644 will suffice for this. Directories that must be written to need to be owned by the user the web server is running as. There may be additional concerns regarding permissions, e.g. SELinux, but the above will get you through the basics.
Documents that must not be accessed by other users or external clients should be 0600, owned by the web server user, and located outside the DocumentRoot. Note that running mod_php in Safe Mode will prevent scripts from ever including anything outside the DocumentRoot; a lamentable flaw.
Set php files to 640
For maximum security you should set minimum permissions, which
is 640.
The owner 6 would be the one uploading the files.
The group 4 would be the one serving the file. Make apache a group member.
The nobody 0 means no other users can read this file. It's important since php scripts sometimes have passwords and other sensitive data.
Never allow php scripts to be read by everyone.
Useful commands:
chmod 640 file.php
chown user:group file.php
usermod -a -G group apache
What these commands are doing:
Change ownership of file.php so user can read and write, group read.
Change ownership of file.php, to chosen user name and group name.
Add apache to the group, so that apache can serve the file. Otherwise 640 will not work.
1) Files that end with a .php extension are handed off to the PHP compiler by Apache. If the proper configuration is not set up to do so, PHP files get served up as text files by the server. The Apache configuration line "AddHandler php5-script php" in the httpd.conf file is the PHP5 method of setting this up.
2) register.php needs to be accessible at http://www.example.com/php/register.php, as the java app is looking for it, so in the Apache htdocs folder, there needs to be a "php" folder with the register.php file in it.
3) PHP files need read access by the user that's running the Apache service. Using PHP as an Apache module has no 'service' to speak of that's separate for PHP. Instead the Apache service, when it gets a request for a PHP file, makes a shell call to the PHP binary to parse the file and hand the Apache service the result, which it serves to the client. Only if you were using PHP from the command line (CLI setup) would the scripts need execute permission, and start with a #!/path/to/php-bin line.
4) The requested file (register.php) needs to be in htdocs in order to be served by Apache. If PHP is running with "Safe Mode" disabled, register.php could include a file that was outside the htdocs folder.
5) The path "../inc/db_login.php" is relative to the PHP script that was originally fetched (register.php), so, since register.php is in htdocs/php/register.php, that would put db_login.php at htdocs/inc/db_login.php.
I've coded a function to address the permissions issues in both of PHP / SuPHP and similar:
function realChmod($path, $chmod = null)
{
if (file_exists($path) === true)
{
if (is_null($chmod) === true)
{
$chmod = (is_file($path) === true) ? 644 : 755;
if (in_array(get_current_user(), array('apache', 'httpd', 'nobody', 'system', 'webdaemon', 'www', 'www-data')) === true)
{
$chmod += 22;
}
}
return chmod($path, octdec(intval($chmod)));
}
return false;
}
Maybe it's useful for you.
All the PHP files which are intended to be addressed directly via URLs can happily reside in the same directories as the static content (this is the usual practice).
It is good practice to have at least one directory outside those visible from the webserver to hold include files, but the PHP include path should still include '.'.
I'd recommend not putting lots of non-standard directories in your root filesystem - the default webroot varies by distribution, but I usually go with something like:
/var/www/htdocs - as the document root
/usr/local/php - for include files
Obviously if you intend running your webserver chrrot, these should be mapped accordingly.
All files must be readable by the uid under which the webserver runs, however if you can restrict what is writeable by this uid as much as possible then you close off a potential attack vector.
I usually go with setting up my dirs as drwxrwSr-x owned by a member of a webdev group with the group ownership as the webdev team, (the httpd uid is not in the webdev group) and files are therefore -rw-rw-r-- So anyone in the webdex group can change files, and the httpd uid can only read files.
1) does the files-extension (.php) means something to the server:
Yes - go read the PHP installation guide.
C.
Assuming your SFTP/FTP user is johndoe and web server group is www-data. johndoe only read, write the files but not execute the files (in my case never). The web server software usually Apache/Nginx from the group www-data can read/write/execute the files. Other users? what are they doing here???
So, I used to set 0670 (rw-rwx---) and works for me always :)
Set file permission to 0644 and folder permission to 0755.
I have coded a library for that.
Example of usage:
<?php
use MathiasReker\FilePerm;
require __DIR__ . '/vendor/autoload.php';
(new FilePerm([__DIR__])) // <-- root directory
->setDefaultModeFile(0644) // <-- file permission
->setDefaultModeFolder(0755) // <-- folder permission
->scan()
->fix();
Full documentation: https://github.com/MathiasReker/php-file-permissions