Vulnerability in Microsoft TLS library could allow remote code execution
technet.microsoft.com
technet.microsoft.com
Regardless, I am more afraid of buffer overflows and general memory management errors than I am of timing attacks. Heartbleed was orders of magnitude easier to exploit than (say) the Bleichenbacher attacks that JSSE has been vulnerable to.
Heartbleed was certainly easier to exploit, than a timing attack - no disagreement there. But the Java SSL stack is pretty flakey and largely seems to be unused. It has lots of interoperability problems with other implementations and generally seems immature. It's not something I'd trust in production myself.
Going with JSSE does have the downside that it's less widely used. Browser makers don't patch it with the latest gizmos like they do with OpenSSL. However, it's at least got a full time development team (unlike OpenSSL until very recently), and ultimately if there are odd conformance bugs lurking the only way they'll be shaken out is by people using it for real. Passing the Qualys test is a good start, but for now my little website is ideal because it is unlikely to ever be popular enough to have serious scaling issues and I can tolerate some incompatibility with odd clients.
Even that is harder than it looks.
For example, a common way of doing a constant time string compare is:
$result |= (ord($safe[$i % $safeLen]) ^ ord($user[$i]));
i.e. get the character to compare mod the length, so you wrap around if the length of the two strings is not the same.Unfortunately the mod operator does not take a constant time on a CPU! If the result is evenly divisible it's faster.
So even in assembly you might not be able to protect from a timing attack. Even if you check your current CPU a new one might be different.
(In this case a better way to do the compare is if the strings are not the same length, compare the attackers string against itself, and then return false.)
($i + 1) % $safeLen
Even so, I guess the only way to eliminate timing attacks would be to write a set of primitive operations (XOR, AND, OR, ORD,...) which are constant-time (on the supported hardware platform) and only use those wherever the private information is handled. Is this possible to do? Are there any attempts at this?Is there a reason for using the attacker's string rather than the valid string? Edit: it doesn't seem to me that using the valid string would leak its length unless the attacker knew quite a lot about the target machine.
It sounds like you are skeptical that timing attacks can be practically exploited. This is a reasonable skepticism that most people go through on initially learning about them. Unfortunately, there are in fact working exploits for this sort of thing.
As I understand it, the correct thing to do is to derive a sleep time from hashing the request content, along with some secret. This makes the delay "random" from the attackers point of view, but still deterministic and therefore impossible to filter out.
Note: I am not a security person, just an interested bystander. Take this half-remembered advice with a pinch of salt.
2. Less than you'd think. e.g., the total count of all 1 and 2 and 3 digit numbers is only 11% of the count of 4 digit numbers. (And that stat gets worse with just lower case letters.) Searching all shorter passwords ends up being an insignificant amount of time compared to searching all correctly sized passwords.
I completely agree with you there. X.509 is a nightmare and it's not an area where constant time matters at all. Being resistant to buffer overruns and general logic errors is much more important there.
There is no reason ciphers like djb's that use data-independent code paths couldn't be integrated into X.509 if the will was there. Totally separate issues.
Your fallacy is that there are several JVMs to choose from, each with its own set of JIT and AOT compilers.
Don't judge Java by OpenJDK, it is only the reference implementation.
What does that even mean? If you write your fail and success states to follow the same exact code paths (i.e. no branches, breaks, returns, or similar for failed) then you've created a "constant time" function.
The inputted parameters are dynamic so the JIT-compiler cannot optimise code away, and even if it could it would do so equally for both the failed or success states.
> Certainly Christopher Meyer has said that he's reported some that remain private since they've not been fixed.
I tried Googling that but nothing. Can you link whatever it is you're talking about?
(1) They require you to have a pre-recorded SSL session you're trying to crack. Random script kiddies won't find it useful.
(2) They require sending a lot of traffic to the server to try and break that single recording (you can get caught quite easily!)
(3) They don't reveal the private key, only per connection premaster secrets (if I understood correctly).
Basically, the first attack was possible because JSSE returned "internal server error" when faced with a particular kind of malformed packet instead of "bad padding" - this binary yes/no thing was enough to allow the attacker to divine some internal state and with enough queries retrieve the PMS. The second was a similar trick but instead of observing a different error code, it exploited the fact that internally the code was throwing an exception and this made a difference of some microseconds in the response. Over a LAN, with enough queries, that was enough to eventually reveal the PMS. However when running over a much noisier environment like the internet, number of queries required goes up quite a bit. I believe, they did not test that.
As I said before, they were both fixed, and I think Rich now agrees with me that they were fixed. There may be others that would require compiler support or hand coding of assembly to fix. Certainly there's nothing in the design of Java or the JVM that makes that impossible however. Stuff handling key material is only a small part of the overall SSL picture.
I think using native code for the low-level implementation of the ciphers, padding etc. would be a good move from a security point of view and is the only way to get constant time implementation. As you say, there's nothing that prevents that in the design of Java.
"What does that even mean? If you write your fail and success states to follow the same exact code paths (i.e. no branches, breaks, returns, or similar for failed) then you've created a "constant time" function."
Well, if you've got a JIT that is analysing which code actually executes, and no control over the optimisations then how do you achieve this? If the hotpath is normally the success condition for example then the JIT will optimise that more. The rare and more dangerous condition will be optimised less. If this happens of course will depend on the engine, but you can't control that without working at a much lower level than managed code offers.
The same is true with native code optimising.
> If the hotpath is normally the success condition for example then the JIT will optimise that more.
The paths should be identical for both failure and success states. That's fundamentally how you "fix" timing attacks.
> If this happens of course will depend on the engine, but you can't control that without working at a much lower level than managed code offers.
You write code that has no hot paths regardless of if correct/wrong. That's how timing attacks are mitigated in all languages.
This is rubbish. If I use custom assembler then that's what gets run. Even if I use C code then I know what the result will be since I can actually check.
> The paths should be identical for both failure and success states. That's fundamentally how you "fix" timing attacks.
That's certainly the ideal. But it's impossible - one result will succeed the other won't. The aim is to make sure both take the same time which is an achievable goal, however to do this you need to know what will execute. You might have that guarantee in practice on a particular JVM for example, but the whole point of using something like a JIT is that it will be smart about optimising stuff based on what actually happens. That's normally great, but this is a situation where all that needed is predictability not performance.
It is "rubbish?" Nobody does that. Most crypto libraries are written in C or C++.
You can pre-JIT (AOT) managed code and check there too.
> That's certainly the ideal. But it's impossible - one result will succeed the other won't.
It is absolutely possible with high coding standards. Keep in mind you only have to write "correct" code in sections which have access to things like crypto keys (or things that are derived from similar), since that's what at risk with timing attacks.
> You might have that guarantee in practice on a particular JVM for example, but the whole point of using something like a JIT is that it will be smart about optimising stuff based on what actually happens.
If the code paths are identical (failure and success) what is it optimising out exactly?
Take a look. You'll see that for example openssl uses perl to generate assembly, and nettle also uses native code. This is needed if you want to use things like the AES instructions on modern CPUs.
JITs can create separate versions of a function for different inputs. A good JIT can turn one general case function into multiple optimized special cases using techniques that include eliminating pseudoconstants (variables that always have the same or a small number of values) and skipping computation of never-referenced results. Even normal compilers can do a lot of that.
The e=3 vulnerability (or its more modern "BERserk" variant) are arguably much easier to exploit than Heartbleed. They allow you to --- offline, in advance --- make your own valid CA certificates.
That makes no sense at all. Timing attacks aren't more or less exploitable in managed code than unmanaged code. Timing attacks are often the result of optimisations within the crypto library which inadvertently give away information, for example a loop which breaks on X != Y, instead of setting a failed = false bool and continuing to iterate through the rest of the array.
Please explain how managed code makes timing attacks more likely.
I would say this is false. Simple differences in time caused by cache line ejection in table-lookup implementations of AES provide a very strong timing attack. (http://cr.yp.to/antiforgery/cachetiming-20050414.pdf)
In RSA (and in fact DL based cryptosystems), modular exponentiation without extreme care leak tons of timing information about private exponents. 'Blinding' is one way to handle this, but performant solutions typically fiddle at the bit level and exploit CPU guards and features to minimize branch prediction/cache line/etc leaks.
In higher level languages absolute control and care of crypto implementations can not be taken and the JIT layer adds another layer of obfuscation (though I know of no attack employing that...).
The out for memory safe languages is to provide built in crypto operations that have been implemented at a lower level.
Please point me to the specific native features which mitigate timing attacks. Because the majority of fixes I have seen are purely in altering the libraries themselves using high level constructs to remove hot paths and make it so both failure and success state take a constant time to execute (which has nothing to do with managed/unmanaged code).
Another important difference between native code and high-level code is that timing leaks in high-level code tend to be larger. For instance, it's very difficult to exploit a memcmp timing leak in practice. But Java's string comparison, depending on your JVM, is exploitable over the Internet.
For what it's worth: I wouldn't select C over Java simply to avoid timing attacks. Side channels in JVM code are a legit concern, but not a dispositive one.
I hope that's not what I said...
> Please point me to the specific native features which mitigate timing attacks.
How am I supposed to implement bitslicing to vectorize operations in Java? I can't. Fine grained control of code is important for implementations of ciphers that are both fast and side-channel free. Fine grained control isn't something Java can give you, by definition.
Take the 'countermeasures' section of 'Efficient Cache Attacks on AES, and Countermeasures' (http://www.cs.tau.ac.il/~tromer/papers/cache-joc-20090619.pd...).
I count exactly two countermeasures that apply to high level languages. Of the first they say "We conclude that overall, this approach (by itself) is of very limited value" and of the second "beside the practical difficulties in implementing this, it means that all encryptions have to be as slow as the worst case... neither of these provide protection against prime+probe/etc".
The rest of the countermeasures suggest bitslicing, use of direct calls to hardware instructions, memory alignment tricks, invocation of hardware modes (i.e. to disable caching), forcing cache ejections, normalizing cache states on interrupt processing, etc.
It is purely the case that high level languages do not offer you the flexibility and control to implement side-channel free crypto.
Crypto is brittle. High level languages are awesome for so many things. But bitslicing isn't one of them. The entire premise of high level languages is that you are freed from working directly on the innards pertinent to the specific target architecture. The entire premise of side-channel free crypto is that you need visibility and control of exactly these things.
By using unsafe (not ideal), the GPGPU bindings like Aparavi/JCuda or the future GPGPU API?
Honest question. Wondering about the possibilities.
> It is purely the case that high level languages do not offer you the flexibility and control to implement side-channel free crypto.
I would say Ada is an high level language that offers C and C++ flexibility, while being safe.
For example:
const string password = "password";
static bool isAllowed(string code)
{
if (code.Length != password.Length)
return false;
for (int x = 0; x < password.Length; x++)
{
if (code[x] != password[x])
return false;
}
return true;
}
Is not constant time because the failure state returns sooner than the success state. const string password = "password";
static bool isAllowed(string codex)
{
bool allowed = true;
char[] code = new char[Math.Max(password.Length, codex.Length)];
codex.CopyTo(0, code, 0, codex.Length);
for (int x = 0; x < password.Length; x++)
{
if (code[x] != password[x])
allowed = false;
}
return allowed;
}
This is an imperfect constant time function as both states (failure/success) return near after the same amount of time (although I fully admit that it might be possible to impose the length of the password constant).But more fundamentally, what is string.Length? Are these Pascal-style strings, or is that a call to a method that walks the string (O(n))? Those kind of issues (along with the full nature of the code path taken by something like assignment and memory allocation) are abundantly more clear in assembler (or byte code, assuming a predictable vm. But a vm likely isn't -- as far as I know it would at least never be more predictable than machine code).
In what sense? In the sense of not mathematically fixing the problem, or in the sense of leaving it feasible to exploit in reality?
The problem is that the law of large numbers is on the attacker's side. If the attacker gets N tries his statistical power goes as sqrt(N), which means that to stay safe the variance in your random delay has to be large enough to cover that. That is, if d is the timing difference between the slow path and the fast path and the attacker gets N tries, the variance in your random delay has to be on the order of d sqrt(N). This is huge even for modest values of N.
I'd argue they're both as bad as one another. Since GC is non-deterministic it means you just need more cycles for an accurate result (and plus you're already having to ignore other sources of latency, like network, disk IO, OS lock contention, etc).
Timing attacks are generally a coding problems, both a JIT-ed managed codebase and a native block of code can contain them.
Let's hope Midori is more than just a rumour. Singularity was pretty darn good for a research OS.
Since then, my chief concern with JSSE has been simply not knowing how solid it is from a correctness of the algorithms perspective, but that is something I'm not well versed in. In other words, my concern was just one of uncertainty. Provided a credible security analysis suggests JSSE is just as secure (if not moreso) than alternatives in unsafe languages, I will be confident deploying future apps on JSSE.
Back in the day Extended Pascal, Modula-2,Mesa... and C compilers had similar code quality.
If today compilers for safer languages are slower than C compilers, it is mainly a consequence of compiler vendors focusing in improving C optimizers.
That isn't significant on modern hardware relative to other bottlenecks (network, IO, etc). Plus people keep adding additional security layers between C/C++ and the CPU which eat away at some of its advantages (e.g. Docker containers, virtual machines, exploit detection libraries, etc).
Java speed matters in certain situations and for certain tasks. For example I wouldn't rewrite an SQL database into Java since performance could definitely be impactful there. But realistically CPU times are such a tiny minority of latency that it stopped being relevant a very long time ago.
I don't think you can pick a single number like that, it depends very much on what the code is doing.
You probably got this 10x figure from a Google paper published a few years ago (https://days2011.scala-lang.org/sites/days2011/files/ws3-1-H...). Redux: the default out of the box 32 bit JVM (in 2011) was 12x slower than the same algorithm implemented in Java. But with a few simple GC flag changes, it became 3.7x slower. And then the Java version had a few further simple optimisations applied to the code and it became as fast as the original C++ version.
Meanwhile the C++ version was optimised again and became around 3x to 5x faster, but that version relied heavily on Google proprietary data structure code and could not be open sourced (!). So for most programmers on most projects, it seems likely to be a wash.
Meanwhile an alternative benchmark that reimplemented a non-trivial C++ program in Java found it became 1.09 to 1.5 times slower, but that was with Java 6 which is now two generations out of date:
http://www.best-of-robotics.org/pages/publications/gherardi1...
It would be interesting to get more recent benchmarks with the latest JVMs and C++ compilers.
In particular, anything requiring manipulating unsigned values all over the place will be a lot slower.
Also, see this[1] for talk about JGit. An actual project with direct comparisons.
The MMAP thing is also a good point. I believe HotSpot will compile the get methods on the MappedByteBuffer down to raw access so it shouldn't matter much for performance, in theory, but the code is still damned ugly. I never understood why they can't expose it as a byte[].
You kind of have them in Java 8, but not as primitive type.
https://blogs.oracle.com/darcy/entry/unsigned_api
I also think a very least having ubyte would be quite nice.
Apparently the reason behind the decision has to do with overflows and underflows in unsigned arithmetic.
Hotspot is just one of many Java native compilers out there , so it is better not to rely on what Hotspot does.
On the other hand, you can make use of JIT Watch or Solaris Studio debugging to see what Assembly is being generated.
> I never understood why they can't expose it as a byte[].
Maybe the official unsafe class will make this better.
I don't understand why a just-in-time java compiler would produce slower code than an ahead-of-time c++ compiler, especially since the java compiler has much more information available (exact cpu revision, cache and ram sizes, and hot spot profiling).
Depends which JVM you are talking about.
For example Graal is more aggressive than Hotspot in selecting variables for escape analysis.
Each JVM (IBM, HP, Aonix, ...) has different quality levels in escape analysis.
one in c++, one in java
10x is giving it too much credit.
Java wouldn't work very well!
In particular, running a program from bash would simply classload it into the existing VM, not invoke a whole separate VM, and then it'd be more or less instant, except you'd have the potential for much more flexible APIs and combinations of tools. Look at PowerShell for an example.
Powershell is a terrible example for the performance point I am trying to make, whatever about its flexibility.
[0] http://www.javalobby.org/java/forums/t72620.html
[0] http://stackoverflow.com/a/13496610
[1]http://www.ibm.com/developerworks/library/j-multitenant-java... (this now looks less experimental but I'm willing to bet >1 instance of eclipse, or bash for that matter would not work very well).
I'm not sure how this works: http://www.excelsiorjet.com/
but it might help to alleviate the problem even though it still has a jvm.
https://en.wikipedia.org/wiki/Java_Classloader
looking at what you mention now, can a program classload itself? seems not: A class with a given name can only be loaded once by a given classloader.
I doubt you would even have to go as far as native extensions for GUI before you start running into problems even though the programs are written in managed code.
Can you better explain how in practice Java programs could share a VM in replacing a typical Unix bash environment/userland?
Would they have to use the special IBM JVM? Would bash have to contain grep as a class? e.g.
machine:~$ grep include Source | grep -v 32 | grep -v 16
Reading about "JAR hell" I really don't think it would work very well.
Interestingly in the IBM link provided earlier they load up substantial non GUI servers such as Tomcat, Jetty and JRuby and achieve a startup time that is twice as fast.
They also have hello world:
Hello World Print "HelloWorld" and then sleep
Multi-tenant JVM: 309
Hand-tuned: 73
Default: 63
Improvement with multitenant: 4.2X to 4.9X
Even with this I think a C++ version would eat it for breakfast. It would be interesting to find out what would happen if a Single JVM were loaded on boot, all programs were loaded into that and compare the JVM based Unix on those terms with e.g. Solaris or something.
Modern JVMs can use AES-NI hardware instructions when available, in some cases at least, so I'd imagine it's not too awful. But I honestly don't know. Benchmarks would be interesting.
That said, in my experience, native SSL/TLS within IIS is incredibly slow/inefficient. Running on 2012R2 (so a modern version), terminating SSL at IIS resulted in me being able to trivially peg the server's CPU using Apache Ab on my laptop. So clearly you need a good implementation.
The worst barrier was probably the cost and hassle of obtaining browser-accepted certificates though.
[1] http://blogs.technet.com/b/srd/archive/2014/11/11/assessing-...
EDIT: Added a better source.
> Other versions or editions are either past their support life cycle or are not affected
And XP is unlisted. Seems to imply that it could be either one.
There are other issues with browsers (namely that a lot of XP users are still using IE8, which has a host of other issues).
The project I am now on isn't supporting IE8, we're going to load some HTML5/ES6 shims, and a notice to users that it may not work, but given how poorly MS's VMs for testing IE8 on XP are, it's really a non-starter. IE8 is about 3-4% of our current traffic, which will likely be displaced by mobile traffic once our site/app is no longer mobile hostile.
I wouldn't consider XP a viable OS at this point, and many users would be better off with a more recent ubuntu, and wine.
Does this update contain any additional security-related changes to functionality?
Yes. In addition to the changes that are listed in the Vulnerability Information section of this bulletin, this update includes changes to available TLS cipher suites. This update includes new TLS cipher suites that offer more robust encryption to protect customer information. These new cipher suites all operate in Galois/counter mode (GCM), and two of them offer perfect forward secrecy (PFS) by using DHE key exchange together with RSA authentication.
https://www.imperialviolet.org/2013/10/07/chacha20.html
Also, did they even add support for Curve25519? Or are they still forcing us all to trust the (almost certainly) tainted NIST curves?
Windows 7 and later do already support ECDHE + GCM, but only when combined with ECDSA. In practice, nobody can use ECDSA because old clients still need RSA certificates.
So we continue to wait for TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, which is clearly the cipher suite that everyone wants. Years later, still not available for Windows Server.
Is the exploit only for when running services on/to the internet (IIS, Exchange webmail, etc - ) , or is visiting an https (TLS) website on and end-user enough to make the exploit happen (even in Firefox/Chrome and behind a tradional proxy server).
Sadly Microsoft does not explain the exact parameters that make this exploit tick - this makes risk assessment hard.
See more: http://adi.is/winshock.txt
How worried should people reasonably be?
There isn't an acknowledged proof-of-concept, so we're not sure that it's exploitable. It hasn't been made clear whether it's wormable, either.
My bet is it will affect XP if it's exploitable, but only for those who added IIS (not default, and not terribly common). It will likely remain unpatched forever, as Microsoft is unlikely to send a patch to an "unsupported" OS again, like they did with the Internet Explorer 0-day [0]
[0]: http://blogs.technet.com/b/msrc/archive/2014/05/01/out-of-ba...
By Microsoft, but I'd bet someone else is definitely going to fix it and distribute a patch. If the amount of effort put forth by the Windows 98SE community in making unofficial patches that let much newer applications work is any indication (look up KernelEx and "98SE unofficial service pack"), XP is going to enjoy an even larger community of unofficial support.
If I recall correctly, SQL Slammer also targeted a server component, but the vulnerable component was also present on some desktop systems, which were then affected.
It wouldn't surprise me if for instance some printer driver listening on a high port also uses the schannel component, and is thus vulnerable.
IBM reported, MS did code review it seems, MS knew about some of these issues for ~6 months.
Patch immediately, people (like me) are running bindiff/etc and a public exploit won't be too far behind.
Not sure how far back it goes yet. All the way? The changes cover code going all the way back to the first SChannel code push, I think. (If XP is exploitable, this may be the XP killing vuln we've all been waiting for.)
It's very serious. Patch immediately.
But that's not a reason to use Firefox on XP. ;)
(Technical details: If the client offer one of the suites, the server is accepting it in the ServerHello, but then RSTing the connection after the client sends their encrypted handshake, and the event log says "none of the cipher suites supported by the client application are supported by the server". Browser and curl don't use that suite, but Amazon ELB does.)