About the security content of iOS 7.0.6
support.apple.com
support.apple.com
"congrats to the Apple iOS team on adding SSL/TLS hostname checking in their latest update! very cool feature."
However this is a pretty damn serious oversight.
I've just shut down my MacBook and picked up my ThinkPad.
Bad Apple.
The lack of hostname checking for IP addresses in Apple's cURL is a completely different problem.
It appears they haven't posted newer source than this. The most recent timestamp I could find was Oct 11, 2013 in 55471, which corresponds to 7.0 and my 10.9 system has the same version number for Security.framework -- same bundle version of 55471 for 10.9.1 aka 13A581. Previous version numbers don't appear to be as well-maintained. I don't expect a newer release to be posted until the next OS X release, as the source was only published under 10.9, not iOS. Additionally, there's no mention of iOS 7 on http://www.opensource.apple.com/
I couldn't easily find the bug without more to go on, because the code is spread across a few components and really, I'm not an expert in TLS. It appears to have been largely unchanged from 2000-2006 or so. TLS 1.2 brought quite a few changes, but it was neat to browse through the lines of "FIXME" and "TODO" comments, as well as various diffs between releases. And neat to see how much code today still goes back to 1999-2001, sometimes all they did was add a 'k' in front of a few variable names or delete the line in the first README saying the server code wasn't tested against Windows ;-)
It sounds like when 10.9.2 is released, or at worst when 10.10 comes along, you'll see a new push of code to the opensource site. We can all diff 55471 against what comes next to see the changes. (If someone's already running 10.9.2 and its unaffected by the bug exhibited via curl, open /System/Library/Frameworks/Security.framework/Versions/Current/Resources/Info.plist and post the Bundle version.)
specifically check the function SSLVerifySignedServerKeyExchange
I leave the joy of spotting it to you. It is obvious and if you know c you'll see it(You don't need any knowledge of crypto).
Check line 631. Appears seemingly out of nowhere.
But, are you sure the 10.8.5 (-55179.13) version isn't in some sense a later, patched maintenance branch compared to a 10.9 (-55471) that might have been frozen earlier? The release dates are very close (~2013-10-03 for 10.8.5; ~2013-10-22 for 10.9), and they might have already been separate branches.
(Is there a 10.8.4 version to compare?)
It doesn't seem like what you said is the case here but obviously we're still missing changesets that may have been committed between 10.8.5 (Security-55179.13) and 10.9 (Security-55471). It'd be really interesting to do a git-blame on that file.
EDIT: Nevermind, that file wasn't open-sourced in 10.8. It's actually really old. (Look for directories starting with libsecurity_ssl in pre-10.8 OS X versions.) Didn't find anything particularly interesting in the old versions though.
Thanks in advanced
Others might say it's a problem of whitespace insensitive languages ;)
Execution will arrive there somehow, but the 'how' is unclear. The word "fail" implies you should reach that point only if there was an error, but that is a bad assumption in this case.
If the real answer to 'how did we get here?' was checked, then the bug could not hide in the undefined behavior. This would not allow a dangling goto to result in a false positive. A false negative will get someone's attention when their web page doesn't load.
Something like this could remove the undefined state:
goto pass;
fail:
if ( err == 0 ) {
assert( err != 0 ); // BUG! variable must contain an error number
err = kSomeAppropriateErrorNumber;
}
pass:
SSLFreeBuffer(&signedHashes);
SSLFreeBuffer(&hashCtx);
return err;It might be more noticeable, but then, the original bug existed because no one noticed.
return ERRCODE;
Would have produced the exact same bug.Of course Python doesn't even have a goto, so the code would have needed to be structured differently to start with.
If I were a betting man I'd wager that this bug wasn't really an accident. It would be really interesting to check commit logs to see the history.
Really? I did something in Python for the first time a while ago and the indentation as code block is something I find very elegant. I can't fathom why would people find something wrong with this.
I think something similar should apply to critical security code. This reminds me of when someone tried to add the following to the Linux kernel:
if ((options == (__WCLONE|__WALL)) && (current->uid = 0)) retval = -EINVAL;
Oops, is that "uid == 0", or is that "uid = 0"? Yet another "typo" that couldn't happen in Python.
if((val = function(args)) != expected)
return val;I'm actually pretty impressed how this bug was not caught before. The compiler warning is just one thing that came to my mind but test coverage should have been the strongest hint. A linter could have also make the thing easier for a code review. Probably these parts of the code should have stricter coding guideline.
Not by default. On both GCC and Clang this kind of error isn't caught using -Wall or even -Wextra - you have to explicitly opt-in using -Wunreachable-code. It'd really be nice if that changed and Clang basically had close to -Weverything on by default and required you to opt out, preferably with something like `#pragma ALLOW_SHODDY_<category>` per file to put some pressure on C programmers not to just continue ignoring errors rather than fixing them.
Either way, definitely avoidable.
Looks typical of a merge cock up to me as the indentation is preserved suggesting it's a duplicate line or there was an if statement on the previous line that was removed.
> However later code is used as a jump target for goto so it's quite hard for the compiler to infer this
Nope, because a jump target always starts a new basic block.
Thanks for the hint. It was amusing to spot the actual bug.
I thought I would hate this model but I absolutely love it. It's the next best thing to pair programming and somewhat less exhausting.
Another clue: indentation fail.
But one thing that pisses me off is that they go and implement SSL and don't have any automated tests for it!!
For a company of Apple's size, that can only be called grossly negligent. There is no excuse. And they probably don't have any automated testing for most of their other code either.
What I would expect is that SSL code is tested with all the different of ways of spoofing a certificate. And that in an automated manner, on every build.
I could see if they were copying & pasting goto statements all over the place, and happened to paste it twice by accident. But that's how it occurred. The second one was added in a separate commit.
I wonder whether the software from the guys at viva64.com would spot that.
However I can't see a valid case for this pattern so static analyser rule to knock it on the head would be a good idea.
clientRandom.data = ctx->clientRandom;
clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
serverRandom.data = ctx->serverRandom;
serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
That is something that I think static analysis tools could signal. It would be a red herring, though.The state of the operation is "success" (err==zero) until some step changes the state to "failure" (non-zero).
The state should be assumed to be "failure" until the last step changes it to "success".
Mixed tabs and spaces, inconsistent indentation, two empty lines in a row, sometimes "if (...)" and sometimes "if(...)".
http://blog.cloudflare.com/red-october-cloudflares-open-sour...
- don't leave local variables uninitialized.
- don't try to hand-optimize lines unnecessarily.
- don't mix assignments into boolean expressions. (Which is really an unneeded optimization.)Absolutely terrifying that crypto safety is such a low QA priority that something like this could ever leave the building.
> A test case could have caught this, but it's difficult because it's so deep into the handshake. One needs to write a completely separate TLS stack, with lots of options for sending invalid handshakes. In Chromium we have a patched version of TLSLite to do this sort of thing but I cannot recall that we have a test case for exactly this. (Sounds like I know what my Monday morning involves if not.)
So no matter how strange or malicious the server-side stack would need to be... not having a test for such a deviation is a major oversight.
Background on Secure Transport:
"At the bottom of the TLS stack on both iOS and Mac OS X is a component known as Secure Transport. Secure Transport maintains a per-process TLS session cache. When you connect via TLS, the cache stores information about the TLS negotiation so that subsequent connections can connect more quickly. The on-the-wire mechanism is described at the link below.
http://en.wikipedia.org/wiki/Transport_Layer_Security#Resume...
"This presents some interesting gotchas, especially while you're debugging." More at: https://developer.apple.com/library/ios/samplecode/AdvancedU...
You won't be able to get the new iOS 6.1.6 on your iPhone unless it supports iOS 6 but not iOS 7, it is basically only for iPod 4th gen.
/usr/bin/curl on Mavericks suffers from this problem:
~ /usr/bin/curl https://imperialviolet.org:1266
If you can see this message then[...]
Keep that in mind when you download an installer using curl and pipe it to bash.Edit: apparently curl does use Secure Transport on OS X as of 7.27:
http://curl.haxx.se/mail/lib-2012-06/0334.html
http://daniel.haxx.se/blog/2012/06/28/darwin-native-ssl-for-...
Of course the jailbreaking community knows well that there have been many ways around that...
[1] http://appleinsider.com/articles/13/12/31/ios-7-now-installe...
Really old devices are probably out of luck, though. I think that would encompass the original iPhone, the 3G, the corresponding iPods Touch, and (probably most importantly) the first generation iPad. That's assuming, of course, that the bug is in iOS 4/5 in the first place, but if it dates back to iOS 6 I'd give good odds that it dates back farther still.
Just a guess, but from the short description I suspect if you have control over DHCP you can get iOS to use your proxy. From there you can use something like mitmproxy ( http://mitmproxy.org/) to forge SSL certificates on the fly and intercept and decrypt SSL traffic without any warnings showing up on the iOS device.
In this case Apple is not performing the domain validity checks on the presented cert. This allows an attacker that is performing an mitm attack to present a valid cert for another domain and establish an SSL connection with the victim.
If you want to see my favorite SSL bug ever.
Perhaps a preferable practice for security-conscious code would be to only set a success value after all checks have passed, rather than trust intervening logic to reset a default-success value, to an error-value, before return.
> Currently the verify operation continues after errors so all the problems with a certificate chain can be seen. As a side effect the connection will never fail due to a server certificate verify failure.
https://www.openssl.org/docs/apps/s_client.html
https://www.mail-archive.com/openssl-users@openssl.org/msg71...
EDIT: I'm an idiot, see below.
I have been trying to work on an implementation of TACK to mitigate headaches involved in pinning. Wish I had more free time.
I can't help wonder how much worse a similar situation would be for the Android ecosystem, with the poor update track record of operators and OEMs.
Deleted comment
http://i.imgur.com/CoALymQ.png
(i've not checked that on iOS or Apple TV just on OSX. Maybe it's another issue but the update description pretty much fits too well ;-)
(I deleted my gp, because it's pretty much obsolete now with your full disclousure. Thanks!)
http://daniel.haxx.se/blog/2012/06/28/darwin-native-ssl-for-...
Secure Transport by Apple is also known as Darwin/SSL.
https://213.133.107.227.xip.io/
Still an epic QA failure but much less of a threat if it doesn't allow arbitrary MITM attacks.
Just sell me the beautiful hardware.
I'll manage installing an OS that's 1. audited by a community of volunteers I generally trust and 2. can be audited (read: modified) by me: I can compile it from scratch.
Apple's OS offerings provide neither 1 nor 2.
But, go figure, Apple's OS offerings are based off of OS code that is both 1 and 2.
Like a "Linux distro", Apple gives me a lot of stuff I do not want or need, and makes it very difficult if nt impossible to remove.
I want a very minimal BSD or Plan9 OS running on my Apple hardware.
And nothing more.
Hardware we purchase should come with full documentation for writing drivers.
If enough users demand this, maybe someday it will.
Everything has bugs, community volunteers are not infallible. It's good to be able to audit the things you use, but most people can't or won't do it.
Only if they used a truly stupid compiler. Chances are the unreachable code behind it got optimized away.
If you use NSS-based browsers exclusively on OS X, can you have been pwned via fake updates due to this bug?