I am looking at ways to restrict direct access to the WordPress Uploads folder. I’ve read a handful of Stackoverflow and blog posts about using “wordpress_logged_in” in .htaccess to check if a person is logged in and if they are not to restrict them. See example of a snippet below.
However, I also read a post that was written almost 10 years ago that it would be preferable to do this via PHP as checking for a cookie isn’t very secure and could be hackable. However, since then WordPress has improved how cookies are done and are more secure as I understand it.
Old Stackoverflow thread here.
How to Protect Uploads, if User is not Logged In?
How hackable is checking for a cookie if a person is logged in? Is the idea here that a person could Brute Force the cookie? For me this solution is more straightforward and something I can easily wrap my head around.
Htacess Example here – Check to see if a person is logged in:
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} (.*)
RewriteCond %{HTTP_COOKIE} !wordpress_logged_in_([a-zA-Z0-9_]*) [NC]
RewriteRule .* - [F,L]
</IfModule>
Check to see if a person is logged in:
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} (.*)
RewriteCond %{HTTP_COOKIE} !wordpress_logged_in_([a-zA-Z0-9_]*) [NC]
RewriteRule .* - [F,L]
</IfModule>
The same applies as it did 10 years ago. This code in .htaccess
doesn’t have anything to do with how WordPress might be setting cookies. And this does not “check to see if a person is logged in”. It simply checks that a string that matches the regex wordpress_logged_in_([a-zA-Z0-9_]*)
does not appear anywhere in the Cookie
header. The “problem” here is that anyone can create a request that passes a value in the Cookie
header that passes your test. Since it is well known that WP sets such a cookie then it is not difficult to guess.
The only way to check that the request is “logged in” to WordPress is to use PHP.
Aside: The first RewriteCond
directive that checks against REQUEST_FILENAME
is superfluous since it simply checks against anything. The NC
flag on the second condition should not be used in such checks, since you are now unnecessarily increasing the range of strings that would pass the test (eg. wOrDpReSs_LoGgEd_In_
would pass). Consequently, including A-Z
in the hash portion is unnecessarily – the hash is always lowercase (and always 32 chars long AFAIK). The L
flag is not required when used with the F
flag (it is implied) and the regex .*
will block all requests if that cookie does not exist, not just access to the WordPress uploads folder. You should also avoid using the <IfModule mod_rewrite.c>
wrapper for anything security related, since a “failure” in your server config (ie. mod_rewrite being erroneously disabled) would allow unrestricted access, instead of breaking with an error (which would be preferable).
So, the above should be written like this:
RewriteCond %{HTTP_COOKIE} !(?:^|;\s)wordpress_logged_in_[a-z0-9_]{32}=
RewriteRule ^wp-content/uploads/ - [F]
The regex (?:^|;\s)wordpress_logged_in_[a-z0-9_]{32}=
specifically checks for that cookie name (more specific), rather than a string that occurs anywhere in the Cookie
header (too general).
(Although, to clarify, this is really no more “secure” than the original code snippet.)