[Esapi-user] ESAPI Random Number Generation Broken

Kevin W. Wall kevin.w.wall at gmail.com
Thu Jun 26 04:39:52 UTC 2014

On Wed, Jun 25, 2014 at 9:57 AM, Jim Manico <jim.manico at owasp.org> wrote:
> PS: Java 8 improves upon this and provides a new API:
> http://docs.oracle.com/javase/8/docs/api/java/security/SecureRandom.html#getInstanceStrong--
> which is what we should be using for " high-value/long-lived secrets like
> RSA public/private keys". But even then, using the same instance without
> reseeding with lead to a PRNG, not a CRNG sequence.

That's all well and good, but even with JDK 7 and earlier, SecureRandom
*is* a CSRNG. (Note that a CSRNG *is* a PRNG.)  The problems with
SecureRandom very early own is that they just punted on the initial
pseudo-random seed. Before JDK 1.4 (I think that's where it was changed),
the first time they set the seed, they did some black magic like mixing
together a few bits from the current time in milliseconds, the current
amount of total and available memory in the Java heap, and added in how
many times a thread could yield in 3 seconds.  Near boot time, all those
things were very predictable. In 1.4 (maybe 1.3), it was changed to initialize
the seed /dev/urandom if it was available and if not, I think it reverted
to some other song and dance.  There is problems however with /dev/urandom
shortly after boot time (and ESPECIALLY shortly after the *initial* system
boot). Using /dev/random would be better, but unfortunately that will
block. (Aside: At my previous job, we wrote an EntropyPool to seed things
like SecureRandom that would read from /dev/random by default or alternately
/dev/urandom. There was a warning in the Javadoc if would block and to use
the weaker entropy setting if that was a concern. It was never a problem
until one time when an application had a new release and they started
requesting [for some unknown reason] about 10k worth of data from this
EntropyPool all at once. And it was in an /etc/init.d script that started
their application in WebLogic Server. Result was they had a 20+ minute
startup delay until 10k bytes could be collected from /dev/random. They
called me in the middle of the night to 'yell' at me. I nicely told them
to RTFM. Sigh.)

Anyway, my guess is that getInstanceStrong() method will allow you to
specify things like "use /dev/random".  However, I agree with
Thomas Ptacek's comment that if it really matters use an Operating
System-level CSRNG and not a userspace CSRNG. There are of course
reasons why you might not want to. Always using /dev/urandom is
a reasonable compromise, but there are still edge cases where you
can get burned by using /dev/urandom rather than /dev/random. But
unless you are protecting nuclear launch codes (and seriously, you
BETTER not be doing that with Java since you can't guarentee that you
clear memory), /dev/urandom will probably suffice.

Also, one thing that I picked up on the Cigital blog post
was that an attacker could potentially hide a call like this

    System.setProperty("securerandom.source", "/dev/zero");

in some 3rd party library that you are using and then your are toast.
Of course, the same is true if you don't specify that you want the Sun
provider as in:

    SecureRandom csrng = SecureRandom.getInstance("SHA1PRNG", "SUN");

as someone could dynamically insert their own tainted provider for
SecureRandom into a 3rd party library you are using and again you
are screwed. (Unless of course you are using a Java SecurityManager
and an appropriately locked-down security policy which I am sure
that you *all* are doing, right. Cough, cough.)

Anyhow, we need to do something about those two things in ESAPI...
especially the first since it would be really subtle. Anyone care to write
up a Google issue to that effect to remind me?

Blog: http://off-the-wall-security.blogspot.com/
NSA: All your crypto bit are belong to us.

More information about the Esapi-user mailing list