[paramiko] paramiko random number regression: Stop using RandomPool!
Dwayne Litzenberger
dwayne at oscl.ca
Thu Apr 3 15:12:23 PDT 2008
Robey,
I have always been impressed by the good judgement expressed in Paramiko's
design. Among other things, you have taken a secure-by-default approach, and
you have not resorted to bug-prone string manipulations in C in the name of
"performance". That being said...
Revision #486 [1] (and therefore Paramiko 1.7.3) re-introduces the problems
associated with PyCrypto's RandomPool class that I described in my post back
in January. RandomPool is not a simple "get random bits" primitive, but
paramiko is again using it as one.
Please take some time to re-read my post:
http://www.lag.net/pipermail/paramiko/2008-January/000599.html
Please also read at least the "Introduction and Overview" section of BCP 106
("Randomness Requirements for Security", currently RFC 4086), if you haven't
already done so: http://tools.ietf.org/html/bcp106.html
RandomPool is a deterministic PRNG. It is based on the PGP random number
generator, which was designed in an era when commonly-used operating systems
(e.g. MS DOS) didn't necessarily provide good sources of entropy. RandomPool
assumes that its caller/subclass will seed it regularly with entropy collected
elsewhere (e.g. from keyboard timings, like KeyboardRandomPool does). It also
_tries_ to seed itself from the operating system, just to make things a bit
better, if possible, but if it fails to get much entropy on its own, it
silently continues as if everything is OK.
Paramiko just instantiates RandomPool and continues as if RandomPool were a
maintenance-free "get entropy" primitive. To make matters worse, it does not
even do so in a thread-safe way.
Today, OS-provided entropy sources are common. The operating system is in a
better position to prevent disclosure of the RNG state, and it can guarantee
that the RNG state won't be duplicated when you create new threads/processes.
For this and other reasons, I deliberately removed RandomPool (which runs in
user-space) in my patches to fix CVE-2008-0299.
Paramiko should refuse to run if it cannot find an entropy source provided by
the operating system. I understand that this means that some existing
paramiko deployments will break, but that is only because they were insecure
in the first place. It is always better for a cryptographic module to return
an error than for it to silently run insecurely.
This is a very serious bug for Windows users of Paramiko. As I mentioned in
my January post, there is a longstanding bug in PyCrypto that causes the
native "winrandom" module to not be built. As a result, the only way to get
entropy from Windows is to use the os.urandom module (provided in Python 2.4
and later). Unfortunately, when you merged my changes, you removed the call
to os.urandom. This error would normally have been detected on systems
lacking a winrandom module (i.e. all of them), but since you replaced the call
to os.urandom with the instantiation of RandomPool, Paramiko's random number
generator simply fails silently.
The result is that Paramiko 1.7.3 is totally insecure on Windows, no matter
what version of Python is being used. On other operating systems, there is
still the RandomPool threading issue.
I will be posting a patch shortly.
Regards
- Dwayne
[1] bzr revision-id:robey at lag.net-20080324065139-nmvo5goh1izbd3gr
--
Dwayne Litzenberger, B.A.Sc.
Information Technology Analyst
Open Systems Canada Limited
#210 - 2332 11th Ave
Regina, SK S4P0K1
Office: (306) 359-OSCL (6725)
http://www.oscl.ca/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part.
Url : http://www.lag.net/pipermail/paramiko/attachments/20080403/c09daa67/attachment.pgp
More information about the paramiko
mailing list