Restrict browser access to directory files - php

In my website, i want to restrict viewing certain files which are stored in a directory called "/content" such that only logged in users can view the files
as it stands right now anyone who types in xxxxxxx.com/content/4dc32b1c0a630.png into the browser can see this image file
I've added Options -Indexes to my .htaccess file but that didn't do anything
if it is helpful my site is built using codeigniter, so a PHP solution would be great, though I'd take any advice you might have!
thank you,
Tim

You can write a controller for that purpose.
In one of my projects I've done a resized pictures controller only for logged in users. It's based on timthumb script http://code.google.com/p/timthumb/
In controller __contruct(); write user authentification code and that's all!
So you will call these files via controller, like http://www.site.com/images/1314.png

Use mod_rewrite to rewrite any accesses to anything in /content to a PHP script that will auth the user and then provide the file, either directly or via mod_xsendfile.

Put these lines in your root .htacess file to block access to content/4dc32b1c0a630.png for unauthenticated users:
Options +FollowSymlinks -MultiViews
RewriteEngine on
RewriteCond %{LA-U:REMOTE_USER} ^$
RewriteRule ^content/4dc32b1c0a630\.png/?$ - [R=403,L]
However I would suggest you use wild cards (if possible) to match blocked files above rather than listing each and every individual file.

Related

WordPress: can't achieve direct image access redirection via .htaccess

My goal is the following: when a user tries to access an image (or any other attachments in /wp-content/uploads/) I need to redirect him to a processor PHP file that will check if a user is logged in and the file is uploaded by that user.
I've come to this solution so far:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^.*wp-content/uploads/.*
RewriteRule ^wp-content/uploads/(.*)$ file-processor.php?file=$1 [QSA,L]
</IfModule>
And it just doesn't work. 😒 I've tried a huge amount of different combinations and had no luck. And then I've decided to try something simpler and found out that I can't even redirect directly accessed images via the following code (while it works fine for any other pages of the website):
Redirect 301 / https://example.com/
And that's part is really confusing... Should there be some different treatment to the files that are accessed directly?
To make it clear. With the last code I got the following behaviour:
If I try to access any page on the website (ex.: "siteurl.com" or "siteurl.com/about"), then I get redirection to "https://example.com/" as expected.
If I try to access media "siteurl.com/wp-content/uploads/2021/10/someimg.jpg", then I can access this media and see it, while I still expect to be redirected to "https://example.com", but I don't get any redirection.
The same problem happens with directly accessed files from my theme. I still can access them despite this last redirect rule in .htaccess:
Redirect 301 / https://example.com/
Could you please explain how to redirect directly accessed files then?
Thanks in advance! 😁
It sounds like you may be behind a front-end-proxy that is intended to serve your static content. (Nginx is commonly used for this.) The proxy serves the static content, completely bypassing your application server (Apache / .htaccess). This provides great performance at the expense of some functionality.
Check the HTTP response headers when requesting one of these images. You may get a clue as to what is happening by checking the Server HTTP response header.
Possible solutions would be to either:
Make an exception in the front-end proxy to exclude the /wp-content/uploads directory.
OR
Reference these images/resources by a different URL to the actual filesystem path.
Since you are wanting to "protect" these resources you would need to store them outside of the public HTML space (ie. above the document root) - so they are not accessible via the proxy. You can then use the same URL (ie. /wp-content/uploads/...) if you wish, but the script (file-processor.php) would read the file from this alternative location.

How to grant permission to certain files using .htaccess

In the wordpress site I'm developing are my digital products stored in the uploads folder. I found out that this folder is publicly accessible when you know the url.
So when I enter http://my-site.com/wp-content/uploads I get a directory listing with all files exposed en simple to download. That is not what I want of course. I found a solution on the internet using this .htaccess code:
IndexIgnore *
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^http://(www\.)?my-site\.com/ [NC]
RewriteCond %{REQUEST_URI} !hotlink\.(gif|png|jpg|doc|xls|pdf|html|htm|xlsx|docx) [NC]
RewriteRule .*\.(gif|png|jpg|doc|xls|pdf|html|htm|xlsx|docx)$ http://my-site.com
This works fine, everyone who is entering the url is redirected to the homepage.
Downloads of purchased goods are going fine to because the request is from within the site. However there is a logo file (used in the WooCommerce emails) which must be accessible. Right now the logo is not displayed in the emails because the system decide that it is not a request from within the site and the access is denied. Can I grant access to this file using an updated version of the code above and if yes what changes do I have to make? Please advice.
HTH from you soon.
First, you can disable directory listing in .htaccess by using Options -Indexes. For more information about it please refer to https://wiki.apache.org/httpd/DirectoryListings
Then, using the header Referer as a security measure can be dangerous as it can be easily changed.
You should consider replacing this part by a script which manage a kind of access-list to allow or deny the access to the original file (e.g. temporary key like on Amazon S3).

Only allow access to a file if logged in to the CMS [SilverStripe]

