This is arguably bad design, but one can understand where the design came from.
It is arguably bad design, because it relies upon api.wordpress.org
to generate random keys and keep them secret. If api.wordpress.org
gets compromised, then the attackers could arrange to record the keys that are used by new Wordpress installations. That would be problematic.
(Yes, Wordpress could send you backdoored source code, but that would be detectable in principle by anyone who examines the source code -- as you have done. In contrast, if api.wordpress.org
is secretly recording a copy of the keys it sends to new Wordpress installations, that is not detectable by any amount of source code inspection or any other mechanism available to interested third parties.)
It is understandable, because it is hard to generate crypto-quality randomness in a platform-independent way.
It's still arguably a bit sloppy/lazy. Arguably, a better design would have been to gather some local randomness (if possible), gather some randomness from api.wordpress.org
, and then mix the two securely using a cryptographic hash function. That way, you'll be secure as long as either of those two values is good. A compromise of api.wordpress.org
would not endanger Wordpress installations running on any platform where the code was able to gather some local randomness; it would only endanger the small minority of installations that were unable to get good randomness.
How can one generate good crypto-quality randomness, from local sources? There are various ways:
Read 16 bytes from /dev/urandom
, if it exists.
Call openssl_random_pseudo_bytes()
, which invokes OpenSSL to get crypto-quality pseudorandom bits.
Call mcrypt_create_iv()
, with the MCRYPT_DEV_URANDOM
flag.
Of course, one can try all available options and mix together everything you get. As long as at least one of these options work, you'll be good. And of course, if you mix this together with output from api.wordpress.org
using a cryptographic function, it'll never be any worse than today's approach, and will be better if api.wordpress.org
ever gets compromised.
So, combining local and remote randomness would have been a better approach. Unfortunately, that does require a bit more work and a bit more code. Perhaps the developers took the easier approach of just querying api.wordpress.org
. One could debate that design decision, but you can understand how this approach might have been chosen.
Overall, though, as Thomas Pornin argues, this is probably not the biggest security risk with Wordpress. We're talking about software with a long history of security vulnerabilities. So, the incremental risk added by this aspect of their random-number generation might be small, compared to the risk you're already taking either way.
See also Secure random number generation in PHP for more on generating crypto-quality random numbers from PHP, and Would it be secure to use random numbers from random.org in a cryptographic solution? for more on why it is not a great idea to rely upon a remote source of random numbers for your crypto keys.