I have a subdirectory of users that I want to limit each subfolder to that user only.
For example I have /users/user1 where I want to protect the user1 folder so that only user1 can access the files inside.
I tried playing around with an .htaccess and .htpasswd file, but I get prompted to log in a second time even though I have authenticated against a MySQL database.
I'm not sure what to do to basically have the second log in request automatically handled since the user would be authenticated previously.
I can post some code that I have for my .ht files, but I thought that this info could get the ball rolling.
I think that using a php proxy to access the files would be sufficient in this case, something along the lines of:
Download.php
<?php
/** Load your user assumed $user **/
$file = trim($_GET['file']);
/** Sanitize file name here **/
if (true === file_exists('/users/user'.$user->id.'/'.$file)) {
//from http://php.net/manual/en/function.readfile.php
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$file.'"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
} else {
throw new Exception('File Not Found');
}
.htaccess To deny all direct file downloads
deny from all
You would then link to the folders by using /download.php?file=filename.ext and it would only download that file from the users directory of the current user.
You'll want to ensure you sanitize the input file name so you're not vulnerable to directory transversal exploits.
Related
Download.php
<?php
$file = $_GET['file'];
if(file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
?>
Following is the JavaScript code I'm using to pass the url to php script:
Download.js
init:function(){
this.control({
'#downloadSite': {
load:function(tree, node, records, successful, eOpts)
{
},
itemclick: function(tree, record, item, index)
{
if(record.get('id') == 300){
window.open('Download.php?file=../TAB/'+record.get('url'));
}
else{
window.open('Download.php?file=../PDF/'+record.get('url'));
}
},
beforeitemclick: function(tree, record, item, index)
{
if(record.get('leaf') == false) return false;
},
beforeitemdblclick: function(){
return false;
}
}
});
}
If I am entering "Download.php?file=../web.config" in the url , web.config file is being downloaded. I want to prevent direct download of source code. the download option is for downloading pdf files that I have stored in the pdf's folder in the main directory.
Please help !!
You've fallen fowl of a pretty bad design decision here that makes you vulnerable to file system traversal.
You might consider:
Ensure the requested file ends in .pdf
Ensure that the file being read ends in .pdf
Drop any requests where the file parameter contains ..
Given Download.php doens't look to be ensuring requesters are authenticated at all, I would suggest maybe having your PDF documents live within a web accessible directory and just linking directly to them, instead of creating an attack vector that could compromise your server.
Use this in web.config,
<authorization>
<allow users="user1, user2"/>
<deny users=”?”/>
</authorization>
https://support.microsoft.com/en-us/help/815151/how-to-restrict-specific-users-from-gaining-access-to-specified-web-re
Don't allow the code to circumvent this, as Michael M is saying.
I have a directory on my server that I want the general public to not have access to. (Nothing. No access to php files, images, anything.)
But I want to allow certain users to access this restricted area based on a boolean value in my php.
Is there any way to use PHP to determine whether or not a user can access a directory, similar to the using an htaccess file but with more customized logic?
One of the easiest way is to redirect restricted users to your homepage.
<?php
header( 'Location: http://www.yoursite.com' ) ;
exit;
?>
You can allow access to specific users by setting Boolean value in your DB.
Below solution will work based on your file storage location.
$file = '/file.png'; // set your file location
$userAccess = false;
if (file_exists($file) && $userAccess) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=your_file.png');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
}
Check this link also.
Hope it will help you :)
So I finally found an answer elsewhere and it involves setting up a PHP file as a sort of proxy in conjunction with htaccess - http://simpletek.raivo.id.lv/restrict-server-files-access-based-on-php-logic/
I want to make a webpage which has download option for a pdf, but i want it password protected i.e. if someone clicks on that link he has to enter username and password and if he directly open the link "www.example.com/~folder_name/abc.pdf" then server ask for password first and then allow to download
Edit: I want user to view the file in browser, not to force it to download
here is my code
<?php
/* authentication script goes here*/
$file = 'http://example.com/folder_name/abc.pdf';
//header('Content-Description: File Transfer');
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename=' . basename($file));
header('Content-Transfer-Encoding: binary');
//header('Expires: 0');
//header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
//header('Pragma: public');
header('Content-Length: ' . filesize($file));
header('Accept-Ranges: bytes');
#readfile($file);
?>
but this code is not opening pdf in my browser.
I don't want code to depend upon pdf plugin used by browser
You can make a .htaccess file in the web folder you have the download set up at so that before anyone can enter the domain, they have to enter the correct user and password to get in.
Here's a blog post that I used when I set up my own but essentially your .htaccess file will look like this:
AuthType Basic
AuthName "restricted area"
AuthUserFile /path/to/file/directory-you-want-to-protect/.htpasswd
require valid-user
You also need to create a .htpasswd file where you can put a username and a password. The password needs to be encrypted with MD5 hash but you can use the generator he links to in his blog. Hope this helps.
You can still use .htaccess to not let anyone directly download your document and secure the link to the document instead.
.htaccess could be like this
RewriteRule ^([A-Za-z0-9-]+).pdf$ index.php [L,QSA]
And you can use php for that.
Somethink like this
<?php
//here you authenticate user with your script
//and then let the user download it
if (!isset($_SESSION['authenticated']))
{
header('Location: http://www.example.com/');
exit;
}
$file = 'www.example.com/~folder_name/abc.pdf';
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
?>
Hi I am letting users purchase hidden virtual mov.zip files with paypal. I got the transaction part and the storing the details in the database etc... but after the user comes back to the transaction page I want to link them to the zipped file which is in a restricted folder (.htaccess deny from all). how can i grant them access into this directory to download the file for a couple of days. I can't temporarily move the file out of the directory because of its very large size (its a package of hd action effects).
Thank you.
If your hosting allow you to change the PHP setting for the script timeout, you could just stream the file through a PHP script that would check the user access.
For example, the request :
>http://domain.com/download.php?file=be6bc64c94bbc062bcebfb40b4f93304
<?php
session_start();
if (!isset($_GET['file']) header('Location: index.php'); // invalid request
// 1. check user session
...
// 2. get file from hash (use a Db like MySQL
$file = ...;
// 3. check user privilege for the given file
...
// 4. proceed to download
if (file_exists($file)) {
set_time_limit(0);
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
} else {
// error 404
}
i have some questions on how folders and files permissions work. say i have users directories outside 'protected' as below..
users
-- usera
-- docs
-- userb
-- docs
protected
i do not want user B who does not have the rights, to access anything in user A directories. also, i do not want any person to access the directories directory via url links. basically i just want users to be able to access their own directories, and no one else. how can it be done?
thanks!
I answered a simular question here limiting users to subdirectories which you should be able to adjust to suit your needs, I've copied it here as well.
Download.php
<?php
/** Load your user assumed $user **/
$file = trim($_GET['file']);
/** Sanitize file name here **/
if (true === file_exists('/users/user'.$user->id.'/'.$file)) {
//from http://php.net/manual/en/function.readfile.php
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$file.'"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
} else {
throw new Exception('File Not Found');
}
.htaccess To deny all direct file downloads
deny from all
You would then link to the folders by using /download.php?file=filename.ext and it would only download that file from the users directory of the current user.
You'll want to ensure you sanitize the input file name so you're not vulnerable to directory transversal exploits.
Without more info to go on, my suggestion would be to make sure the user directories are above the web root. This will prevent them from being linked to. Then create a PHP script that validates that a user is who they say they are. Once you know the identify of a logged in user, you can use fpassthru() (http://php.net/fpassthru) or similar to deliver the docs to the user.