0

ULID is a specification for unique identifiers which is intended as an alternative to traditional UUID. Some of the major differences are:

  • The creation date of the identifier is encoded into part of the identifier.
  • Because of the above, the identifiers are lexicographically sortable. That is to say that if you create two identifiers, the second one will always be "greater than" the first if they were created in different milliseconds (there is support for making identifiers created in the same millisecond also sortable but I'm not worrying about that).
  • Its identifiers use ten fewer characters than UUID while avoiding ambiguous characters like "letter O" and "number 0", "letter I" and "number 1," etc.

I have been using it for a web storefront side project that may never see the light of day, but in case it does somehow I'm wondering about what the security implications of basically including the same value that would be in the "created" column of a database row in every unique identifier I might share with a user would be.

For example:

  • User IDs. Anyone who comes across the unique user ID for any user on my site will be able to see when the user created their account on my site. I think this is the biggest "problem" but on the other hand I can't really visualize in what circumstances it would actually be a problem, assuming Alice somehow had the ULID of Bob's account and nothing else.
  • Order/purchase IDs. Anyone who gets an order ID will be able to see when that purchase was made. I think in most cases that ID will be displayed right next to a date anyway, though (for example, in "receipts" emailed to users after they make a purchase).
  • Item IDs. Anyone who can access an item ID can see when that item was added to the site. Again, I can't visualize when this would be a problem.

I feel like the "correct" answer from a purely security-oriented approach is that we should be exposing as little information as necessary and so that would mean using random UUIDs for all of these things. But from a practical approach I'm wondering if I'm overthinking things and that exposing these dates in most cases won't be the problem that I'm thinking they might be.

Should I avoid using ULID for a project like this?

1
  • "Should I avoid using ULID for a project like this?" - security is a always a trade-off. So I would reverse the question: what are the advantages of using ULID instead of UUID for your project? And then you can decide if these advantages outweigh the disadvantages you've mentioned. And how much of a problem these "information leaks" really depend on context you don't provide, i.e. creation date might not be a problem on a site selling gummy bears but law enforcement might be interested in this value on a site selling illegal drugs. Commented Feb 28 at 6:26

1 Answer 1

1

ULIDs are sometimes sequential, and this can have security impact.

Normally, ULIDs consist of a timestamp and a random part. However, when two ULIDs are generated within the same millisecond, the "random" part is simply incremented by one, and is thus not very random. The ULID spec says:

if the same millisecond is detected, the random component is incremented by 1 bit in the least significant bit position (with carrying).

// Assume that these calls occur within the same millisecond
ulid() // 01BX5ZZKBKACTAV9WEVGEMMVRY 
ulid() // 01BX5ZZKBKACTAV9WEVGEMMVRZ 

If an attacker creates two objects within the same millisecond, they can derive the ID of the second object from the first.

For example, consider using ULIDs as password reset token. The attacker simultaneously requests a password reset for his own account and for the victim's account. They increment their own password reset token by one to obtain the victim's password reset token, and can take over their account.

This is a bit of an extreme example, but I think it is a real flaw in ULIDs that they are not always random.

1
  • But in reality I wouldn't use ULIDs (or UUIDS) for password resets, instead using a long fully-random string, right? Commented Feb 28 at 18:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .