0

If I display user_id that represents each unique user in the db as an atrribute in an HTML element, is that good practice? Because I need the reference to the user if I want to perform an action on that particular user such as adding him to be my friend.

Example in HTML:

<div data-user-id='12' onclick=addFriend(12)>
    Click to add John as your friend
</div>

The 12 represents the user's actual user id from the db. So is it safe from a security perspective to do this?

16
  • Depends entirely on what knowing that ID gives me access to. Nov 8, 2018 at 10:19
  • 8
    Please, define what you mean by "safe"? Safe from what? Safe against whom? What are you protecting? Whom are you protecting it from? Or what are you protecting it from? Nov 8, 2018 at 10:22
  • If you use that ID in links to tell the server which user is requesting that data, then I can very easily modify that ID and thus access other people's data.If you then have users from the EU, you immediately fall foul of GDPR rules and could have legal action taken against you as a result. Use sessions, GUIDs and cookies instead. If they aren't used for links, why have them in the HTML in the first place?
    – David Arno
    Nov 8, 2018 at 10:43
  • 1
    I believe this can be a good, answerable question, but we need more information about what this Id identifies and how it is being displayed or used in HTML. Nov 8, 2018 at 12:51
  • 1
    Added the HTML example back. Might be a good idea to refresh the page before making any more edits. Nov 8, 2018 at 13:16

3 Answers 3

2

Centuries ago it was believed that the name has some arcane power over the named. Parents would give their children a secret middle name so that their commonly used names will be partial, and evil mages won't be able to easily know their full names and use it in spells.

Those of us that live in the age of modern science know that this is nonsense. Even if you know my full name you won't be able to cast a leprosy curse on me. At most, you'll be able to look me up in Google and find some public information about me. There is no real risk here - the risk is so low that my parents didn't feel the need to give me a secret middle name and that I don't mind name appearing in the bottom right corner of this answer.

Are the IDs in your page akin to the harmless modern names or to the mystical names of old? If I know your ID, do I have power over your account? Can I change your settings? Can I make posts on your behalf? Order products with your money? Access your smart home and change Alexa's mode to "killer AI"?

If security is important, you don't need to answer that question - you just need to make sure that the answer is NO. You mentioned the SQL database - but if I have access to your database I can just find user accounts by names, even if I don't know their IDs. One of the commenters (David Arno) mentioned changing the ID in a link - but the server should be checking the credentials anyway to determine if a query or operation is allowed. If the ID alone is enough for outsiders to attack - your security is already compromised.

Security should not be in the UI. It should be in the server. The only parts of security that have anything to do with the client's machine are the credentials mechanism to prevent impersonation and the encryption mechanism to prevent eavesdropping.

2

No, there is no inherent security flaw with putting the User Ids in HTML. After all, it's a web page. You need the web page to allow the user to add friends, and without some sort of identifying value, you cannot do this. You must provide the identifying value in the web page some place, whether it's in an onclick or data-x attribute or a hidden form field. This is simply how the World Wide Web works.

The security flaw could come in from the JavaScript code executed in the onclick event handler. If adding someone as a friend results in a GET request to the server, then someone just needs to post a web page on the internet with some <script> tags referencing your URL, and trick your registered users into visiting this page (which isn't a big deal if users are able post messages or comments and embed URLs in them).

<script src="https://example.com/friends/add/1"></script>

Let's pretend the URL https://example.com/friends/add/1 is how a friend is added to the current user's friend list, and it also responds to a GET request. A web page with the SCRIPT tag above in its HTML source will cause the browser to issue a GET request to that URL — even if it doesn't send back valid JavaScript! And since the current user is logged in, the browser happily sends their session cookie to the web server saying "hey, this person is logged in" and your web server is none the wiser.

If the user viewing this page is logged in to your site, boom. They have a new friend.

You can guard against this sort of attack by making sure any request to the server that modifies data requires a POST, PUT or DELETE request.

So the final answer is:

No, putting database Ids in HTML is not inherently dangerous. It's how those Ids are used that could be dangerous.

Identifying values are not a security risk unless they fall into these categories:

  • Tax information
  • Account information
  • Official government Ids of any sort

And make sure any request to the server that modifies data in any way requires a POST, PUT or DELETE request, and never a GET request.

1
  • Thank you Greg for your response. I see your point. Some developers said that it is not good to display ids in the html because it has vulnerabilities. Therefore they suggested to encrypt the ids on the backend before sending the ids over to the frontend (such as by using JWT, Base64 encoding, etc.). Then, they said to decode the string on the backend to get the id securely and do the logic from there. So now I am unsure which action is the best to take regarding this id in html matter. In terms of security and website performance, do you agree with them? Nov 10, 2018 at 7:17
1

Having the ID directly in the HTML is not inherently insecure per se.

However, I would worry about this: You seem to be using consecutive ids (Given that the example Id is a low number, I would guess it is an autoincrement or set by a trigger). This constitudes a user enumeration vulnerability.

Please use random ids or a reasonable length, doing so would mitigate the risk of a malicius user to guess Ids of users.

A malicious user can write a script that iterates over the ids and adds everybody as friend. Even if everbybody rejects (and I assure you, some won't, because there is people who accepts everybody), that script would annoy a lot of users, and add load to your servers.

This would be made worse the more functions the user can call with these ids (for example, this could reveal private or sensitive information about the user. Make sure to check who is requesting and whatever or not they have access to such information), and even worse if there is an SQL Injection vulnerability (the fact that you mention a query in the comments makes me worry about this, please use prepared statements, thank you).


There is also a risk of cross-site attacks. Your function addFriend will have to ultimately translate to some request to the server, right? If there is chance to mimic that request (cross-site request forgery) or call the function (cross-site scripting), a malicious user could send a link to the victim that when open - while the victim has an open session on your site - would result in a third party added as friend.

There are plenty of things to do to mitigate cross-site attacks. Please refer to Owasp articles on Cross-Site Requst Forgery and Cross-Site Scripting.

You will find that one thing you can do is generate codes that mean "Add X as Friend" that are single use and tied to the session of the user. This would mean that no script or request forgery will be able to add a friend for which the code has not been generated. And the same approach can be done for any other function or request that needs to be secured.

Other things you may consider: You may also "add a cooldown" to the operation, making sure that a function that calls them in rapid succesion does not work. In fact, executing one could invalidate and regenerate all other codes, making any script that reads them and use them way harded to implement (plus you would know who keeps doing it and yield a temporary ban).

Addendum: Use Captcha in conspicuous activity.

Note: Do not store these in the permanent database. Out of personal experience, that becomes a mess very quickly. Also do not tie them to the user, but to the session. In fact, using session variables (even if backed by a database) is a good approach.

However, instead of storing all the valid codes (and saving storage on the server), you can generate and store a criptographic key and use it to cipher codes that represent the operation. If you do this, invalidating the codes imply replacing the key with a new one.


See also: The Moonpig Bug: How 3,000,000 Customers' Details Were Exposed where Tom Scott explains a user enumeration vulnerability.

4
  • I see. Let's say that User 1 wants to add User 2 and this time I change the type of user_id from a numerical id to a UUID and I did not encrypt the UUID so the actual UUID is used. So is it still ok for me to store the UUID of users in the UI as a reference for certain actions performed on the particular user (such as adding as a friend, sending DMs, etc.)? Or is there a more secure way of doing this? I hope you get what I mean Nov 9, 2018 at 23:40
  • 1
    @RyanNewman even consecutive ids can be secure. As I said, it is not inherently insecure per se. Take for instance this very website, look at your profile... you see that number in the url? Yeah. It is not the only place where this site differs from best practices, however, it is not really a problem since there is no sensitive information there and other precautions are taken against bots and such. I would prefer the UUIDs, over consecutive ids, of course. You still need to make sure that the site is otherwise secure, make sure to validate who can do what.
    – Theraot
    Nov 10, 2018 at 0:14
  • I get your point. Some developers said that it is not good to display ids in the html because it has vulnerabilities. Therefore they suggested to encrypt the ids on the backend before sending the ids over to the frontend (such as by using JWT, Base64 encoding, etc.). Then, they said to decode the string on the backend to get the id securely and do the logic from there. So now I am unsure which action is the best to take regarding this id in html matter. In terms of security and website performance, do you agree with them? Nov 10, 2018 at 7:15
  • @RyanNewman Base64 is an encoding, but not cryptography (there is no secret). The users can just run them over any of the many free encoders/decoders on the web. So that alone won't do. JWT are good, and they have some cryptography (if you sign them), however that only protects the integrity of the data, not its confidenciality. If the goal is to keep id confidential those aren't the tools. You can use a session tied table with unique random aliases for each user. Generate and send as needed, recovering the id is just a query. Thus the id is never sent, and it is faster.
    – Theraot
    Nov 10, 2018 at 7:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.