Zinflate and AddressSanitizer finding #414
We started fuzzing library classes. Its dumb fuzzing, and all we do is generate a random string and send it into a filter like
It looks like
Running the test suite under Address Sanitizer with garbage/random data results in the following. It looks like we have an out-of-bounds read. Its not clear if there's an accompanying write, or if it can be controlled by an attacker.
Here are the Crypto++ 5.6.x patches. It looks like the issue predates Crypto++ 5.0 released in 2002.
Crypto++ 5.6.5 (released 2016-10-11)
Crypto++ 5.6.4 (released 2016-09-11)
Crypto++ 5.6.3 (released 2015-11-20)
Crypto++ 5.6.2 (released 2013-02-20)
Crypto++ 5.0 (released 2002-10-04)
referenced this issue
May 12, 2017
I should note I have not been able to reproduce this using any of the inputs provided by Jeffrey (@noloader) that were supposed to result in an out-of-bounds read under gcc + AddressSanitizer.
I tested using Visual Studio 2015, replacing the static int array with an object that would throw if an out-of-bounds index was provided. I could not get this issue to trigger.
I cannot say that the issue does not exist, but according to my current knowledge, it has not been proven to exist outside of the combination of gcc + AddressSanitizer.
Sorry about the delay in requesting the CVE. I'm going to copy it up to the initial report so others don't need to hunt for it.
One of the reasons for the delay is we wanted to test other interfaces, and then batch the request for CVE's. We were able to test a number of interfaces (including public keys, private keys and associated parameters), but we were not able to uncover additional problems. I think that's because of Issue 346, Security issue (DoS) in Crypto++ ASN1 decoder. The 346 issue was already known to us and it was previously hardened.
It may be worth noting we also added an assert, and it fires under debug builds with Clang, GCC, ICC and MSC. Others have experienced the assert on Windows machines; cf., Question about verification tests failing. And we see the assert logged during AppVeyor testing; cf., AppVeyor Build #70.
I'm looking through this problem for Debian wheezy but I have to ask a question about the patch.
This means that m_distance can be
Next time this part of the code is triggered then m_distance is used as index for both
I do not say that the patch is wrong. It is just that I wonder if something more fundamentally is wrong.
I believe the code your are talking about is around
I was not able to get into that code path during testing with bad data. The problem area that we detected was the code before it, around
I believe what happened was the code around line 560 failed to fill the buffer, it dropped into the conditional, and it subsequently executed the break. The
I was having trouble tracing some of the code paths. Its the reason the code was loaded with asserts. Often times its easier to instrument code with asserts and then let the code debug itself. The instrumentation lead us to line 560 as the point of first failure on some of the negative test cases.
I have a small concern about the patch. It addresses the immediate problem of the out-of-bounds read in the identified area. My open question is, are we rejecting "good" input? In this respect, we could be failing safe at the possible expense of rejecting valid input. The "fail safe and reject good input" was the reason for this question on the mailing list: RFC 1950/Inflator feedback needed.
Thank you. Yes I was referring to these places in the code. Now I can also see a number of asserts in the more recent code that do not exist in version 5.6.1 (that we have in Debian wheezy). I think that explains why we can not get into the problem I was referring to. However I have a similar concern as you regarding the possibility of rejecting good input. However I have that already with the asserts that probably have been there for quite a while.
In any case now I understand how the package should be patched (I think at least).
I think I have some good news here. I think I tracked down the root cause. It explains why I would see the issue under GCC but Denis would not witness it under MSVC, It looks like the test code was violating GCC's strict aliasing rules, and it created problems with the random strings were were compressing, decompressing and tampering.
What was happening is, we would generate a random string:
Then, we would get a hold of the non-const pointer with
Now, here's where the problem started. The test program would do things like take part of the
And the place we would get into trouble was, we would use the runts and underruns until the end of the closing block. However, GCC was scheduling
We did not generate findings for undefined behavior, but that does not mean it was absent. I'm not sure about this area of the C++ standard. Usually you get in trouble when the arrays are different objects; and not when they are the same object. Maybe Denis knows more about it.
We also cannot rule out a bug in Address Sanitizer. If we did not have undefined behavior and we did not violate strict aliasing rules, the the issue could have been rooted in Asan. Asan's internal mechanics may have been doing something that we interacted poorly with.
After doing away with the pointers into the
So it looks like the CVE was a false alarm. Current and past versions of the library were not at risk. And no versions of Crypto++ were released with the defective driver program. I believe the worst case now is, we have some extra checks in the library that probably won't be exercised.
My apologies for the false alarm.
@noloader - Excellent news! I was wondering about this issue, and if I should invest more time to try to reproduce it.
This unfortunately confirms my previous suspicions that GCC engages in over-aggressive and unsafe exploitation of technically undefined behavior that doesn't look undefined at first glance, or even second glance, and even to advanced users.
I think this is a considerable security risk for GCC users, and is one reason I avoid the compiler. I strongly disagree with the preference to optimize performance, instead of optimizing security, in situations such as this.
Do you know, is there even a warning that you can enable that would let you know there's undefined behavior in this case? Does GCC contain diagnostics for this, or is it necessary to use external tools to avoid this type of issue?