August 31, 2020
Hi there,

As always when I make an appearance it's that something has gone wrong. Either in a popular library or D itself... This time it's a little bit of both.

There are many projects out there that use UUIDs to generate secrets such as session tokens and password recovery tokens. Other projects use it to protect against things like symlink attacks by generating temporary file names, or reduce the risk of IDOR by generating user IDs etc.

The issue is, they shouldn't use Phobos' randomUUID() for that. The Phobos implementation of UUID4 doesn't use cryptographic randomness which leads to predictable UUIDs, putting all these projects at risk.

Now, the question is: who's at fault? Is it Phobos? The RFC doesn't enforce the use of cryptographic randomness and the library doesn't claim that these UUIDs are suitable for secret generation. Is it the developers then? Every other language that I can think of uses cryptographic randomness for UUID4 because this kind of use is very common, so I think it is normal for developers to expect it to work similarly in D.

I personally think that Phobos must be changed. We can nag projects all day long, but any new developer will come and fall into the same trap. Furthermore I have thought for a long time that Phobos needs to provide a standard interface to the system's CSPRNG (CryptGenRandom on Windows, getrandom() or /dev/urandom on Linux, /dev/random on Unix). This is a component that does not involve the difficulty of cryptographic code (since you're not recoding anything) and is absolutely critical to so many operations that are very common at the age of secure communications. People use the path of least resistance and at the moment it is incredibly harder to use secure randomness compared to reaching for std.random.uniform(). Clearly randomUUID itself fell into this case.

Then again some might argue that developers should read the RFC of anything they use and, well, as much as I disagree, the RFC is the RFC, wrong as it may be.

I obviously can't solve that conundrum on my own and there are far too many projects impacted for me to take the time and reach them all, so I've written an article showing how to predict Phobos UUIDs in practice. I hope this shows that this is a very practical and important issue that must be dealt with, and the best way for that would be to generate cryptographically secure UUIDs in Phobos.

https://breakpoint.purrfect.fr/article/cracking_phobos_uuid.html

tl;dr: At the moment predicting a future UUID takes only a few thousand requests. It's nothing when it comes to things like trying session cookies or password recovery tokens. If you are a project manager, check whether you use randomUUID to generate secrets and replace it by cryptographically secure UUID.

Even if you don't care about the details of the attack, there's a section at the end of the article that details how to fix the issue and (maybe more importantly) how *not* to fix the issue.

Enjoy your day!