11 comments

  1. Chris says:

    Great post. I was wondering….. I have a site that is restricted to the public (unless you are a WP member of the site). But I’ve noticed that you can access FILES directly even if you are not a member (e.g. http://site.com/wp/uploads/something.pdf). Is there a way for ALL content to redirect to the login page if you aren’t logged in?

    Thanks!

    Reply

    Cory reply on January 27th, 2010 17.49.39:

    There are ways, but they’re all pretty cumbersome or flawed. ATM, the best way I can think of is to wrap all content in PHP.

    * You would use mod_rewrite to check if the user is requesting something in ^/wp-uploads/.* (That’s a regex that detects if anything in the folder of wp-uploads or below is being requested.
    * All the requests would then be redirected to a file that you would need to create in your site root, let’s call it binauth.php

    So… using your example and mod_rewrite rules that I leave it up to you to create, a request to wp-uploads/something.pdf would be redirected to http://site.com/binauth.php?path=wp-uploads/something.pdf

    This file would then use WP’s internal functions to determine if the user has been properly authenticated. At this point, you would know the file they are requesting, along with if they are logged in and authorized to view the content.

    You could then do one of two things:

    1. Issue the proper headers (like Content-type) for the file, and use PHP’s readfile to send it to the user. (This is the only way to do it securely)
    2. Redirect the user to the file at auth-uploads/something.pdf You would then have to create a rewrite rule that detects and directs these requests to the correct location internally. This is NOT secure, but would prevent the average user from being able to access your files.

    If the user is not logged in, you would issue a 403 (not authorized) error, and they wouldn’t see your files.

    You would also probably want to set up a rule in robots.txt to prevent spiders from even trying to access your files:
    User-agent: *
    Disallow: /wp-uploads/*
    Disallow: /auth-uploads/*

    There is probably a WP plugin out there to do this automatically. I didn’t bother searching.

    Reply

    Jim reply on July 20th, 2010 15.05.25:

    FYI, most spiders skip the rules in robots.txt or do even use the info there to index your precious posts…

    This is a better idea: http://perishablepress.com/press/2010/07/14/blackhole-bad-bots/

    Reply

  2. Lee says:

    Hey, great job!! I’ve been trying to mess with other htaccess files and they’re just not as clean and simple as the method you came up with! One time I didn’t realize I wasn’t getting comments because of the htaccess file was blocking whenever someone tried to post a comment. I also wanted to ask a question, the wp-includes directory by default is listed by going to domain.com/wp-includes… dropping a blank index.php or html file will suffice restricting access right? putting Options -Indexes in the htaccess file would effectively do the same thing, correct?

    Reply

    Cory reply on March 8th, 2010 19.50.49:

    Hey Lee. Sorry I missed your comment!

    > dropping a blank index.php or html file will suffice restricting access right? putting Options -Indexes in the htaccess file would effectively do the same thing, correct?

    Absolutely right. Whenever I make something from scratch, I’ve just got in the habit of creating blank index.html files. You never know if the server your code is going to run on will have indexes disabled or even index.php configured to be an directory index.

    # modifiy the apache httpd.conf DirectoryIndex directive
    # http://httpd.apache.org/docs/1.3/mod/mod_dir.html#directoryindex
    # fulfilled from left to right (index.php will be used before index.html etc.)
    DirectoryIndex index.php index.html index.htm
    

    Options -Indexes is a good idea to use server wide if you have files that should stay hidden, but it should also work with .htaccess. http://httpd.apache.org/docs/1.3/mod/core.html#options

    It is generally considered a better idea to store any files that shouldn’t be listed outside of webroot if at all possible. Things like database connection credentials and whatnot — or a directory of porn that you’ve been squirreling away on the company webserver. You know, the usual stuff.

    Reply

  3. Interesting: but what permissions should be set for the .htaccess file? If set to 644, anyone can read it, which rather defeats the point of the exercise…

    Reply

    Cory reply on March 8th, 2010 18.41.01:

    Hi Donald. Your apache config should be set to disallow serving of all dot files. (.htaccess, .htpasswd etc). I think most flavors of apache installs come preconfigured this way.

    I’m not sure that prohibiting access to your htaccess file is a concern from the filesystem side of things? Do you disagree? I’d be more concerned about disallowing access to wp-config.php and your DB login and pw.

    Reply

  4. @Cory: Yes, you’re right, my server certainly blocks all access to dot files. My concern was just that the secret word, in your solution, is included in the htaccess file, so somehow people might be able to read it if they _did_ gain access. An extra layer can be added by including the following:

    # secure htaccess file

    order allow,deny
    deny from all

    Reply

    Cory reply on March 8th, 2010 19.36.30:

    Ahh… I see where you’re coming from.

    Just for completeness for the generations to come, the following will prevent access to .ht* files:

    <FilesMatch "^\.ht">
        Order allow,deny
        Deny from all
    </FilesMatch>
    

    You would put that in your httpd.conf as its own directive.

    edit: Removed “satisfy all”. It is included with wamps httpd.conf, but not necessary because this is the default setting for apache.

    Reply

  5. Sofia says:

    I love your version! Have just set up my own self-hosted WordPress blog and have read up on security – was just about to go with the IP limiting before accidentally stumbling over this post.

    I tried to set this up in my htaccess but for some reason it’s not working. I copied your code and replaced the capital letters with my own stuff, have tried many times with different keywords – no success – instead I end up on the front page. Any ideas why?

    Reply

  6. Mark says:

    Hi Cory,

    this is what I was looking for! :)
    Had a lot to google!

    As I am not very experienced in writing htaccess-files.
    How would the sample look like, if I would have my blog in a subdirectory of my domain like /blog/ and the blog would be visible by visiting
    http://www.mydomain.com/blog/

    and where would I have to put the htaccess-file?
    In the root-folder?

    All the best
    Mark

    Reply

Leave a Reply