URL Rewriting to Privately Access Files - php

I'm trying to build a simple website which is going to let users upload files, and privately share them with other designated users. The problem is: I don't want anyone to be able to type in the url for a file to be able to get to it (then anyone could see it).
I decided to try using .htaccess to prevent direct url access, however, I cannot figure out how to access the file myself. All of the uploaded files are going to go into a subfolder called "restricted".
My ".htaccess" file is:
RewriteEngine on
RewriteCond {%QUERY_STRING} !^.*key=SECRET.*$ [NC]
RewriteRule ^restricted/(.*)$ showfile.php?file=$1
My "showfile.php" file:
<?php
echo file_get_contents('[...]/restricted/'.$_GET['file'].'?key=SECRET');
?>
However, when I open "restricted/test.txt" or some other file in the restricted folder, it successfully redirects to "showfile.php?file=test.txt", however, I get a php error:
Warning: file_get_contents([...]/restricted/test.txt?key=SECRET)
[function.file-get-contents]: failed to open stream: No such file or
directory in [...]/showfile.php on line 10
It seems like even though the query string contains "key=SECRET", it is still trying to redirect.
What I want: I want it to redirect on direct URL access, but that I can access it through the php page it's redirected to.

If you want to access the file as an HTTP resource instead of direct disk access (like in your question), you can do the following:
Code in .htaccess (placed the "nonpublic_test" folder):
RewriteEngine on
RewriteCond %{REQUEST_URI} ^.*/restricted/.*$ [NC]
RewriteCond %{QUERY_STRING} !^.*key=SECRET.*$ [NC]
RewriteRule ^(.*)$ /$1 [R=403,L]
Then in your showfile.php:
<?php
echo file_get_contents('http://www.domain.name.here/restricted/'.$_GET['file'].'?key=SECRET');
?>
This will prevent any access to the restricted folder and its contents but still allow your showfile.php script to access the file inside that folder and output it.

It would be better off to move restricted folder a level above site root and have your PHP code in showfile.php like this:
<?php
echo file_get_contents('/path/to/restricted/'.$_GET['file']);
?>
With rule simply as:
RewriteEngine on
RewriteRule ^restricted/(.*)$ showfile.php?file=$1 [L,QSA,NC]

Related

htaccess - check if original URL in the HTML contained `../`

I have a directory tree that looks like:
public_html
_COMMON
INIT.php
project-1
index.php
project-2
index.php
Those two projects use files from _COMMON. First, they load some configuration via the following code in their index.php:
require_once '../_COMMON/INIT.php';
After that, they use common resources via:
<script src="../_COMMON/node_modules/jquery/dist/jquery.min.js"></script>
I have two domains. They are both connected to the same server, meaning they both serve the same files. I want to serve project-1 from:
http://example.com/project-1/
and
http://project1.com/
To do that, I rewrite project1.com URLs to project1.com/project-1/ with the following htaccess:
RewriteCond %{HTTP_HOST} ^(?:www\.)?project1.com$
RewriteCond %{REQUEST_URI} !/project-1
RewriteRule ^(.*)$ /project-1/$1 [L,NC,QSA]
Problem comes here.
The require_once part works because the URL of INIT.php is resolved after the request URL is rewritten, meaning:
User vists http://project1.com/
URL rewritten to http://project1.com/project-1/
Executing http://project1.com/project-1/index.php
http://project1.com/project-1/index.php with ../_COMMON/INIT.php resolved to http://project1.com/_COMMON/INIT.php
However, the script isn't loaded successfully. I guess that's because the URL of jquery.min.js is resolved in the browser, before the URL is rewritten. I guess the following happens:
User vists http://project1.com/
http://project1.com/project-1/index.php is served, but URL is http://project1.com/
Browser sees ../_COMMON/node_modules... and tries to resolve it
Browser initiates a request for http://project1.com/_COMMON/node_modules/jquery/dist/jquery.min.js
URL is rewritten to http://project1.com/project-1/_COMMON/... which doesn't exist
What I've tried
I could just add this:
RewriteCond %{REQUEST_URI} !/_COMMON
to my htaccess and be done.
That's kind of a cheesy solution, though. What If project-1 uses a file from another directory at the root? Adding all those directories in the htaccess seems silly. I don't need to rewrite the URL if it doesn't contain _COMMON, I need to rewrite it if it doesn't go up the directory tree, I.E. if it contains ../. Is there a way to detect that?
Basically, what I want is to not rewrite URLs that begin with ../. I tried:
RewriteCond %{REQUEST_URI} !\.\./
but it doesn't work. I guess it's because that ../ is resolved in the browser, so it's not inside the URL that is actually processed by the htaccess. Is there some other way I could detect whether the original URL contained ../?

