Dice for various games, especially for rolepla...

The Zend Framework team recently released versions 2.0.8 and 2.1.4 to address a number of potential security issues including advisory ZF2013-02 “Potential Information Disclosure and Insufficient Entropy vulnerabilities in Zend\Math\Rand and Zend\Validate\Csrf Components”. Quite the mouthful!

In short, Zend Framework used the mt_rand() function to generate random numbers in situations where neither openssl_pseudo_random_bytes() nor mcrypt_create_iv() were available. This is possible when the openssl and mcrypt extensions are not installed/compiled with PHP. The mt_rand() function is a particularly weak Pseudorandom Number Generator (PRNG) selected for speed over security so it should never be used unless for obviously trivial use cases. Consider the following as food for thought:

if ($_GET['rand'] == mt_rand()) {
    exec($_GET['command']);
}

This example has two characteristics. It has nothing to do with cryptography and it gives attackers something interesting to work with if they can guess what mt_rand() will return. It demonstrates that the concept of reserving good random number generation solely for “cryptographic” purposes is entirely false and misleading. You should use good generators for all but the most trivial purposes. If guessing a random number or string leads to an unauthorised outcome, then using mt_rand() is a security vulnerability. This applies to a whole range of uses for random number generators: session IDs, API tokens, CSRF tokens, nonces and unique ids. These all rely on randomness as do core functions like uniqid() and array_rand(). What happens if they are predictable?

What makes mt_rand() and uniqid() such bad choices for anything when it comes to security? I wrote a new chapter for the slowly expanding security book I’m writing which you can read here online:

http://phpsecurity.readthedocs.org/en/latest/Insufficient-Entropy-For-Random-Values.html

The extremely short and sweet version is that all of PHP’s internally used and externally exposed PRNGs use seeds. Those seeds are based on limited information like current seconds, microseconds, and process PID. These values are not very uncertain and even partially predictable, i.e. they have “insufficient entropy”. If you use the same seed, those PRNGs output the exact same values every time. If you get a random value from a server, you can brute force it to get the seed used (e.g. use HTTP Date head to guess seconds and twinned requests to minimise microsecond deltas). Servers can output brute forcible random numbers either automatically (i.e. Session IDs) or by design (e.g. CSRF Tokens). Now an attacker can predict future values – for the same PHP process! Finally, there’s this thing called KeepAlive that lets an attacker reuse the same PHP process multiple times…and predict random values on future requests. For example, the token generated when resetting an account password that is appended to a secret reset password URL sent by email to the account owner whose account can inject unsanitised HTML into any part of a website.

In any case, take the time to read the longer book chapter ;) . It has a lot more practical information including a walkthrough of a theoretical attack and links to some tools publicly available for mounting proof of concept attacks. I also discuss solutions including Anthony Ferrara’s RandomLib.

Enhanced by Zemanta

Related posts:

  1. Mutation Testing Brain Dump
  2. Progress update on Zend_Service_Yadis
  3. Zend Framework Contributors Mailing-List Summary; Edition #2 (July 2011)
  4. Writing A Simple Twitter Client Using the PHP Zend Framework’s OAuth Library (Zend_Oauth)
  5. Do Cryptographic Signatures Beat SSL/TLS In OAuth 2.0?