Many website owners want the ability to sell files as downloads, or make them available to registered subscribers, or make them available as free downloads. It is often the reason for having a website. There are many scripts and plugins that will enable you to do this, but unfortunately they are most certainly not created equally. It is important to choose one that is well-coded with download security in mind.
Offering downloads on your site raises some serious security issues, the main one being how do you make sure that your users can only download the files that they are entitled to? It is not an idle question, if a malicious user can exploit your download system to download configuration files for your site they can basically own your server and do what they want with it. Even if an insecure download system doesn't allow access to sensitive system files, if it allows users to access commercial files that they are not entitled to, it is a serious weakness, and one which unfortunately some commercial download systems suffer from.
So in this article I am going to discuss some strategies that a programmer can use to make offering download files as secure as possible. I am not going to put a lot of code in this article, because what I want to achieve in this article is to give non-programmers as well as novice programmers some idea of what the issues are. It is written mainly with Joomla sites in mind, although a lot of the general principles apply to almost any site.
I will start off with a thing not to do.
Don't Pass the File Path in the Download Link
As an example, look at this PHP code:
$file = $_GET['file']; echo file_get_contents($file);
Even if you are not a programmer it is not hard to fathom what this code does, it takes the file path from the user request, and uses that to fetch the file and echo the results to the browser, which downloads it. It would normally be accessed by the user with an URL like this:-
The problem is that the file path can be absolutely any one that the user chooses, they can download any file on your site just by manipulating the URL. It is just about as insecure as it is possible to be. Now you might think that no-one would be daft enough to write such an insecure script, and if they did, no-one would ever use it. Sadly, this is simply not true, I have seen examples of exactly this code in use in commercial software, and also given as an example in coding tutorials. Unfortunately it is an example of the kind of bad coding that just refuses to die.
Just don't do this, ever. If you find that you have a script on your site that does this, remove it and once and assume that your site has already been hacked, and start the clean-up.
You could make this script a bit more secure, by restricting the files that are available for downloads to a specific folder, and use the PHP basename() function to remove any additional path information from the $file variable, but still it is not a great strategy. There is no way to place any restrictions on who can download files in the folder, and it is still possible to download any file in the folder if you know or can guess its name.
Use a Database Table
A much better strategy is to save the URLs of files that should be are available for download as records in a database table. Then the user would use a download link like this:-
or if it is a commercial download then the link might have a download key attached, to authenticate the order:-
This is immediately much better. Because the user is accessing the file indirectly, by supplying the id of a database record, it means he or she can only ever access a file that the site owner has explicity decided that they want to make available for download, by adding it to the database. So it would not be possible to manipulate the url to access sensitive system files such as the Joomla configuration.php.
Of course this kind of approach requires quite a bit more work to set up, since it requires a system for creating and managing database records for the files, so it is a lot more work for a programmer (which is probably why the insecure example above refuses to die). The thing is, this is the kind of thing that Joomla is really good at, it has a set of inbuilt classes that do a lot of the heavy lifting of putting information into a database and extracting it again, so this kind of application is quick to build for a good programmer, and there really is no excuse for not doing it.
However this approach is not without its pitfalls. Firstly of course, if ever you (the programmer) are reading or writing anything from a database, you must remember to escape any user input, to avoid sql injection vulnerabilities.
Secondly, if I were a user who was presented with either of these as a download link, and because I have a devious mind, my immediate thought would be, what happens if I change the file id in the URL? The number '103' is quite obviously the id number of a database record. If there is a file number 103 then it is highly likely that there is a file with number 102, 101, and so on. So if I change the number in the URL to '102', can I get access to a file that I may not be entitled to? Clearly the answer to this is 'yes', unless there are additional restrictions in place to prevent this. This is a particularly important issue if the download is a commercial one. Unfortunately I have seen more than one Joomla commercial download plugin that suffered from this vulnerability: the plugin checked the download key, to validate the order, but neglected to check whether the valid order entitled the user to download that particular file, and just used a simple id number to identify the file. So once the user has any valid download link, they can download every single commercial file from the site just by changing the file id in the link.
You can make this harder by referencing the file in the download url by a random token rather than a predictable id number, for example
The random token will be stored in the same database table as the file URL, and can be used to fetch the file instead of the id number. A user presented with a download link like this will find it difficult to manipulate the URL to obtain a file that they are not entitled to by changing the file token, because the chances of finding a token that corresponds to a file record are quite low, so this is definitely a big improvement over the previous example. However I would not recommend entirely relying on this, it would not be difficult for a malicious user who has a valid order to write a script to randomly try download tokens. You can make this more difficult by increasing the length of the token, but computing power is increasing all the time. For the same reason it is important to make the download key which validates the order quite lengthy.
Additional Security Measures
If you are storing file information in a database record then you can also use the Joomla ACL system to assign a view level to the file, so the site owner can control which user groups have access to the file. This sort of control is most appropriate for files that you want to be freely downloadable, but only by particular Joomla user groups on your site. This is the approach that our AS3 Cloud File Manager extension takes, it applies the Joomla ACL to files and download packages (and also uses random file tokens in the URL). And I am not going to apologise for mentioning my own extension, the point is that I have spent a good deal of time thinking about these issues so I have made sure to make it as secure as I know how.
For a download system for commercial files, usually using the Joomla ACL is not appropriate, because you want to restrict the download to a single person, not a user group. So you need to have a way of validating not just the order, but the order item (that is the product) which consists of one or more files. Normally this should not be rocket science, any e-commerce system which records orders will normally record the order items as well, for example Virtuemart, Eshop and J2Store all do this. So it is just a matter of checking both the order validity, and whether the order includes the file being requested, at the time when the download occurs, to make sure that the customer is actually entitled to the file, but sadly not all programmers bother.
If you are looking for a download system where the programmer does bother, our Spiral Paid Download plugin for Virtuemart, does exactly this. And again I am not going to apologise for extolling the virtues of my own extension.
You can add an additional layer of security by storing files available for download on cloud storage systems such as Amazon S3 or Dropbox, thus completely separating them from your own system files. It is not necessary for security, it is perfectly possible to host files on your own server and securely offer them for download, but cloud storage adds an extra layer. Cloud services often have additional advantages, for example they can be more reliable for downloading large files than using your own server.
If you want to sell files hosted on Amazon S3 or Dropbox, our Spiral Paid Download plugin for Virtuemart extension can integrate with our AS3 Cloud File Manager extension to allow you to do this through Virtuemart.
Preventing Commercial Download Sharing
I do get asked from time to time, whether is it possible to stop customers who have a valid download link from sharing it with others? I don't think that there is a 100% reliable way of stopping this. You can limit the number of downloads that the link allows, or place a time limit on the downloads (and our download plugin does both these), which may help, by placing some cost on this. Or you could require that a customer be logged in - but then they could easily share their login too, so it is not foolproof. The fact is that if someone is really determined to share a file they can just put it on a file-sharing site. Unfortunately there is no technical solution to dishonesty..