top | item 5163488

1% of CMS-Powered Sites Expose Their Database Passwords (2011)

134 points| feross | 13 years ago |feross.org | reply

90 comments

order
[+] sequoia|13 years ago|reply
0. Put local config files outside of webroot or other publicly accessible directories, include programatically.

1. Disable swap/backup files in your editor (or write them to a different location)[1]

2. Git ignore or SVN ignore swap files and backup files

3. Configure your web server to not serve such files.

Some combination of these should keep you safe. :)

[1]: in vim: noswap nobackup nowritebackup or http://vim.wikia.com/wiki/Remove_swap_and_backup_files_from_...

[+] astrodust|13 years ago|reply
Step 0 is the only way to do it. I'm constantly stunned to see how many PHP apps violate this rule.
[+] brendoncrawford|13 years ago|reply
4. Don't make live edits on your production server.
[+] calinet6|13 years ago|reply
Lol. That's just called statistics.

I bet you 1% of every web site or server in existence does something so blatantly and unthinkably wrong that it would make any sysadmins eyes pop out of his head.

1% is in fact extremely low in my opinion—my guess would be closer to 10-15% of sites have some glaring security hole.

The only important thing is to not let it be your site.

[+] stcredzero|13 years ago|reply
> I bet you 1% of every web site or server in existence does something so blatantly and unthinkably wrong that it would make any sysadmins eyes pop out of his head.

I wonder what the percentages are for cops, doctors, judges, and pilots are?

[+] im3w1l|13 years ago|reply
Or a site holding data of yours, which is harder.
[+] nodesocket|13 years ago|reply
Prevent nginx from serving files that start with a period or tilde will help.

    # prevent hidden files from being served and logged
    location ~ /\. {
      access_log off;
      log_not_found off;
      deny all;
    }

    # prevent tilde files from being served and logged
    location ~ ~$ {
      access_log off;
      log_not_found off;
      deny all;
    }
[+] romaniv|13 years ago|reply
This is a bit of a hack, since you don't really know how the "backup" file will look like. It might end with tilde, but it might end with .bkp. It's impossible to iterate through all the possibilities, just like it's impossible to separate them from valid files.

A much cleaner solution would be to separate "callable" entry-point files (like index.php) from "library" files into separate directories and point nginx/Apache only to the directory with callable files.

[+] antihero|13 years ago|reply
How utterly stupid do you have to be to engineer software that requires you to have configuration files in a publicly accessible folder? Even most shared hosts now will have a public_html folder and the ability to put sensitive stuff not inside it.

The .htaccess hacks are great but they are just patching the symptom, and one slip up and you're back to square one.

The best way to do configuration is to have it in environment variables that are populated in a completely separate config file for the specific instance, so for instance a uWSGI ini file.

This is very easy with Django and uWSGI.

In your uWSGI.ini:

    env = DJANGO_SETTINGS_MODULE=yoursite.settings.production
    env = DJANGO_SECRET_KEY=herp
    env = DJANGO_DB_PASSWORD=derp
In yoursite/settings/production.py

    from .base import *
In yoursite/settings/base.py

    import os
    
    DATABASES = {
        'default': {
            ...
            'PASSWORD': os.environ.get('DJANGO_DB_PASSWORD'),
            ...
        }
    }

    SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')
I'm not sure if this is possible with WordPress or the whole shitty PHP way of doing things - perhaps if you had a FPM pool for each site and site specific configuration in there?
[+] killahpriest|13 years ago|reply
How utterly stupid do you have to be to engineer software that requires you to have configuration files in a publicly accessible folder? Even most shared hosts now will have a public_html folder and the ability to put sensitive stuff not inside it.

Complete untrue. You can (and are advised to) move your wp-config.php above public_html. The reason its not done by default is because you just can't do this on many of the crappy hosting services, and it creates a barrier for entry for people making their first-ever site.

[+] kmfrk|13 years ago|reply

    The best way to do configuration is to have it in
    environment variables
Isn't it the only sensible way, actually?

Django doesn't expose static files the same way, so you still get away with a secret.txt stored as a file.

[+] shakesbeard|13 years ago|reply
Because your average graphics designer or blogger has no idea what Apache is, what public directories or file permissions are. They just want to run their own blog. That's why Wordpress (or PHP for that matter) is successful; it's easy to set up and get started.
[+] Kudos|13 years ago|reply
You are correct, you could do almost exactly the same thing in "the whole shitty PHP way of doing things" using FPM pools.
[+] Yaggo|13 years ago|reply
The fundamental problem with many PHP applications is that the php files are located in document root, i.e. can be potentially served as static files. More correct approach would be to put them outside document root (e.g. APP_DIR/lib), and using index.php which requires them (e.g. APP_DIR/static/index.php).
[+] bradleyland|13 years ago|reply
I'm not sure this is fair to pin on PHP in a broad way. Many PHP frameworks do not use the application file-structure root as the httpd document root.

For example with a Symfony app:

. - App root

./web/ - httpd doc root

./app/ - app files

./app/config/ - config files

Barring an exploit that lets you break out of the httpd doc root (not saying this is impossible), there is no way to request the config or app files directly.

[+] mylittlepony|13 years ago|reply
That's not restricted to PHP, since it does not even depend on the language.
[+] anu_gupta|13 years ago|reply
The title of the linked post is 1% of CMS-Powered Sites Expose Their Database Passwords - has it changed since submission?
[+] fatalerrorx3|13 years ago|reply
It looks like this article was submitted over a year ago with that original title, it's since changed it's name and was recently resubmitted
[+] gamegoblin|13 years ago|reply
It originally said 1% of Wordpress sites.
[+] Torn|13 years ago|reply
Could be HN mod editorialising at work
[+] josefresco|13 years ago|reply
To protect the wp-config.php file using htaccess is a well known security precaution for any WP pro.

