Security
Python's os.urandom() in the absence of entropy
Python applications, like those written in other languages, often need to obtain random data for purposes ranging from cryptographic key generation to initialization of scientific models. For years, the standard way of getting that data is via a call to os.urandom(), which is documented to "return a string of n random bytes suitable for cryptographic use." An enhancement in Python 3.5 caused a subtle change in how os.urandom() behaves on Linux systems, leading to some long, heated discussions about how randomness should be obtained in Python programs. When the dust settles, Python benevolent dictator for life (BDFL) Guido van Rossum will have the unenviable task of choosing between two competing proposals.
Blocking os.urandom()
Traditionally, os.urandom() has been implemented on Linux by opening /dev/urandom and reading the requested amount of data. This interface is non-blocking; it will not wait if the amount of entropy in the system's entropy pool is low. The implementation of /dev/urandom is such that the quality of the random data it returns will be high even if the entropy pool is depleted — with one possible exception. Immediately after the system boots, when the entropy pool will contain little or no entropy, /dev/urandom may return relatively predictable data. In most systems, this window of poor randomness is only open for a few seconds at most, but exceptions do exist.
In the Python 3.5.0 release, os.urandom() was changed to use the relatively new getrandom() system call on Linux. Unless it has been called with the GRND_NONBLOCK flag, getrandom() will wait, if need be, for the system entropy pool to be initialized. os.urandom() does not supply that flag, meaning that it can block if the entropy pool has not yet accumulated enough randomness. It seems like a relatively small change, with the prospect of being sure of living up to the "suitable for cryptographic use" promise in compensation. But one need only look at Python issue 26839 to see that the implications are not quite as simple as one would expect.
It turns out that, in some distribution configurations, Python scripts are run at the very beginning of the user-space bootstrap process. If the entropy pool is not yet ready, those scripts will block until entropy-pool initialization is complete. If there is nothing else going on, and especially if the system is booting as a virtualized guest, it may take a long time to accumulate enough entropy to proceed. In the incident that led to the bug report, the boot process simply hung for 90 seconds until systemd lost patience and killed the blocking process. That kind of behavior, created in the search for unpredictable random numbers, has quite predictable effects in the form of unhappy users.
From this sprung the bug-tracker entry referenced above, which turned into a fierce discussion on the wisdom of the API change and whether os.urandom() should return crypto-quality randomness at any cost. The discussion spilled over onto the python-dev list when 3.5 release manager Larry Hastings despaired of reaching any sort of consensus and asked Van Rossum to simply rule on the matter. The resulting thread led many participants to question whether they wanted to continue following the list at all but, in the end, it did come to some useful conclusions.
If one is doing cryptographically sensitive work early in the bootstrap process — generating an SSH host key, for example — then blocking the boot almost certainly makes sense. The consequences of the alternative — generating weak keys — can be severe. In this case, though, it turns out that such high-quality randomness was not needed. Nobody was generating keys; instead, Python was initializing its own internal random-number generator and setting up dictionary randomization to defend against hash-collision attacks. These internal calls were (inadvertently) changed when os.urandom() was changed, but there seems to be a rough consensus that they do not need blocking behavior.
So the proper fix for the observed boot hang is to do these internal initializations without blocking on the entropy pool. For Python 3.5, the os.urandom() change will also be partially reverted, in that the function will, once again, be non-blocking. It will call getrandom() with the GRND_NONBLOCK flag and, if that call fails, fall back to reading /dev/urandom as before. With these fixes in place, the blocking part of the change is effectively reverted and the immediate problem has been solved.
Blocking or exceptions?
That still leaves open the issue of how os.urandom() should behave; developers who are concerned about security are adamant that it should not return data when the entropy pool is not yet ready. So there is still pressure on Van Rossum (and the community as a whole) to specify blocking behavior starting with the upcoming 3.6 release. Python's benevolent dictator seems inclined to downplay the issue:
It became clear in the discussion, though, that opposition to returning questionable randomness from os.urandom() is strong. It seems likely that, in 3.6 and later releases, os.urandom() will no longer return data drawn from an uninitialized entropy pool. The question of how it will behave is, as yet, unresolved, though. In the end, Van Rossum asked the proponents of two different approaches to write up their ideas as Python enhancement proposals (PEPs); he will then choose between the two.
The first approach, favored by Victor
Stinner, is to simply make os.urandom() blocking and be done with it —
after ensuring that Python itself uses non-blocking behavior during its
initialization. Changing to blocking behavior is arguably an incompatible
change in a longstanding Python API but, as Stinner points out:
"First of all, no user complained yet that 'os.urandom()'
blocks. This point is currently theoretical.
" As long as the
problems with starting Python itself are resolved, the thinking goes, there
should not be problems for other users.
The alternative comes from Nick Coghlan. With this proposal, os.urandom() will raise a BlockingIOError exception if random data cannot be had without blocking. Adding a new exception to an established API has its own hazards; no existing code will be expecting that exception, so surprising explosions might result. But, for a problem that should only be possible during the bootstrap process, Coghlan believes that this is the best approach:
This proposal also envisions adding a function to the in-development "secrets" module — secrets.wait_for_system_rng() — that would simply block until the system's entropy pool is fully initialized and ready. The small (possibly nonexistent) body of code that breaks with unhandled BlockingIOError exceptions could call this function to ensure the availability of strong random data from os.urandom().
It is not clear when a decision between these two proposals will be made. It is worth noting, though, that Coghlan has indicated that he is happy enough with Stinner's proposal that he can support it should that be the one that is accepted in the end. So the discussion may have been long and painful, but the end result should be strong random data in Python in a way that the community as a whole is able to agree upon. Hopefully that means everybody can rest and prepare for the inevitable debate over whether this change should be backported to Python 2.
Brief items
Security quotes of the week
This attack was already understood as a theoretical problem for the Tor project, which had recently undertaken a rearchitecting of the hidden service system that would prevent it from taking place.
No one knows who is running the spying nodes: they could be run by criminals, governments, private suppliers of "infowar" weapons to governments, independent researchers, or other scholars (though scholarly research would not normally include attempts to hack the servers once they were discovered).
Targets are important in cryptography, and Google has turned New Hope into a good one. Consider this an opportunity to advance our cryptographic knowledge, not an offer of a more-secure encryption option. And this is the right time for this area of research, before quantum computers make discrete-logarithm and factoring algorithms obsolete.
New vulnerabilities
community-mysql: unspecified
| Package(s): | community-mysql | CVE #(s): | |||||
| Created: | July 11, 2016 | Updated: | July 13, 2016 | ||||
| Description: | Latest upstream release, 5.7.12, fixes unspecified vulnerabilities. | ||||||
| Alerts: |
| ||||||
davfs2: unspecified
| Package(s): | davfs2 | CVE #(s): | |||||
| Created: | July 11, 2016 | Updated: | July 13, 2016 | ||||
| Description: | Update to the latest upstream release to fix unspecified vulnerabilities. See the Red Hat bugzilla for more information. | ||||||
| Alerts: |
| ||||||
gnutls: certificate verification vulnerability
| Package(s): | gnutls | CVE #(s): | |||||||||||||
| Created: | July 12, 2016 | Updated: | July 25, 2016 | ||||||||||||
| Description: | From the Red Hat bugzilla:
A vulnerability was discovered in gnutls that affects certificate verification when GnuTLS is used in combination with the p11-kit trust module. This issue affects gnutls 3.3.23, 3.4.12 and later versions. | ||||||||||||||
| Alerts: |
| ||||||||||||||
gsi-openssh: support GSI authentication
| Package(s): | gsi-openssh | CVE #(s): | |||||
| Created: | July 12, 2016 | Updated: | July 13, 2016 | ||||
| Description: | From the Fedora advisory:
This version of OpenSSH has been modified to support GSI authentication. This package includes the core files necessary for both the gsissh client and server. To make this package useful, you should also install gsi-openssh-clients, gsi-openssh-server, or both. | ||||||
| Alerts: |
| ||||||
httpd: authentication bypass
| Package(s): | httpd | CVE #(s): | CVE-2016-4979 | ||||||||||||||||
| Created: | July 12, 2016 | Updated: | July 18, 2016 | ||||||||||||||||
| Description: | From the CVE entry:
The Apache HTTP Server 2.4.18 through 2.4.20, when mod_http2 and mod_ssl are enabled, does not properly recognize the "SSLVerifyClient require" directive for HTTP/2 request authorization, which allows remote attackers to bypass intended access restrictions by leveraging the ability to send multiple requests over a single connection and aborting a renegotiation. | ||||||||||||||||||
| Alerts: |
| ||||||||||||||||||
libgd2: denial of service
| Package(s): | libgd2 | CVE #(s): | CVE-2016-6161 | ||||||||||||||||||||||||||||||||||||||||||||
| Created: | July 12, 2016 | Updated: | July 27, 2016 | ||||||||||||||||||||||||||||||||||||||||||||
| Description: | From the Ubuntu advisory:
It was discovered that the GD library incorrectly handled memory when encoding a GIF image. A remote attacker could possibly use this issue to cause a denial of service. | ||||||||||||||||||||||||||||||||||||||||||||||
| Alerts: |
| ||||||||||||||||||||||||||||||||||||||||||||||
nodejs-ws: denial of service
| Package(s): | nodejs-ws | CVE #(s): | |||||||||
| Created: | July 11, 2016 | Updated: | July 13, 2016 | ||||||||
| Description: | From the Red Hat bugzilla:
ws is a "simple to use, blazing fast and thoroughly tested websocket client, server and console for node.js, up-to-date against RFC-6455" By sending an overly long websocket payload to a ws server, it is possible to crash the node process. | ||||||||||
| Alerts: |
| ||||||||||
php5: cross-site scripting
| Package(s): | php5 | CVE #(s): | CVE-2015-8935 | ||||||||||||||||||||
| Created: | July 8, 2016 | Updated: | July 13, 2016 | ||||||||||||||||||||
| Description: | From the openSUSE advisory:
CVE-2015-8935: XSS in header() with Internet Explorer (bsc#986004) | ||||||||||||||||||||||
| Alerts: |
| ||||||||||||||||||||||
samba: crypto downgrade
| Package(s): | samba | CVE #(s): | CVE-2016-2119 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Created: | July 8, 2016 | Updated: | December 19, 2016 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Description: | From the Slackware advisory:
This release fixes a security issue: Client side SMB2/3 required signing can be downgraded. It's possible for an attacker to downgrade the required signing for an SMB2/3 client connection, by injecting the SMB2_SESSION_FLAG_IS_GUEST or SMB2_SESSION_FLAG_IS_NULL flags. This means that the attacker can impersonate a server being connected to by Samba, and return malicious results. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Alerts: |
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tcpreplay: denial of service
| Package(s): | tcpreplay | CVE #(s): | CVE-2016-6160 | ||||||||||||||||||||
| Created: | July 8, 2016 | Updated: | December 6, 2016 | ||||||||||||||||||||
| Description: | From the Debian-LTS advisory:
The tcprewrite program, part of the tcpreplay suite, does not check the size of the frames it processes. Huge frames may trigger a segmentation fault, and such frames occur when caputuring packets on interfaces with an MTU of or close to 65536. For example, the loopback interface lo of the Linux kernel has such a value. | ||||||||||||||||||||||
| Alerts: |
| ||||||||||||||||||||||
Page editor: Jake Edge
Next page:
Kernel development>>
