2

I'm working on a website which necessitates the use of server generated codes, which are displayed once to the user and then stored in a database.

I plan on using /dev/urandom as a source of entropy to ensure that the pseudorandom codes are cryptographically secure, as it is crucial that future codes are not predictable.

But I am concerned that someone could repeatedly generate codes, drain the entropy pool, and thus be able to predict future codes. Will requiring the user to solve a CAPTCHA in order to generate a single code be sufficient to prevent this form of attack?

2 Answers 2

5

I'm not aware of any publicly known attack on predicting future output of /dev/urandom, no matter how much previous data you have already seen from it. It would be possible in theory, that such an attack exists, though. If such an attack exists, it will almost certainly require vast amounts of output in order to make a prediction. Probably much more data than an attacker would be able to extract without bringing down your server or network first.

There are a few other factors that work in your favor and against a hypothetical attacker.

Linux' entropy pool is fed by non-deterministic events such as the timing of network packets. In order to query your server, an attacker has to create network traffic. Since the traffic will go over multiple routers that are not under the control of the attacker, it seems highly unlikely that they will be able to predict the arrival times reliably. Therefore, the attack defeats itself by filling the entropy pool as it is trying to drain it.

Modern x86 CPUs have special instructions (RDRAND) to retrieve physical entropy at an extremely high rate. As the Intel documentation says,

The [all-digital Entropy Source] runs asynchronously on a self-timed circuit and uses thermal noise within the silicon to output a random stream of bits at the rate of 3 GHz.

While a fast CPU could consume random words at an even higher rate in which case the CPU would fall back to a partially deterministic generator, it is safe to assume that your application won't send out critical data at over 358 MiB/s (equivalent to 3 × 109 bits per second).

Linux' entropy pool mixes in the entropy obtained by RDRAND where it is available. This is done in a clever way such that even in the quite plausible purely conspiratorial case that Intel has put a backdoor into RDRAND on government request, it would be no worse than if the device were not used at all and probably still help somewhat.

In conclusion, I don't think that draining your entropy pool is something you should be concerned about too much at this point. If you still are, there are less obtrusive ways than having your users solve CAPTCHAs.

For one, you could artificially rate-limit your code generator. If you only allow, say, one code per second and IP, your service will still be fast enough for legitimate use but make extraction considerably harder.

In addition, note that /dev/random and /dev/urandom are not only readable but also writable. From the man page:

Writing to /dev/random or /dev/urandom will update the entropy pool with the data written, but this will not result in a higher entropy count. This means that it will impact the contents read from both files, but it will not make reads from /dev/random faster.

Hence, instead of showing the CAPTCHA to your users, you could write it to /dev/urandom. Of course, this only really makes sense if the CAPTCHA was generated on a different machine such as when using a service like reCAPTCHA. This advice is of course to be taken with a grain of salt. It would probably make more sense to update your entropy pool with data obtained from a service like RANDOM.ORG.

The thing you should be concerned about is that if your server was freshly booted, the internal entropy pool might not be filled yet. In this case, reading from /dev/urandom will provide poor entropy. One trick to avoid this is to have your application initially read a single byte from /dev/random which will block until the system has harvested some entropy. On systems that have RDRAND (assuming it is not backdoored), this startup issue will be benign as RDRAND needs no warm-up.

If you develop your application using a technology where you can make calls to C library functions, Linux 3.17 and later provides the getrandom syscall which should be preferred over reading from /dev/urandom as it also works if /dev/urandom is not available (for example, because your application is chroot()ed) and, more importantly, doesn't suffer from the startup issue that /dev/urandom has. (getrandom will block until the entropy pool is initially filled.)

A service like RANDOM.ORG can also be used to mitigate the low-entropy situation after startup but I would never depend on a third-party service directly for generating my random secrets. If you want to be safe, assume that everything you download is deterministic and known to an attacker. (In case that has not become clear yet, writing such data to /dev/urandom does no harm. It just doesn't do any good either.)

0

Personally I am not so concerned with /dev/urandom draining. Given a few bytes from a good source (packet timings or whatever your kernel uses), you can get exabytes in data by using a CSPRNG like /dev/urandom does.

If you are really concerned with draining the pool though, /dev/random will block if it judges entropy to be low.

A CAPTCHA would also work if you expect people to be trying to pull randomness out by the terabytes, but they're quite a pain for users. I'd only show one after an IP address (or a subnet for that matter) did a suspicious number of requests already.

You must log in to answer this question.