The issue however is if you have a copy of said file, in which case protecting the main version would be useless.

Also I'd say the blame if you can assign any is on Vim, Emacs, Gedit, and Nano which would have had to crash in order to set these chain of events in motion.

[+] IgorPartola|13 years ago|reply
vim lets you choose where to put swp/backup files. Mine are always in ~/.vim/tmp. Avoids awkward issues with scripts that operate on the current directory recursively. And no, you cannot blame shitty security on a text editor.
[+] damncabbage|13 years ago|reply
> Also I'd say the blame if you can assign any is on Vim, Emacs, Gedit, and Nano

... Or the guy who is just editing files directly on the server (or shovelling everything up with FTP), instead of sane version control.

(I'm not sure anyone doing the former can be counted as "Pro", WP or otherwise.)

[+] jsmeaton|13 years ago|reply
Our tutor in my first year uni course taught us to put sensitive information into a folder outside the web path, and use relative paths to include the files where needed. There is absolutely zero reason these sensitive files should be accessible via URL.
[+] dave1010uk|13 years ago|reply
WordPress looks for wp-config.php in the current directory and 1 directory up, so there is no need for any use of htaccess.
[+] djt|13 years ago|reply
thanks for the summary, I had to read the whole article to pick that out. Also, if there is a connection error (such as FTP session ending) that could also leave the copy on the server.

Take away is to not use an editor that auto-saves or to save it on your local computer and put the finished file onto the server.

[+] thejosh|13 years ago|reply
wp-config.php~ and wp-config.php# and other variations may slip through a simple htaccess, even for a "wp pro" :-)
[+] analog|13 years ago|reply
Why would they not have a config folder which uses .htaccess to protect everything inside? That would close this vulnerability without affecting convenience.
[+] cdmckay|13 years ago|reply
Yii places all config information (and any files that shouldn't be accessed by a visitor) in a folder called "protected" that is behind a "deny from all" .htaccess file. WordPress should consider something like that.
[+] ck2|13 years ago|reply
While this is bad of course, you also would have to allow network access to your mysql from remote ips.

Which if allowed is even more stupid.

If you run mysql only locally then do skip-networking and if you have to have networking restrict the ips it's allowed from.

If they can use the mysql password locally, well then you have far bigger problems with security than mysql and exposed php configuration files.

[+] jrnkntl|13 years ago|reply
You can always try to append "/phpMyAdmin" to the root url, you'd be surprised how often that works.
[+] bthomas|13 years ago|reply
Wonder how many use the same password for ssh and mysql though
[+] nikcub|13 years ago|reply
The first time I read a vulnerability report about text editor backup or swap files being served as pain text was probably in the mid-to-late-90s

Some things never change.

[+] eksith|13 years ago|reply
For the majority of users that use PHP: A lot of hosts now allow editing of php.ini which isn't accessible to the web (or else it's time to switch hosts).

You can store the login credentials there : http://www.php.net/manual/en/pdo.construct.php

This is another reason why you should move away from mysql(i) to PDO.

Or if that doesn't work, try storing in the .htaccess or Apache conf environment variables : http://stackoverflow.com/a/2583857

[+] mobweb|13 years ago|reply
My small-ish personal website gets hammered everyday by bots trying to access obscure config files and installer scripts from various CMS I have never even heard about.

I think the chance of successfully obtaining DB credentials using this method is fairly high even without those "backup files" mentioned in the link.

I'd assume there are many people out there who can set up a simple CMS themself but ignore/don't understand how to properly remove the various "installer" and "configurator" scripts once they're done...

[+] itry|13 years ago|reply

  "If the text editor crashes or the SSH connection drops during editing"
What about the time of editing? During that time, the temp files exist. Are they readably? I would guess so. So even if you just edit them and have to crash, you are vurnurable.
[+] MattBearman|13 years ago|reply
This is why everything except a font accessor (index.php) should be stored in a directory behind the publicly accessible web root directory.

It's standard practice for most web frameworks, and yet it seems the most popular CMSs don't bother.

[+] analog|13 years ago|reply
It would make the CMSs harder to deploy, security gets traded off for convenience.
[+] tolos|13 years ago|reply
> Thus, 230 / 216391 = 0.11% of all websites are vulnerable.

> Latest stats say that about 13.8% of the top 10,000 websites run CMSs. If we just focus on CMS-powered websites, then the percentage of vulnerable sites is much higher:

> Thus, 230 / (216391 * 0.138) = 0.77% of websites running a CMS are vulnerable.

I don't think those numbers mean what you think they mean.

13.8% out of 10,000 doesn't say much about the top 216,391. And perhaps 0 out of 230 of the vulnerable websites use CMS, however unlikely that is.

[+] jamesbrennan|13 years ago|reply
When I'm working with CodeIgniter (which ExpressionEngine is based off), I always rewrite access to subfolders of the project to the index.php file, because that's the only file that there needs to be access to for the site to function properly. This keeps anyone from accessing configuration (or any other) files.

  RewriteCond %{REQUEST_URI} ^somefolder.*
  RewriteRule ^(.*)$ /index.php?/$1 [L]
[+] pioul|13 years ago|reply
Quite an old issue (2011), did anybody run the script to see if as many sites still publicly expose these files?
[+] jorde|13 years ago|reply
It would also be interesting to know if any of the big CMS vendors (Automattic, Drupal etc) has done anything to prevent this in the newer releases.
[+] xguru|13 years ago|reply
<Files ~ "(^#.*#|~|\.sw[op])$"> Order allow,deny Deny from all </Files>

found this in comment, it's useful to me