I'm having trouble putting data in safe locations. What I want to do is allow my localhost to access the files to create my pages but prohibit all other access.
I started out trying to write a .htaccess file to prevent access to subfolders but read here that this was a poor way to do things and was getting into a tangle anyway so, following advice, I tried moving the files out of the public_html directory:
The structure is:
bits_folder
images
testimage.jpg
files
testfile.php
public_html
application
callingfile.php
With this layout, I get error 404 if I try to access anything in bits_folder from the browser, as desired. callingfile.php however does not seem able to access the testimage, but can include the php testfile.
callingfile.php:
require("../../bits_folder/files/testfile.php"); //works and displays file echo
<img src="../../bits_folder/images/testimage.jpg" //gives broken image
both the files (testimage and testfile) are in the folders where they should be.
I am assuming that the reason for this behaviour is that the img is a http request after the page is served and will thus be denied but I am no server expert. Is this the case? Can this be overcome? Should I be doing this another way?
Only place scripts and images for PHP to use outside public_html. Images and other things that are as src or otherwise linked in HTML/JavaScript cause the browser to request those. The web server will refuse to serve them from outside the public directory.
Your browser will get access denied for www.example.com/../../bits_folder/images/testimage.jpg
Related
I'm using the code in Tom's response here. However I have a script that automatically generates .html files into my public_html folder. These files are then loaded by my .php file, which looks something like this:
<?php
require('./access.php');
include('./secret_information.html');
?>
However the "secret_information.html" file is viewable by anyone without the password. I am running an Apache web server. As I understand, all html code / images to be used on a website need to be in the public_html folder. So how can I hide this information? Do I need to setup my automated scripts to generate .php files rather than .html or is there another solution?
include can access any file, as long as it is accessible by the web server.
So you can put secret_information.html anywhere in the file system, preferably outside of the document root or public_html.
If you must keep the file inside your publicly accessible web for some reason, you may use Apache's Authentication and Authorization facility.
I am attempting to create a script in PHP which reads and includes all files from a directory which is above the domain name directory.
For example:
My domain name is example.com and located in /var/www/html/example.com/ and I want /var/www/html/example.com/file.php to be able to read from:
/var/www/html/videos/video1/ which contains index.html and the folders:
/var/www/html/videos/video1/images/ and /var/www/html/videos/video1/scripts/
e.g. www.example.com/file.php?dir=/var/www/html/videos/video1/index.html
If I use include (/var/www/html/videos/video1/index.html) it will only call the html file, which is done perfectly. However all the files in images folder and the scripts folders are not able to load.
I don't want to copy or call each file separately. I want to be able to only need to call index.html and then make the browser think it's in that directory and automatically read any file within there.
I know this works because Moodle uses this method (in file.php) to protect learning files by storing them in a moodledata folder which is one level above the public folder.
I've had a look but cannot make sense of it and I've searched the Internet to achieve the method I have explained above but have not had any success.
The reason I want to do this is to avoid having duplicate video files on the server for other sites that are hosted on the same server.
Many thanks in advance and for taking the time to assist.
$dir = realpath(dirname(__FILE__)."/../");
This would be the directory you are looking for. Require files relative to that.
To output a different file look at readfile which outputs straight to the buffer or perhaps use file_get_contents which can be held in a variable.
See if you can load an image in the browser directly, if you can it's probably a problem with your code, if you can't it may be a rights issue.
I created a login page that is processed in PHP, which then allows you to type in an itemID and an image is pulled up.
Structure of the directory is the following: Webroot > (cgi-bin - css - error - images - secure - index.html)
(The ones in parenthesis are in the same directory). cgi-bin has include files, css has css files used for the website. error has files to redirect using .htaccess incase of a 401, 402, 404, 500 error, etc. Secure folder has files that verify the user is logged in before serving content. While the index is the login page.
I'm having a hard time finding information on how to protect my sensitive information from the outside (hotlinking, direct URL, etc), while still allowing my program to use it.
The program is written, and works perfectly, but I can type a direct URL to an image or cgi script and view its content. I tried using .htaccess "deny from all", but this denies access from my internal program also.
how can I block external access to the files, but still allow my php scripts/forms to retrieve the data.
Thanks for your time and help.
2 ideas:
Your program can pass the username and password, like so:
http://username:password#example.com/some_resource
Or if you know the IP address of the machines that you want to allow you can deny from all and allow from a specific IP.
I wrote this VERY simple PHP login system:
<?php
session_start();
$error = '';
if (isset($_POST['username']) && isset($_POST['password']))
{
if ($_POST['username'] == 'user' && $_POST['password'] == 'pass')
{
$_SESSION['client'] = 'ok';
Header ("location: /kit/kit/index.php");
}
else
{
$error = 'Usuario o contraseña incorrectos.';
}
}
?>
Don´t worry about the vulnerability issues, it´s not protecting anything valuable.
In every .php page i add:
<?php
session_start();
if (!isset($_SESSION['client']) || $_SESSION['client'] != 'ok')
{
Header ("location: /kit/index.php");
die();
}
?>
This protects the .php sessions just fine.
The problem is that this doesn´t protect the files.
I mean if go directly to:
something/other/file.zip
it will download it wether you have loged in or not.
I hope the question is clear enough, if not, please ask!
To stop a user from seeing the directory, all you need to do is create an index page in that folder. Ex: index.htm, index.html, default.htm, default.html.
To stop a user from entering the folder (e.g. stop anyone from viewing http://www.yoursite.com/myFolder/), you may need to access some features of your web host. Some hosts allow you to password protect files or folders. You can also create an .htaccess file/folder
An htaccess file is a simple ASCII file, such as you would create through a text editor like NotePad or SimpleText. Many people seem to have some confusion over the naming convention for the file, so let me get that out of the way.
.htaccess is the file extension. It is not file.htaccess or somepage.htaccess, it is simply named .htaccess
Create the file
In order to create the file, open up a text editor and save an empty page as .htaccess (or type in one character, as some editors will not let you save an empty page). Chances are that your editor will append its default file extension to the name (ex: for Notepad it would call the file .htaccess.txt). You need to remove the .txt (or other) file extension in order to get yourself htaccessing--yes, I know that isn't a word, but it sounds keen, don't it? You can do this by right clicking on the file and renaming it by removing anything that doesn't say .htaccess. You can also rename it via telnet or your ftp program, and you should be familiar enough with one of those so as not to need explaining.
htaccess files must be uploaded as ASCII mode, not BINARY. This makes the file usable by the server, but prevents it from being read by a browser, which can seriously compromise your security. (For example, if you have password protected directories, if a browser can read the htaccess file, then they can get the location of the authentication file and then reverse engineer the list to get full access to any portion that you previously had protected. There are different ways to prevent this, one being to place all your authentication files above the root directory so that they are not www accessible, and the other is through an htaccess series of commands that prevents itself from being accessed by a browser, more on that later)
JUST INCASE stop users from downloading your file
store all things that are downloadable ourside your document root. which means before the public_html file.
EDIT: updated the section below to show graphical representation of folder structure
how do you access them then?
work
downloadableFiles
downloadables
- memberOnlyFile.zip
- welcomePackage.zip
- memberhshipVideoVideo.mov
photos
- photo1.jpeg
- photo2.jpeg
publi c_html
- index.htm
About
- about.html
- about.gif
LogIn
- login.htm
- loginScreen.htm
- loginFancyButton.gif
Now anything in the public_html folder the world can see through your website.
Anything outside your public_html folder, will not be visible directly to the world through your website by typing the file name into the address bar in their browser. so thats a good thing as we are going to save all our files that we dont want to give access to outside of the public_html folder.
Now say if you want a certain user to be able to download a file, say maybe a logged in user, you can still make the file downloadable by having a link to that file.
If we are at the login Page, to access the loginScreen webpage you just write down the hyperlink like so:
login screen
since that page is on the same folder. now if you want to allow a user to be able to download a file from the downloadable files folder which is outside the public_html folder since it is not in that folder it self youjust reference to it like so:
How would we get to that folder if we are in the login folder as we are viewing the loginScreen.htm page, you go one folder back so we end up being in the public_html folder. then we go another folder back so we are in the work folder.
so it would look like this so far.
../../ which means two folders back.
then to access the memberonlypath.zip we then need to go into the downloadableFiles folder then we need to get into the downloadable files and then we can link it to the file membersOnlyFile.zip which is the file we were lookng for before.
so the full link now becomes
download file
This way the user cannot access the file by simply typing it on the address bar but can download it if you reference it yourself like the above.
Hope this helps
PK
Store all files you don't want downloaded outside the DocumentRoot.
You need .htaccess to deny access to the folder.
Just have a php download script like: this one that will get the file below the public_html folder.
"Static" files are served by the webserver, not PHP, so authentication is handled differently. There are two easy ways around this:
Handle all authentication in the webserver, e.g. with HTTP basic/digest authentication. Apache 2.2 has a helpful introduction.
Serve the files with PHP, e.g. with foo.php/path/to/file if you have "pathinfo" enabled (according to the PHP docs you set AcceptPathInfo=ON in the server config somewhere) or foo.php?path=path/to/file, which is pretty terrible, but oh well.
There is a more enterprisey solution:
Write an authentication module for your download server which understands authentication cookies from the other site. Many big sites do this (adcdownload.apple.com comes to mind), partly so they can stick the downloads on a CDN but still have some sort of access control.
There is a lazy workaround:
Stick everything in an "unguessable" directory name (e.g. some random base64 chars). Make sure you can't list the parent directory (the easiest way is to create an empty "index.html" file).
I am trying to secure my PHP Image upload script and the last hurdle I have to jump is making it so that users cannot directly excecute the images, but the server can still serve them in web pages. I tried changing ownership and permissions of the folders to no avail, so I am trying to store the images above public_html and display them in pages that are stored in public_html.
My File Structure:
- userimages
image.jpg
image2.jpg
- public_html
filetoserveimage.html
I tried linking to an image in the userimages folder like this:
<img src="../userimages/image.jpg">
But it does not work. Is there something I am missing here? If you have any better suggestions please let me know. I am trying to keep public users from executing potentially dangerous files they may have uploaded. Just as an extra security measure. Thanks!
You want something that's basically impossible.
The way a browser loads a page (in a very basic sense) is this:
Step 1: Download the page.
Step 2: Parse the page.
Step 3: Download anything referenced in the content of the page (images, stylesheets, javascripts, etc)
Each "Download" event is atomic.
It seems like you want to only serve images to people who have just downloaded a page that references those images.
As PHP Jedi illustrated, you can pass the files through PHP. You could expand on his code, and check the HTTP_REFERER on the request to ensure that people aren't grabbing "just" the image.
Now, serving every image through a PHP passthru script is not efficient, but it could work.
The most common reason people want to do this is to avoid "hotlinking" -- when people create image tags on other sites that reference the image on your server. When they do that, you expend resources handling requests that get presented on someone else's page.
If that's what you're really trying to avoid, you can use mod_rewrite to check the referer.
A decent-looking discussion of hotlinking/anti-hotlinking can be found here
Use an image relay script!
To serve a imagefile that is outside the public_html folder you would have to do it by a php script. E.g make a image-relay.php that reads the image that is outside the public html...
<?php
header('Content-Type: image/jpeg');
$_file = 'myimage.jpg'; // or $_GET['img']
echo file_get_contents('/myimages/'.$_file);
?>
Now, $_file could be a $_GET parameter, but its absolutley important to validate the input parameter...
now you can make an <img src="image-relay.php?img=flower.jpg"> to access a flower.jpg image that is located in /myimage/flower.jpg ...
Well, a web browser will only be able to access files and folders inside public_html.
If the public_html directory is the root of the server for your users, Apache cannot serve anything that is not inside/below that dorectory.
If you want a file to be served by Apache directly, you'll have to put it in/below public_html.
I think your misunderstanding is in the fact that if you include an image in an <img> tag, your browser will send the exact same request to the webserver to fetch it, that will be sent to the webserver if you try to open the src url of the image in your browser directly.
Therefore, either both things work, or neither.
There are hacks around, involving a (php or other) script to make sure that an IP that has requested the image has also requested the html page within the last few seconds (which will not work if the user is behind a proxy that rotates outgoing IPs) or by checking the referer (which does not work with HTTPs and also not if the user has referer disabled).
If you want to make sure that only some users can see the image (both via <img> tag and directly), you can put the image outside public_html and have a (php or other) script that verifies the user's credentials before serving the image.
If you are using Apache or lighttpd you can use the X-Sendfile header to send files that are not in the web root(provided you haven't changed the configuration of mod_xsendfile).
To learn more about X-sendfile see this site.
This solution is giving you the best possible performance as PHP doesn't send the file but the server does and therefore PHP can be exited while the files are being served.
Hope that helps.