oss-sec mailing list archives
Re: Randomness Attacks Against PHP Applications
From: Solar Designer <solar () openwall com>
Date: Tue, 5 Nov 2013 01:32:38 +0400
Hi George and all, It's been a year, and I happened to implement some enhancements to php_mt_seed last month. Although oss-security is not meant to be a place to announce new versions of security tools, I think having this one posting added to the existing thread is appropriate. php_mt_seed is now beyond PoC, and it has a homepage at: http://www.openwall.com/php_mt_seed/ Please see below for some detail on what has changed:
On Sun, Sep 23, 2012 at 1:14 AM, Solar Designer <solar () openwall com> wrote:The way I'd approach this is by limiting the set of possible seeds based on the first mt_rand() output (perhaps with a min-max range, so _many_ seeds will be potentially valid - could be millions, yet significantly fewer than the full 4 billion set). This can be accomplished almost as quickly as cracking the seed based on an exact mt_rand() output (full 31 bits of it, no min-max range) - that is, in one minute on CPU. Then slower, but more generic code may be used to filter out the impossible seeds based on further mt_rand() outputs, until there's just one seed value left. The slowness of that second cracker would not matter much because it'd only need to search a much smaller seed space.
I've implemented this without having to store the subset of seeds matching the first mt_rand() output. The extra checks are performed by the same thread that finds the first output match, with the seed still in a local variable (perhaps still in a CPU register, even).
A limitation, though, is that the very first mt_rand() output after seeding must be among those available, even if in truncated form. If it is not, then more of the state has to be maintained in the initial cracking pass, thereby making it slightly slower. When the first output is (at least partially) available, we only need 3 state elements, so they're kept in registers nicely.
I was wrong to say that more state "has to" be maintained. In cases like this, it's either storage/retrieval or recomputation. For the current implementation, I chose the latter. Current php_mt_seed recomputes just the required portions of MT's state if and when the extra comparisons are invoked. So current php_mt_seed is able to find seeds based on one or many, initial or not, and exact or not mt_rand() outputs. Some examples of this are given here: http://www.openwall.com/lists/announce/2013/11/04/1 http://www.openwall.com/php_mt_seed/README http://forum.insidepro.com/viewtopic.php?t=22342 I've also added AVX2 and MIC (Xeon Phi) intrinsics. In basic invocation mode (that is, given one full and exact mt_rand() output value), php_mt_seed 3.2 searches the full 32-bit seeds space on a Core i7-4770K at stock clocks in 48 seconds, and on a Xeon Phi 5110P in 7 seconds. In advanced invocation modes, these are slightly higher - e.g., 51 seconds and 11 seconds, respectively, for the sample set of mt_rand(0, 61) outputs given by the InsidePro forum's user. On Thu, Sep 27, 2012 at 10:42:24PM -0400, George Argyros wrote:
This sounds like a good approach and it would probably be faster when even truncated outputs are available. The problem is that we encountered quite a few applications with a pattern of generating tokens like md5(mt_rand()), and in general we found all kinds of weird ways to generate tokens that a random developer came up with. In the md5 case you won't be able to get the output of mt_rand unless you bruteforce the md5 in the same fashion (which would still be faster using code like the one you wrote, than using our approach, however you will need to write some application specific code for cracking and thats what we wanted to avoid).
Well, yes, in your example the md5() currently would not fit into php_mt_seed's standard code and invocation modes - however, it is fairly easy to hack into the source.
Our goal was to provide a usable interface so that people will only have to deal with the application specific part of the attack, rather than getting the cracking done correctly. Nevertheless, I think that applications that leak an mt_rand output are common out there and in that case your cracker is a simpler and faster choice since it does not require the user to write any C code at all. For cases when more complex token generation algorithms are used I think that an approach that takes care of all the cracking like the one we used may be better. Also in case you use the option to generate some rainbow tables (which may take some time too, depending on the "hash" function used), the online search time will be a few seconds. Another option could be to combine these two approaches and further optimize the code that handles the cracking while also providing a basic optimized version of mt_rand like the one you wrote to use when writing other more complex "hash" functions.
I'm not familiar with your approach. With current php_mt_seed, the extra md5() or whatever would need to be hacked into the diff() function, and the MATCH_PURE flag would need to be reset. I don't see how it can get much easier than that - well, short of providing ready to use primitives implementing common PHP functions such as md5(). Finally, to make this posting more appropriate for oss-security: it appears that Drupal and WordPress need to have their random password generation fixed: https://twitter.com/solardiz/status/397380784128270336 https://api.drupal.org/api/drupal/core!modules!user!user.module/function/user_password/8 http://core.trac.wordpress.org/ticket/25816 Alexander
Current thread:
- Re: Randomness Attacks Against PHP Applications Solar Designer (Nov 04)