When a user creates a booking via this website, an invoice (pdf) will be generated and saved in assets/invoices. Only staff members will access these to download and email to the clients. However, at the moment if the exact URL is known by somebody they are able to access it whether they are logged in or not. I am trying to restrict access to these files for those logged into the CMS only. Is there a way to do that via some permissions module?
Is Secure Assets the module your after: https://github.com/silverstripe-labs/silverstripe-secureassets
With it you can set permission for Files/Folders "that mirrors the access restrictions of sitetree pages".
When I tried to achieve this through modules I was not getting any results. What I did to achieve this was adding a private folder in the assets directory, having all my secure files within this folder. I added a htaccess file within the private folder containing:
<IfModule mod_rewrite.c>
SetEnv HTTP_MOD_REWRITE On
RewriteEngine On
RewriteBase /
RewriteEngine On
RewriteCond %{HTTP_COOKIE} !cookie_name=cookie_value; [NC]
RewriteRule ^ /page-not-found [NC,L]
This code checks for a specific cookie name and a specific cookie value, if this condition is not met it will redirect the user to the page-not-found url.
Within an extension to a booking system in the CMS I had present, I set the cookie. This cookie was then set upon logging into the CMS, if a user did not have this cookie they could not view any of the files/folders within the /assets/private directory.
I've made a module a while back to do this. https://github.com/colymba/ss-privateassets
You could try it or use it to write your own.

Private folder in PHP?

My website deals with images. Whenever a user uploads an image it will be stored in "imagefiles" folder, but the problem is users can see all the images of that folder on web through http. To prevent it I made changes to .htaccess of the folder to be forbidden, but by doing that I am unable to read the images to show it on webpage myself.
So how can I make this folder such that only I can use to read it and when users try to access it through http it should say forbidden?
You could disable the index for that folder, by creating a dummy index.html page, or disabling the default index in your .htaccess with:
<Directory /path/to/image/folder>
Options -Indexes
</Directory>
That will stop people from browsing a directory listing of all images, but not stop them from accessing images directly.
If you want more fine control you should Rewrite all requests to that folder to a PHP script which will check the $_REQUEST['REQUEST_URI'] to determine what image they were trying to load, then if they are allowed to view it by whatever logic you choose, you send out the appropriate headers for the type of image it is, and readfile('/path/to/image');
Probably the most flexible way to do what you want is to get the folder with images out of reach of webserver. Then show them on your page via readfile() (as Paulpro mentioned). There is nice example of how to do that in php manual:
http://www.php.net/manual/en/function.readfile.php
Using this way you will be able very easily control users access to images on your website.
Or you can use mod_rewrite to disable access to directory listing as:
RewriteEngine On
RewriteBase /
RewriteRule ^imagefiles/?$ - [F,L,NC]

Is PHP allowed to modify .htaccess file in current folder?

I have a PHP web app located on shared hosting.
My goal is to modify .htaccess file from PHP code when the PHP page is running.
I need that .htaccess to insert a couple of mod_rewrite lines into it.
The problem is that on Windows+Apache I can dynamically modify .htaccess file
but the same code on Linux reports a problem when I try to access this file in any
way (copy or fopen):
"failed to open stream: Permission denied"
I have given .htaccess file 777 permissions - still no result.
WHat prevents me from doing this? How can I develop a workaround?
P.S.
My initial goal was to be able to add a new RewriteRule into .htaccess that maps a
newly added category_id with new category_name.
If it wasn't shared hosting, I would use something like RewriteMap (in main Apache config) and would be able to access the map file.
This is the first real limitation I've been unable to tackle with PHP+Apache, but I hope it's circuventable too.
This seems like an overly-complex solution to just having a general "load category" page that takes the category name from the URL and loads the corresponding ID.
For example, if the URL is:
http://yoursite.com/category/programming
I would remap that to something like:
http://yoursite.com/category.php?name=programming
I want to suggest something else that also works. Instead of writing a rule for every 'special' url, why not use one for all?
I found it a whole lot easier to use what wordpress uses: every url is redirected to the index.
All you have to do is, set up the index file, read in the directory that was loaded (perhaps using $_SERVER['URI_REQUEST']), and deal with it.
add to .htaccess this:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
Thanks to that chunck you have a system somewhat unlimited at your disposal. If you ever feel like renaming you categrory url, or add another special case, it's already ready!
You only need a small set of rewrite rules. To do what Chad suggests:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/category/.*$ category.php [QSA]
Thus, anytime someone navigates to /category/category_id, the request will be directed to category.php, which will be handed the /category/ URI in $_SERVER['REQUEST_URI'], from which you can easily get the category ID, and you don't need to bother with editing the .htaccess file every time you add a category.
While I agree with the above comments, it can definitely be done. PHP apps like WordPress do exactly this based on changes made on the settings page. It should be as simple as writing the file out however the parent directory NEEDS to have permission for the web server user to write to it.
If it isn't working for you the trick will be making the parent directory either 777 or 775 and having the group set to whatever group Apache runs under (usually "apache" or "www" or something similar)
Adam (commented on your question) is quite correct though, some other security layer on your server might be preventing you from doing this, and this is probably a good indication that you might be approaching the problem the wrong way.
I agree with Chad Birch. In case you can't be dissuaded, though, in your situation I would first be looking for parent directories with locked-down permissions.
FYI, one of the reasons that rewriting the .htaccess is a bad idea is that any requests that come in while the .htaccess is being rewritten will not have any of your redirects applied.

Categories