5

I use the following url when I edit a post from the user :

../post/edit/3            //If the id of the post is 3 for example

To avoid that the user modifies the url intentionally, for example /post/edit/5, I use the following logic to make sure the user doesn't edit the post when he doesn't have permission:

if (//user is allowed to edit post){
    //edit post
}
else {
    throw new AccessDeniedException('You do not have the permission to edit this post');
}

Is this the general approach that you use when editing a post? Is there a way to do something cleaner so that the user cannot play with the id of the post in the url?

EDIT

The more I think about it, the more I realize that I have never seen an id in a url like this in a website that is concerned with security. So, I agree we can still use the id and check if the user can show/see this id, but still the user can already do too much. Wouldn't it be better to hash the id, allowing us to generate a new encrypted ID using any available algorithm:

<?php
echo hash('md5', 'id_to_edit');
?>

What is the standard approach to secure an id in a url? In general, is it a good idea to display info like the id in a url?

Carlos Granados
  • 11,273
  • 1
  • 38
  • 44
Mick
  • 30,759
  • 16
  • 111
  • 130

8 Answers8

6

Special situations may call for special measures, but in a typical situation, all that is necessary is:

  • Use SSL so that sessions can't be hijacked by eavesdroppers
  • Check the user's permissions before doing anything.

Plenty of sites do it similar to the way you described initially. For example, WordPress has URLs like https://example.com/wp-admin/post.php?post=112&action=edit. Clearly, a curious user could choose to edit the post=112 part.

So, one standard you might consider is: "Do I need to be more concerned about security and privacy than WordPress?"

If, for example, you don't want people looking at log files to know what IP addresses are editing what posts, you have a few options. Each approach has trade-offs so what the best one is will depend on what your biggest concerns are.

For example:

  • You might use a hash to conceal the post id number, like you suggest in your update to your question.
  • Or you might just send that info via a POST method (instead of GET) over SSL and not include it in your URL at all.

One advantage of the first approach is that people can use bookmarks to get back to the page. You might not want that. Or you might. Depends on your app.

One advantage of the second approach is that (for example) Google Analytics won't reveal if one post id is being accessed/edited over and over again or if many post ids are being accessed/edited. This may matter to you depending on whether such information might tell someone something and who has access to your Google Analytics stuff. Or it might not matter at all.

There are a lot of other possible considerations too, such as performance.

By the way, if you do use MD5, be sure to include something in the input that an attacker will not know. Otherwise, it will be trivial for an attacker to reverse a discovered hash via a lookup table and generate further legitimate hashes for sequential post ids. In PHP, you'd want to do something like:

hash('md5', $some_hard_to_guess_secret_string . $data_you_wish_to_hash);

There is no single best practice that applies to every situation. But in a typical situation, it is not necessary to hash the post id value or even send it through POST. In a typical situation, be sure to use SSL (so that sessions can't be hijacked) and check user permissions before doing anything and you are likely good to go.

Trott
  • 66,479
  • 23
  • 173
  • 212
  • +65 for this fantastic reply. I really feel like this bounty was necessary. It helped me get essential things about security. Thanks Trott :-) – Mick Jul 26 '12 at 04:32
  • The example of using a common salt for all users is dated and bad. You should generate a random salt for each user and store it with the hash(password+salt). See the excellent answer to http://stackoverflow.com/questions/2583203/salt-passwords-and-security for an explanation. – walrii Jul 26 '12 at 05:39
  • @walril That is true for passwords. It is not necessarily true for ids that are not associated with any particular user. You shouldn't use MD5 for passwords anyway; passwords should be hashed with something more resource intensive to make brute force attacks more difficult. – Trott Jul 26 '12 at 05:42
  • @walrii The salting stuff is an aside anyway, so I've removed the hardcoded string, replacing it with a variable, but no details about salt generation etc. Thanks. – Trott Jul 26 '12 at 05:52
4

You must treat all data coming from the client as suspect. This includes the URL. You should check that this client is indeed authenticated and that he is authorized to perform whatever action is indicated (by the URL, post data, etc). This is true even if you are only displaying data, not changing it.

It is not important if the record id is easily seen or modifiable in the URL. What matters is what can be done with it. Unless the id itself imparts some information (which would be surprising), there is no need hide it or obfuscate it. Just make sure you only respond to authenticated and authorized requests.

walrii
  • 3,472
  • 2
  • 28
  • 47
3
  1. check permissions
  2. don't use GET values for validation, authentication, authorization. session, post variables are ok.
  3. to make things interesting... $x =md5(random number + post_id + userid) send all the values seperately like /edit/3?id=$x&y=rand_number when you get back to the edit page you check everything. else throw them an exception. few more ideas involve db but if you are interested.
j0k
  • 22,600
  • 28
  • 79
  • 90
2

That's standard approach. You should alwasy check permissions on both: showing form and on action after submiting the form.

Jerzy Zawadzki
  • 1,975
  • 13
  • 15
2

Regardless if you hash the ID or not, you must check permissions when editing a post, or someone could potentially stumble upon a page they are not supposed to be able to edit and they could cause serious damage. This could either be through randomly guessing, or through browsing through the history of another user that used your app.

Check permission before allowing someone to edit something.

That isn't to say you can't hash your IDs so they aren't quite as linear, but take a look at popular applications such as Wordpress, or even Stack Overflow. They are all based on incrementing numbers because regardless of knowing the ID or not, if you don't have permission, you can't edit it.

Andrew M
  • 4,208
  • 11
  • 42
  • 67
1

Obfuscating IDs will not increase security. As previously mentioned - you should always check permissions.

The reason why you might have an impression that you haven't seen url like this in a website that is concerned with security is because some of those websites are usually running on something like Java or .Net, and are using GUIDs ( http://en.wikipedia.org/wiki/Globally_unique_identifier ). Some of them however are using sequential IDs (e.g. gmail is using sequential IDs for emails).

MD5'ing is not a good idea. Cracking it is really easy, especially if it's something like md5(5684). I've looked up couple of hashes of numbers <100.000 here http://md5.noisette.ch/index.php and it found every single of them.

valentinas
  • 4,277
  • 1
  • 20
  • 27
1

It can be better to use ACL for that. You can configure your application to deny everything and use ACL to give an access to the specific object.

It's a common practice not to use any hashes instead of ids in URL. Clean id allows you to grep apache logs, application logs with simple command. All logic must be in the code to give or deny access to the specific domain entity.

lisachenko
  • 5,952
  • 3
  • 31
  • 51
0

How much more secure do you need to be than checking if the user that's already confirmed who they are (logged in) has permission to edit the post in question? If you simply had a hashed value displayed in the address bar it would still be relatively easy to find the hashing algorithm and then they could still have control over what post they're trying to edit. Security through obscurity will always be a false sense of security.

Nick Savage
  • 856
  • 1
  • 7
  • 18