Deny access to all files in a directory unless a specific php page is referrer

We have files stored in a directory "uploads/downloads" which are accessed through a php file in the manner of https://www.example.com/request_file.php?file=123. That PHP file queries a database table and returns a file stored in the directory mentioned.
Using htaccess (I presume) how can I deny access to any files in the "uploads/downloads" directory unless the are being accessed through the request_file.php page?
Try something like this:
RewriteEngine On
RewriteCond %{HTTP_REFERER} !request_file.php
RewriteRule ^uploads/downloads/ - [L,R=404]

How to create fake PHP directory that mapped to another PHP directory?

For example, I have a folder web.com/app/resource/css/ and from browser perspective I want the user to be able to access this folder via url web.com/css/ instead of web.com/app/resource/css/. How do I accomplish this with PHP?
Put this in your .htaccess file:
RewriteEngine On
RewriteRule ^css app/resources/css/ [QSA,NC,L]

Prevent direct PDF file access from URL

Redirected from here, I need to prevent access of PDF (or any other) file types, when someone access it using direct URL.
The Problem
Say you had a PDF file that you’d like visitors on your own site to download.
However, if someone were to copy this link and call it from a browser window directly, or if they were to post the link to you PDF on another website then the document shall not be accessible. By default it is.
I am successful in hiding the pdf file path in address bar and the url formed is http://localhost/myproject/web/viewer.php?id=11&name=sample.pdf, but in console one can see the complete path like http://localhost/myproject/document/11/sample.pdf.
This code redirects successfully on second time page reload, but not when I select Open in new tab from console.
RewriteCond %{HTTP_REFERER} !^http://(www\.)?localhost [NC]
RewriteCond %{REQUEST_URI} !hotlink\.(pdf) [NC]
RewriteRule .*\.(pdf)$ http://google.com/ [NC]
Used below code in .htaccess to prevent access
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^http://(www\.)?localhost [NC]
RewriteCond %{HTTP_REFERER} !^http://(www\.)?localhost.*$ [NC]
RewriteRule \.(pdf)$ - [F]
Somehow it does not work accurately. It shows file forbidden message only if I hit CTRL+SHIFT+R key otherwise using the file URL I can still access it.
I want to prevent the pdf file showing as http://localhost/myproject/document/11/sample.pdf directly in the url bar
If you have access to a database, maybe you could store the file/s in a blob field. This way you can easily write code to protect the file how you like.
You can store PDF files not in webroot folder and return it content use PHP. For example for user URL will be like:
http://localhost/myproject/document.php?hash=some_hash`
and on file document.php you will get document hash from $_GET parametr use file_get_contents function. Also in this case you can allow access only once
I hope it will help

.htaccess WP-admin url twice

I am unable to access my WordPress site URL, it redirects like
http://www.mydomain.net/wp-login.php?redirect_to=http%3A%2F%2Fmydomain.net%2Fmydomain.net%2Fwp-admin%2F&reauth=1
but it shoud redirect to
http://www.mydomain.net/wp-login.php?redirect_to=http%3A%2F%2Fmydomain.net%2Fwp-admin%2F&reauth=1
I believe the problem is with .htaccess file as I am rewriting the path of folder like
public_html/mydomain.net
instead of public_html as this domain is primary domain of cPanel but to avoid confusing, I created a directory and rewriting path using .htaccess.
There is nothing wrong with WordPress. In settings>general both the URLs set to mydomain.net
.htaccess code is Placed in Public_HTML
RewriteEngine on
RewriteCond %{HTTP_HOST} ^mydomain.net$ [NC,OR]
RewriteCond %{HTTP_HOST} ^www.mydomain.net$
RewriteCond %{REQUEST_URI} !mydomain.net/
RewriteRule (.*) /mydomain.net/$1 [L]
I had a similar problem after changing the root directory of my blog (before migration) and trying to coming back... Changing the data in my DB was not working for me.
I still did not figure out why but I had a "page not found" when I tried to access categories, tags,... and even on the home page. Links to articles worked correcly and the administration page was not accessible (wp-admin rewritten twice in the url).
These actions solved my problem:
Edit the wp-config.php file.
After the "define" statements (just before the comment line that says "That's all, stop editing!"), insert a new line, and type:
define('RELOCATE',true);
Save your wp-config.php file.
Open a web browser and manually point it to wp-login.php on the new server.
I had to change the value of the root directory in the administration page (after these actions gave me back the access to it).
Check http://codex.wordpress.org/Changing_The_Site_URL#Relocate_method for more info.

Categories