PHP: Allows the user to download the purchased file ONLY

I am considering a problem allowing customers buying content from me through PayPal. I offer some intangible products. When someone completes a purchase for one of these products, they will be redirected to the landing page - let me call it "thank_you.php" - which automatically queues the download and allows the link to download the queue in case it does not start automatically. This will be done by passing the unique identifier of the element to the download page ("download.php").

This method is essentially a simulation of the best answers from these threads:

PHP generates the file to download, then redirects

PHP script so that users can download a file from my site without opening a link to a file on my site?

However, I am afraid that as soon as the user is on "thank_you.php", they will be able to upload their product, and then use Firebug (or equiv.) To edit the item ID and load another item:

<a href="download.php/38a205ec300a3874c867b9db25f47c61">Download Here</a> 

to

 <a href="download.php/7c8ddc86c0e4c14517b9439c599f9957">Download Here</a> 

I need ideas and help from you guys who are much better at this than me: what (& how) I could implement as a solution that would still allow the same client to gain access and leisure, but still prevent this manipulation?

EDIT : ID hashes are used to preview and link to an element on the entire site, I'm not afraid that people guess, but rather look at the site on a separate tab to get different identifiers and just keep downloading different items.

+4
source share
5 answers

When they make a payment, they save the identifier of the download available to them and a random hash - as in the payment table. Use this hash to get the identifier. A hash should never refer to a specific product, but instead to payment.

+3
source

While these other answers suggest that you have a session with a username, it sounds as if you just created a hash for the file to hide the file name. In other words, you could also secure milk on the keyboard, and that would be your file name for each of your files.

It seems you are worried that the user will log in, pound on the keyboard and, somehow, will be in exact accordance with your monkeys. This is unlikely.

Most likely, someone will copy and paste your link and share it. It sounds as if you need to add at least one more layer to your authentication scheme (for example, a hash with the username and element identifier) ​​or with the expiration of the links.

From your comment, it also sounds like you are using a hash to identify an element in another part of your website, which means that users can determine the hash of an element by looking at a source in another part of your website. At the moment, your safety through ambiguity is very similar to mine, using code words (for example, “fish means John, cat means“ Lisa ”), gossiping with someone and saying“ fish and cat are making things up, ”all having a sheet on the side with lists written down that everyone can see. It looks like you're just trying to hide the file names so that people can't guess them. This is known as security through the unknown , and really doesn't buy you much.

Most other answers assume that the element exists and it will have several different hashes pointing to it (for example, file1 will have hash1, hash2 and hash3, which are valid links to it). In this case, they created several hashes, and each hash is unique to a specific user +. I think they also assume that everything on the site is you linking to the download element as item1 not hash1 , which sounds like you are doing?

You might be better off just creating a dictionary somewhere in your code that has mappings between the element name and the hash, and then only on the download page, replace the hash for the name. Again, this is only security through obscurity, the link can be shared, but people will not be able to get the hash just by browsing your site.

+4
source

My original answer:

You will need to store (be in a database or a session variable) which elements the user can receive, for each you create a unique random token. This token will be used to identify purchased goods. Pass the token to the page where they will be loaded (either in the session variable, or in the POST argument, or as the last option in the URL, i.e. GET). On the page, when you need to download, you will query the database / session variable, using the session information to identify the client and the transferred token (however you transferred it), and with this, extract the file to download.

If you need to keep a list of purchased items for reloading, you can also do this, but remember to create tokens again when the user requests a download. You can also add an expiration date if you like it.


Now I have mentioned a couple of alternatives, and then by the nature of the answers given, I think you will need more detailed information on how to do this.

Maybe Ernie is right, and I should not assume that you have a session. Maybe I should show you how to do the session.

So, I'll take one of the implementation options, the easiest option.


 <?php //Oh, I'm in a PHP page... //check if there is not a session if (session_id() != '') { //Ok, there is no session, let create one session_start(); } //Now we are sure there is a session //Let store in the session the id of the file I want to allow to download $_SESSION['download'] = GetFileId(); //GetFileId will do some mambo jambo expecto patronum to return an id //The id will be 38a205ec300a3874c867b9db25f47c61 or something ?> 

Now on the download page ....

 <?php //Oh, I'm in another PHP page... //check if there is not a session if (session_id() != '') { //no session? screw you, no download for you header('Location: sorry.php'); } else { //Now we are sure there is a session //Let get from the session the id of the file I want to allow to download $id = $_SESSION['download']; //Now get the url to redirect to allow the download $url = GetUrl($id); //GetUrl will do some mambo jambo expecto patronum to return an url //Ok, now we are going to return that file... //So put the correct MIME type header('content-type: image/gif'); //if it is a gif... //Load the file $contents = file_get_contents($url); echo $contents; //That the only output exit(); } ?> 

Please note that I only allow access to the file with PHP, so I can first check if the user has access. You should not allow the user to simply put the URL (even he cannot guess) and access the file. Therefore, if you use your server, you want to place these files outside the server’s web folder, or if you use the hosting protected by it with .htaccess (or another mechanism provided by your hosting).


In accordance with this decision:

It is simple, easy to implement. However, it has some disadvantages:

  • If the session ends before downloading, the user has lost his money *.
  • There is no clear way to implement reloading.
  • It is still vulnerable to session hijacking (far away, I know, but it's better to be safe).

*: Say that the connection was lost and the session expired in the client. Oh no, we don’t need happy customers.

So, you really need to restore this using the database and create random tokens, preferably with an expiration date.

+3
source

One of the easiest things you could implement is a registration system to track user purchases. You can cross-reference the requested identifier with identifiers stored in relation to user purchases. If they are not connected, do not serve the file.

+1
source

You need to keep track of which items the user has purchased in the database. download.php can check if the user has purchased the item they are trying to download.

+1
source

Source: https://habr.com/ru/post/1437706/


All Articles