I am new to web development and I'm learning PHP in order to sell a few binary files (shared Linux host). The site is not yet live.
My php scripts (50% borrowed code, 50% self-written, 95% fully understood) login to MySQL to READ the items for sale, and WRITE sale transaction data into another table. Functions.php, located in a subfolder of the webroot, contains the login name and password for MySQL.
Q1. This doesn't seem secure to me. How should the login/password info be stored so the scripts can access it? If functions.php was stored outside the webroot, could the .php files located in webroot #include (PHP "require_once") it? (I did try this once and my scripts broke in a way that seemed permissions-related -- if I knew it should work I'd keep plugging away at it)
Q2. I am unsure where to store the binaries that purchasers can download. Is it correct that savvy users can somehow find / download them (without paying) if I just store them in a subfolder of the webroot? Is it possible to use a .htaccess file to block access to the "binaries" folder within the webroot? Can black-hats get at / modify a .htaccess file?
Q3. Would it be a better idea to store the binaries (max=4Mb) in a MySQL table and copy them from there to a temp file in webroot before each download, then delete?
Q4. Can anyone recommend a set of scripts that manages this sort of thing that I could review / modify rather than reinventing the wheel?
Thanks
Q1 - Your MySQL password and other application specific settings should be stored in a separate file outside of your webroot. You can either put it out of webroot directly or restrict it via .htaccess. You can include the file or read from it as long as you know the path.
Q2 - The binaries should also be stored outside of the webroot. The ideal way to serve them would be to have them downloadable via a PHP file. This way you can do authentication before the file is served and you can make the links temporary so that users can't share it with other people
Q3 - If you use the above method, you don't need to store it as a BLOB in MySQL
Q4 - I haven't really come across anything that does and is a library/autonomous script. Serving them via the correct headers shouldn't be too difficult though.
Not sure if best practice, but this is how I'd approach it:
Q1: I store MySQL login information, along with local paths and other settings, in a config.inc.php file outside of the web root. I can then include that at the start of each script. I also use a database.inc.php which connects to MySQL and selects the database (plus a few database functions). In theory it isn't insecure inside the web root as being called directly will only execute the PHP, not display the contents of it. Storing an XML config or similar is different however!
Q2: If downloadable binaries are stored within the web root then they could be downloaded if the right URL is discovered. Instead they should be stored outside the web root, and a PHP "gateway" script serves the contents of those files if the request meets the right conditions. You may want to store a token with each purchase in your database, and only valid tokens are permitted to download the files. An example of a download script is here.
Q3: I believe it's better to use the file system to store files, rather than a database. It won't improve security over my answer to Q2 if that's what you mean.
Q4: You could try existing shopping cart software. Magento supports downloadable products.
Hope that helps
Related
Hello and thanks to everyone for reading my question.
I've been working on a PHP web program for a little while and was wondering what measures should I take to protect the source before putting it on a live server. The source isn't being distributed, it's being accessed through a website (users log into the website to use it).
First I'd like to protect the source php files from being found and downloaded. I'm not using any framework, just php and all files are in the home directory as index.php. I read around and it seems that robots.txt isn't really effective for hiding. I came across some posts of people recommending .htaccess, but I often thought it was for protecting files within a directory with a password, so not sure if there's a way to make it htaccess suitable for a web app.
Second, I'd like to protect the source files in the case someone gets access to them (either finds them and downloads them or a sys admin that has ready access to the server). I thought of source encryption with something like ioncube. My host also has GnuPG [which I'm not familiar with, any thoughts about it compared to ioncube?]
I'm not familiar with source protection, so any ideas would be nice, and of course thank you muchly :)
Just make sure your web server is set up to handle .php files correctly, and that all files have the correct .php extension (not .php.inc or similar)
As long as your server executes the PHP, no one can download its source code (ignoring any security holes in your code, which is a different topic)
There was a time when it was common to name included files along the lines of mystuff.php.inc - this is a bad idea. Say your site is at "example.com", and you store your database configuration in config.php.inc - if someone guesses this URL, they can request http://example.com/config.php.inc and get your database login in plain text..
It is a good idea to store configuration and other libraries up one directory as bisko answered - so you have a directory structure like..
/var/example.com:
include/
config.php
helper_blah.php
webroot/
index.php
view.php
This way, even if your web-server config gets screwed up, and starts serving .php files as plain text, it'll be bad, but at least you wont be announcing your database details to the world..
As for encrypting the files, I don't think this is a good idea.. The files must be unencrypted to Apache (or whatever server you're using) can access them. If Apache can access it, your sysadmin can too..
I don't think encryption is the solution to an untrustworthy sysadmin..
Well for your first point, that's web server security, which you should look for help on serverfault. Basically you would use a secure/locked directory for this, or access the files in a virtual directory via a web service.
For you second point, you would use an obfuscator for this, which will protect your source, but remember that if they get the file, you can only do so much to protect it. If they are really interested, they'll get what they want.
The first step you should take is take out all unnecessary files out of the website root and put them in some other place and leave only the files, being called from the web.
For example if you have this setup:
/var/htdocs/mysexydomain.com/root/config.php
/var/htdocs/mysexydomain.com/root/db.class.php
/var/htdocs/mysexydomain.com/root/index.php
/var/htdocs/mysexydomain.com/root/samplepage1.php
Take all the files one level above so you get
/var/htdocs/mysexydomain.com/includes/config.php
/var/htdocs/mysexydomain.com/includes/db.class.php #see the includes dir? :)
/var/htdocs/mysexydomain.com/root/index.php
/var/htdocs/mysexydomain.com/root/samplepage1.php
I'm making a web application which will only allow registered members to download zip folders from a folders directory.
I really need to know which would be the proper way to secure the folder as only members stored in my database will be able to access them so the problem is if somebody finds the directory and a file name there's nothing to stop them accessing it.
I've been doing some research and found some approaches but they all have major drawbacks.
1.) put the files outside of the webroot then use readfile to send them the data.
This is how I have it currently set up. the major draw back is that I'm on a shared server and max execution time for the script is 30 seconds (can't be changed) and if the file is big or user connection slow the timeout will be called before the download is complete.
2.) htaccess and htpasswd inside a webroot directory.
The problem with this is I don't want to have to ask the user to put a password again. unless there's a way to allow php to send the password then send a header to the actual zip file that needs to be downloaded.
3.) Keeping the files in webroot but obfuscating the file names so they are hard to guess.
this is just totally lame!
What I really would like to do is keep the files outside of web root then just send a header:location to that document to force a download, obviously as it's not in web root so the browser won't see it. is there a way around this. Is there a way to redirect to an out of web root file with header:location('/file') to force a download. thus allowing apache to serve the file and not php with readfile.
Is there some easier way to secure the folders and serve with apache that I am just not coming across? Has anybody experienced this problem before and is there an industry standard way to do this better?
I know this may resemble a repeat question but none of the answers in the other similar question gave any useful information for my needs.
What I really would like to do is keep the files outside of web root then just send a header:location to that document to force a download, obviously as it's not in web root so the browser won't see it.
More to the point, it is outside the web root so it doesn't have a URL that the server can send in the Location header.
is there a way around this. Is there a way to redirect to an out of web root file with header:location('/file') to force a download.
No. Preventing the server from simply handing over the file is the point of putting it outside the web root. If you could redirect to it, then you would just be back in "hard to guess file name" territory with the added security flaw of every file on the server being public over HTTP.
Is there some easier way to secure the folders and serve with apache that I am just not coming across.
Your options (some of which you've expressed already in the form of specific implementations) are:
Use hard to guess URLs
Put the file somewhere that Apache won't serve it by default and write code that will serve it for you
Use Apache's own password protection options
There aren't any other approaches.
Is there some easier way to secure the folders and serve with apache that I am just not coming across.
No, there isn't an easier way (but that said, all three implementations you've described are "very easy").
Another approach, which I consider really dirty but might get around your resource constraints:
Keep the files outside the web root
Configure Apache to follow symlinks
On demand: Create a symlink from under the web root to the file you want to serve
Redirect to the URI of that symlink
Have a cron job running every 5 minutes to delete old symlinks (put a timestamp in the symlink filename to help with this)
It's effectively a combination of the first two options in my previously bulleted list.
I have a website which has a lot of confidential data and code which I have custom made. I have hired a developer to do the designing and some simple PHP integration for me.
To prevent him from seeing all files, I made a test environment in one of subfolders like mywebsite.com/testfolder
Now I want him to access the db_test.php, function.php and parameter.php files which are located in the root folder such that he can just include them while executing the scripts (example mywebsite.com/testfolder/mainfile.php) and not download them (with php script or by any other means). The idea is to prevent him to see the code and just use the stuff as it is.
This would also mean that his access to the root folder should be also completely restricted except for the above mentioned files.
I have created a test database and a separate user for him so the database bit is secured.
I have also created a ftp user which can just access the testfolder through ftp
What I am concerned about is that he might run a php script that will give all secrets in the root folder.
I have myself been able to list and download files by running a simple php script from testfolder.
Please suggest how to make this work as I am planning to have a virtual team who will work on the website which will have restricted access to various different resources.
RULE NUMBER ONE: never develop on a live project.
you may create a development environment (=web site) somewhere else, put some meaningless files and/or databases there and allow your developers full access. then, from time to time, you update your working copy from the repository (you have setup hg/git repo, haven't you), review and test the changes and only then upload files to your main web site.
I have a folder (/files) and I have tons of files there that users can download. I want users to be able to download their files only and no be able to see others people file.
For example:
User A can only view and download:
- file1.doc
- file2.jpg
User B can only view and download:
- file3.txt
- file4.jpeg
User C can only view and download:
- file1.doc
- file2.jpg
- file3.txt
My idea was to put all files in the same folder so all users knows where to go. My question is: Can I use .htaccess or should I build a PHP scripts for this? What about security (which one is more secure)?
Thanks
Is it an open directory, to start with? What you could do is create a subfolder for each user, put their files in there and then assign appropriate permissions in .htaccess for said folders. However, this would require some security integration with your OS (i.e., users would have to have accounts on your machine, not just your web application)... A quick and dirty -- and insecure -- alternative would be to prepend all uploaded filenames with the username (e.g., 'file1.jpg' uploaded by 'foobar' could be named 'foobar.file1.jpg', for example), then it's just a case of your PHP script returning only those files with the respective username and perhaps stripping that part out when displaying (or again, you could use folders, as long as your script can create a new folder per user, when one doesn't exist). Another option, which is slightly more secure is to create a hash of the file and usernames in a database, rename all uploaded files with this hash and then query the database appropriately.
The best solution would definitely be OS managed accounts, a I first mentioned, but it entails more overhead.
Build a PHP script where you use readfile to send the file to the browser. This way you can restrict access for individual files, and use the authentication system you already have.
You can certainly use either htaccess or PHP for this. Neither are more secure, as far as I know, that the other - though done wrong both can permit access where none is intended!
PHP might be marginally better, since you have more flexibility (in terms of integrating it with other PHP authentication, say) and you can put the folder outside the usual web root, which is good practise anyway.
I've seen recommendations to store some or all php include files some place other than in the web document root directory (username/public_html in my case) for the specific reason of protecting php files with sensitive information (like database connection and login info) in the event that the web server hiccups and stops protecting php files and they become 'visible' to outsiders who know where to look.
It seems somewhat paranoid to me, but I'm guessing people have gotten burned badly on this before so I'm willing to go along. The suggestion usually takes the form of having the include files in something like '../include_files/' so its not directly in the document root and not directly accessible to outsiders through the web server.
My question is this: is there a significant difference in security between that way and just putting your 'include_files' directory under the document root and sticking an .htaccess file in there (with the appropriate entries)? Would putting an .htaccess file in '../include_files/' make any significant improvement there?
TIA,
Monte
Using .htaccess adds overhead since Apache has another item it needs to check for and process.
Keeping files out of web root isn't being paranoid, it's good practice. What happens if someone accesses one of the "include" files directly and it throws out revealing errors because all the pre-requisite files weren't loaded?
Each file needs to have it's own security checks to make sure it is running under the expected environment. Each executable file in a web accessible area is a potential security hole.
It really depends on what you have in your include_files. The most important thing is that you put any credentials you have outside of the document root ( database logins, etc ). Everything else really is secondary and doesn't matter that much.
If you don't want anyone stealing your source code then try to follow Zend conventions:
application
library
public
DocumentRoot points to public and that just contains media files, js/css files. HTML/views, db logic, conf/credentials are in application. Third party libraries are in library.
Theoretically, if you just stick a .htaccess file in the folder, you could still have the .php files called directly.
Taking them out of the server root; however, keeps them from be accessed ever by someone who is browsing your website.