Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SECURITY: Secure id in a url

Tags:

php

symfony

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?

like image 876
Mick Avatar asked Dec 04 '22 02:12

Mick


2 Answers

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.

like image 127
Trott Avatar answered Jan 08 '23 11:01

Trott


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.

like image 25
walrii Avatar answered Jan 08 '23 12:01

walrii