Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I am running a LAMP stack on Ubuntu 12, with the primary function to serve a PHP based API.

There is only one file I want to be exposed to the public called: api.php

It needs to reference a config file I have in /cfg/api-config.php which contains db passwords so the API can write to the database etc.

So I only want the api.php to be 'served' by apache and made public.

The config file I put in /cfg must be readable by the api.php but not by anyone who might visit the site.

I have no .htaccess, just a httpd.conf configured as per the below.

<VirtualHost *:44448>
    DocumentRoot "/api"
    ServerName localhost:44448
    ServerAlias Server.local
    DirectoryIndex index.html
    CustomLog "/var/log/apache_access.log" combined
    ErrorLog "/var/log/apache_error.log"

    SetEnv APPLICATION_ENV development
    php_flag magic_quotes_gpc off

    <Directory "/api">
        Options Indexes MultiViews FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>

Permissions on my /cfg and /api folders are: drwxr-xr-x and permissions on my sensitive config file with db password located in /cfg/api-config.php is -rw-r--r--

I was wondering if anyone can tell me if this is set up correctly and safe?

Whereby:

A) All files other than the /api/api.php are not public, and no access can be gained to my servers files.

B) The config file with the passwords for db (for the api) is also not readable by anyone visiting the site?

I have tried to test this by creating a new folder in /cfg with chmod 777, and I can't seem to access it, which is good!

share|improve this question
    
/cfg (located in the root level of the filesystems) should be readable by the UID running the web server, only, and of course not be located anywhere under the DocumentRoot. Remove the options for Directory `/api'. –  MattBianco Dec 20 '13 at 9:54
add comment

4 Answers

up vote 2 down vote accepted
+50

You have two files (assume they are located at /var/www)

  • /var/www/api/api.php
  • /var/www/cfg/api-config.php

First of all, restrict access to /cfg with apache (this ensure nobody can access it from http) and allow access to /api:

<Directory /var/www/api>
    Options None
    AllowOverride None
    Order allow,deny
    Allow from all
<Directory>

<Directory /var/www/cfg>
    Options None
    AllowOverride None
    Order allow,deny
    Deny from all
<Directory>

Next, restrict your php with open_basedir:

open_basedir = /var/www/api:/var/www/cfg

(add /tmp, session and other directories here if you need them)

Next, change access mode of /var/www/cfg directory and /var/www/cfg/api-config.php file (assuming your apache user is www-data):

  chown -Rv root:root /var/www/{cfg,api}
  chmod -v 711 /var/www/cfg
  chmod -v 755 /var/www/api
  chmod -v 644 /var/www/api/api.php /var/www/cfg/api-config.php

By using 711 on /cfg, you ensure, so nobody can read (list) contents of the directory, while still can read api-config.php (you need this for reading file by PHP)

share|improve this answer
add comment

First I would change the file permissions of your cfg and the files that resides therein. If you store DB - settings in it, this is a read access and write - access should be removed. It's nice to have your Apache HTTP Daemon - environment set up secure, but this is another layer of security. Your PHP - Installation runs within the user - context of your HTTP - Daemon, so I personally would even remove read access for the group. I wonder about the tests you carried out. The cfg - folder seems to be not under your DocumentRoot so it seems to be unaccessable by your HTTP - Server at a first glance. But people trying to break into your installation will not rely on this kind of approach. You have AllowOverride All Order allow,deny Allow from all in your configuration which simply means: No access control at all. You also state FollowSymLinks, which introduces other security impacts. So this installation is far behind being secure. You could secure your cfg - folder by putting a .htaccess - file in the DocumentRoot of your installations. Entries in it can strongly secure both file - and directoryaccess, e.g.

<Files RELEASE_NOTES.txt>
order allow,deny
deny from all
</Files> (taken from an magento - installation)

If you wonder of the security impacts of FollowSymLinks: Remember that PHP is running in the context of your Apache HTTP Daemon Installation and that PHP can perform Write - Operations on your file - system. If PHP - Code gets inserted into your application creating symlinks on it so that someone could spy on your file - system by just creating symlinks to the parts of your system he or her is interested in. Placing a simple .htaccess - File into your cfg - directory of the form Order allow,deny Deny from all will remove the ability to browse this directory via your HTTP Daemon. If your api.php is the front controller to your PHP - Installation / Webapp, you should consider using Apache's mod_rewrite to rewrite all URL's requested to point to your api.php, e.g.

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^ api.php [L]

in a .htaccess - file you place into the /api - directory, which will route all requests to your api.php. e.g. localhost:44448/someURL?id=988 will become a request localhost:44448/api.php?id=988 internally.
To clearify:
Rewrite - rules should not be used for access - control, they mainly have the purpose of changing how requests are processed.
Many PHP - Frameworks or CMS use the RewriteRules to have a central entry point to the web application at which application components get loaded, routing components may be invoked, and translations from URL - paramters to internal structures are performed.
E.g. Symfony2 translates Query / and Post - parameters to a more object - orientated structure, encapsulating it into an object.
Symfony2 also leverages security concepts by reading routing - informations and configurations before generating the HTTP - response, so e.g. ensuring a authentication has been performed or that a user must have the right user - role for accessing a URL -path.

share|improve this answer
add comment

You seem to have done the one critical thing, which is to put /cfg/api-config.php outside of your DocumentRoot. If /cfg isn't within the URL space, then web site users can't read it. This is the most basic precaution you can take.

Is it possible for users still to be able to read that file? Sure, if you break the configuration somewhere else (by setting up an Alias or RewriteRule to the file, for example), or if the application does something stupid like outputting the contents of the file. Application vulnerabilities are the real concern: the application has to be able to read the file, and the more complex the application, the more likely it is to have a hidden vulnerability in it. But as far as the Apache configuration goes, I think you're done.

share|improve this answer
add comment

In addition to the suggestions above, I would recommend removing write access to any files/folders in your DocumentRoot owned by your apache user. (e.g. your api.php file) This assumes that api.php (or anything it calls) doesn't need to write anything to the local web server. This should help prevent unwanted files from being written to your web server

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.