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.)