PHPNewbie
PHPNewbie

Reputation: 41

Does this seem like a secure way to allow user's to share their data publically?

I have a PHP application that allows users to manage financial data.

I have had requests from some users to make it possible to publicly share their data via link. So, for example, a user might open their dataset, apply various filters, and then want to be able to directly share the resulting dataset (readonly) with someone else.

At present, data can only be viewed when logged in to your account.

There is already the ability to export the resulting dataset to a pdf or csv file, but what people want is to be able to generate a link and share this.

So, I was planning the following:

At present, when filters are applied to a user's dataset, this is reflected in the URL eg. mycontracts.php?budget=1&provider=2&agreed=no

Session data is used to ensure that logged in users can only view their own records. So it would be dead easy to create a non-secured page with access to the database, whereby a query like:

public.php?user=1272&budget=1&provider=2&agreed=no

Would output all the data.

The obvious issue with this is that by modifying the URL, anyone could gain access to anyone's data.

So, what I was going to do is when a user wants to share their filtered (or unfiltered) dataset, I basically get the values of all the URL Parameters and put them into a string (so in the above example: 127212no) and then add a random salt (eg. %^%Sd&tG*112) and then hash and bind this to the URL... so they'd end up with something like

public.php?user=1272&budget=1&provider=2&agreed=no&key=b89eaac7e61417341b710b727768294d0e6a277b

The public.php script would then be able to double check that the variables provided generate the same hash, and only then would it load the data. That way, any attempt to modify the URL parameters would result in a hash mismatch. I had also considered adding a unix timestamp to the shareable URL (which would also become part of the hash) to make it so shared links automatically expire after a certain amount of time.

Are there any security issues with the above approach? The only thing I can think of is that it reveals a user's actual ID number, but there's nothing that could be done with it.

Upvotes: 2

Views: 142

Answers (2)

KIKO Software
KIKO Software

Reputation: 16688

I agree with everything deceze has said. But, in the end, you're still give the public access to the inner workings of your application.

Suppose you make a programming mistake, however unlikely that may seem, and there is a bug that leaks information, then hackers would have access to the information in the database. This is still a real possibility.

No matter how you look at it, what you're really doing is make a tiny hole in the security of your application. A controlled hole, hopefully, but still a hole. I think that is a bad idea.

What is my solution?

You already have two other types of output: A pdf or csv file. You could add an HTML file to that, and allow user to store that file on your server so the public can access it. In other words: You don't give access to the real data of the user, you give access to a stored copy of that data. How exactly you store this copy is up to you.

This way a hacker can never "hack" the URL, because only published copies of the data are available. Users still completely control this copy, they could delete it, or restrict access. Another advantage is that the shared information is fixed, it cannot change.

However the main point is that this way you don't give access to the user's data in the database, based on the url, in any way.

Upvotes: 2

deceze
deceze

Reputation: 522042

If your only security mechanism is that you hash information present in the URL with a set hashing algorithm (and yes, adding a static salt is for all intents and purposes just a slightly altered algorithm), then once that algorithm gets known your security is gone. Anyone can generate any URL they want themselves with the expected hash value. A skilled attacker could discover the used algorithm (and salt) with a bit of experimentation locally on their own machine fairly quickly.

If anything, you'll want to use a cryptographically secure hashing algorithm which involves a secret and is slow, so a brute force attack will take impractically long. Instead of reinventing the wheel there, look at existing schemes like JWT for this purpose.

However, I'd suggest you make this even more explicit and store the parameters in the database, attach a randomly generated string of sufficient length to it, and share that random string, e.g. example.com/public.php?key=pio7632hmNM2bf3o2f8lkIYHbfe. With this you have full control over what data is publicly shared and what isn't and there's no attack surface for even attempting to brute force any algorithm. Users are also able to revoke publicly shared URLs. The only thing you need to protect from is someone trying to crawl every possible key from your website to discover valid keys, for which rate limiting and/or something like fail2ban is a must.

Upvotes: 4

Related Questions