-
Notifications
You must be signed in to change notification settings - Fork 145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
openssl_random_pseudo_bytes() does not appear to cryptographically secure #5
Comments
Where does it make that claim? You pass a variable (by reference) to the second argument of This does sound like a bug that the PHP team should be made aware of. So far,
If all 4 fail, it will throw an exception which should hopefully kill the script that invoked it. Would you be more comfortable if |
You're right, I misread the docs there. I edited my comment. I'm no security researcher, but it seems to me that openssl_random_pseudo_bytes() shouldn't be used to all if the goal is to always return a cryptographically secure result. Simply moving it to the bottom of the list would mean it could still be used in some cases, which would violate that goal. Anyway, I entered a bug with the PHP team: https://bugs.php.net/bug.php?id=70014 We'll see what they have to say. Maybe they know something about RAND_pseudo_bytes() that I don't. |
It must be marked as a security bug, so the public cannot see its contents. Please let us know what they say. |
Demoting it means, if run on a Linux system where If you don't have mcrypt (which invokes Windows' |
Shouldn't a version check be added before using openssl_random_bytes? And it has been fixed in 5.6.10, but any other version might still be insecure and thus the argument by @MasonM still seems to apply. |
More importantly: |
Doesn't it make more sense to just completely remove it then? -- edit: or at the very least reopen this issue? |
https://docs.google.com/spreadsheets/d/1Y74jasbZgLtgYcNhQG63yf5sam4eEaXMYDPgy11HFoo/edit#gid=0 Imagine this matrix without the openssl column. |
I did, it is one of the reason I self-host ;-) It would be possible to require some constant to be set (not ideal), before using openSSL, that way users of this library can choose whether they want possibly insecure behavior. This project is supposed to be a "secure backport", not a "secure in almost all cases but maybe not in some backport" right? |
While libmcrypt is very scary, I tried using CAPICOM.Utilities GetRandom() years ago and gave up. I can't remember clearly why but my unclear memory is
|
What worries me most is those run-time environments in which PHP is so tightly sandboxed/jailed that nothing can access the proper system RNG. In this case OpenSSL is the only thing that will return a value but, at the same time, it won't be properly seeded because it too cannot read from the system RNG. In this situation, OpenSSL might be adequate for some purposes (e.g. some uses of salts, email confirmation lookup keys, maybe even Diceware) but I wouldn't trust it for keys or IVs or stuff like that. A lib that provides OpenSSL as a last resort in a situation like this needs somehow to educate the user. Imagine PHP apps out there in the cloud with access to PHP's OpenSSL API but no proper randomness. This is what we enable if we aren't careful. |
Right. That's part of ext/mcrypt not libmcrypt.
This is probably why people are getting colliding 128-bit UUIDs. The obvious solution is, "Just use PHP 7, it has a sane cross-platform and simple CSPRNG." But that defeats the purpose of a polyfill. Ultimately, there is very little we can do if someone falls back to OpenSSL. It's the absolute last possible option, and unlike |
Hypothetically, imagine Dropping the hypothetical, i.e. assuming One last point, why can't the |
Concerning the worry of breaking BC by removing OpenSSL from random_compat, just think of it as rolling out a security patch. We are all familiar with the inconvenience of having to patch all our servers when a vulnerability is discovered. It's not necessarily a bad thing to force people into either fixing their runtime environment or else catch an Exception or silence an error. |
Re: BC -- we just have to increment the minor version and call it |
I'm going to mark this as closed again. The only systems that will use OpenSSL meet all of these conditions:
In this setup, should OpenSSL fail us, there's nothing we can do from PHP to secure it. |
I agree completely with your analysis but not the conclusion. I think putting OpenSSL behind the I say it is ethically dubious for two reasons. First there is the general feeling of mistrust towards OpenSSL I get from the various footguns its API provides and the history of injuries to feet that have been documented, at least one of which is referenced above. Evidently I'm not alone in having this concern. But more importantly, under the conditions you set out in those three bullets, the only conditions in which random_compat uses OpenSSL, there is cause to ask if its RNG is properly seeded. But random_compat has no way to answer that at runtime. The history of randomness failures in cryptography demonstrates the importance and sensitivity of RNG seeding. Hence I believe that if there's any doubt over an RNG's seeding then is not OK to say it is suitable for use within cryptographic contexts. The wasted opportunity is simply that random_compat could alert the user whose PHP system is not suitable for general cryptography when she tries out the package. The exception's documentation would educate the user on the nature of the problem and the options to solve it. One option might be a way to quiet the exception and use OpenSSL, a decision an educated user might reasonably make but not one random_compat can make in good conscience a priori. |
The problem is that users on insecure platforms are more likely to go, "Oh, random_compat doesn't work. I'll just use |
To be honest, you could end that sentence with "... I'll just use Maybe there is some middle-ground however ... I like the suggestion to optionally plug-in OpenSSL, it being the user's choice. That's tricky to do because it's a polyfill and not our own API design, but not impossible. |
Well, can we really protect against outright stupidity? It would be viable to have the user define a global constant as I suggested. the naming of that constant would then give the developer some hints about what he's doing. const I_DO_NOT_CARE_ABOUT_SECURITY = true; Would serve nicely, and seems unlikely to collide with any other global constant. Other options include: I'm sure we can come up with some more ;-) |
No. :P |
Something like this? if (!defined('RANDOM_COMPAT_USE_OPENSSL')) {
define('RANDOM_COMPAT_USE_OPENSSL', false);
}
// ...
} elseif (RANDOM_COMPAT_USE_OPENSSL && extension_loaded('openssl') && PHP_VERSION_ID >= 50300) { |
Even if that were true, it's a better outcome, in my opinion, than providing them a |
Yes. But neither we nor random_compat can decide if it is good enough for the application. |
While my previous suggestions where obviously (partially) jokes, I would prefer at least the word UNSECURE in the constant; that way it is actually obvious that it is not secure at all. |
I disagree. Educating the user is what I proposed. If I didn't think education had any practical value, I wouldn't have proposed it. |
Problem: We don't specifically know that it's "not secure at all". Even before bug 70014 was fixed, it's indeterminable if the RNG was seeded or not from PHP. Is its reputation dodgey? Yes. Is it a userspace CSPRNG which is generally a bad idea? Yes. But does it provide adequate randomness for PHP developers? I don't know. But I can't say "no" for certain. |
@tom-- I was referring to the people that refuse to read the error message you propose and are in this category:
I am in favor of exception if the constant is not set (education) and otherwise accepting that if they refuse to be educated and set the appropriate constant using insecure openSSL. |
I wasn't suggesting otherwise. In fact, if we go for using a constant to enable OpenSSL, I'd prefer to keep it undocumented. ;) |
Just so we're clear: If we do disable or remove OpenSSL, it won't be in 1.0.6. Ping @ircmaxell |
@paragonie-scott We can go for POSSIBLY_INSECURE? I mean it is not about being right as much as it is about being safe in my opinion. |
That looks fine. There are various possibilities. For me the more important thing is the exception and its documentation, which could say something to the effect that if you don't need a trustworthy CSPRNG, I volunteer to author a docblock for the exception if you like. |
I've reopened #51 if you want to discuss it there, and reference it in any PRs. |
OK. I'll make a proposal via PR. |
That's fine. |
Although the PHP docs claim that openssl_random_pseudo_bytes() returns a "cryptographically strong" result as long as the
$crypto_strong
parameter is true, I checked the source and that does not appear to be the case. The openssl_random_pseudo_bytes() PHP function calls the RAND_psuedo_bytes() OpenSSL function, which the OpenSSL docs say should only be used for non-cryptographic purposes:It's quite possible I'm missing something here. If so, I apologize for wasting your time.
The text was updated successfully, but these errors were encountered: