- Адам Лэнгли объяснил причины бага в iOS: лишняя строчка кода поломала всю безопасность
- Understanding the Apple ‘goto fail;’ vulnerability
- Vulnerability details
- Who is affected?
- How did this happen?
- How could this have been prevented?
- Writing/compiling code
- Reviewing code
- Testing
- Protocol definition
- What can you do about it?
- «goto fail;» considered harmful
- «goto fail;» considered harmful
Адам Лэнгли объяснил причины бага в iOS: лишняя строчка кода поломала всю безопасность
Вчера компания Apple выпустила обновление безопасности iOS 7.0.6 для iPhone 4 и более поздних моделей, iPod touch 5-го поколения и iPad 2+. Одновременно выпущен аналогичный патч 6.1.6 для iPhone 3GS и iPod touch 4-го поколения.
Обновление закрывает уязвимость CVE-2014-1266, которая позволяет злоумышленнику из «привилегированной позиции в сети» перехватывать и модифицировать пакеты в сессиях, защищённых SSL/TLS. Речь идёт о MiTM-атаке с подменой трафика.
В лаконичном пояснении Apple говорит, что при установке защищённого соединения по SSL/TLS система не способна определить аутентичность соединения. Проблему решили путём «добавления недостающих этапов валидации».
Хотя по лаконичному описанию не совсем понятно, каких конкретно «этапов» не хватало, но можно говорить об отсутствии полноценной защиты соединений. Так или иначе, но отсутствие необходимых этапов аутентификации означает, что раньше на все устройства Apple третьи лица, вероятно, могли устанавливать поддельные/модифицированные апдейты ОС на смартфоны и планшеты пользователей.
Сегодня известный криптограф Адам Лэнгли опубликовал статью с анализом бага в iOS. Он обращает внимание на разницу в коде OS X 10.8.5 (Security-55179.13) и 10.9 (Security-55471), где, вероятно, исправлен тот же самый баг.
Собственно, вот он.
Обратите внимание на две строки goto fail подряд. Первая из них корректно связывается с оператором if , а вторая вообще не имеет никакого отношения к делу. В результате, выполнение программы всегда завершается на этом этапе, со второго goto fail . Значение err содержит правильное значение, потому что операция обновления SHA1 была успешной и верификация подписи всегда даёт «добро».
Речь идёт о проверке подписи в сообщении ServerKeyExchange, что используется в шифрах DHE и ECDHE для передачи одноразового ключа соединения. Сервер говорит: «Вот одноразовый ключ, а вот подпись от моего сертификата, так что ты знаешь, что ключ от меня». В случае с Apple, если связь между одноразовым ключом и сертификатом сломана, то вся система разваливается. Теперь вообще ничего не работает: можно отправить клиенту правильный сертификат, но подписать рукопожатие произвольным секретным ключом, или вообще его не подписывать! Отсутствуют любые доказательства, что сервер, который присылает сертификат, вообще владеет секретным ключом для этого сертификата.
Уязвимость, вероятно, присутствует во всех версиях iOS до 7.0.5 и в OS X до 10.9.1 включительно.
Источник
Understanding the Apple ‘goto fail;’ vulnerability
Posted by Synopsys Editorial Team on Tuesday, February 25, 2014
Learn more about the Apple “goto fail;” vulnerability, including vulnerability details, who it affects, and what you can do about it.
You may have heard about the recently publicly disclosed vulnerability in Apple iOS. Let’s take a look at the goto fail vulnerability details as well as who is affected.
Vulnerability details
As the code at http://opensource.apple.com/source/Security/Security-55471/libsecurity_ssl/lib/sslKeyExchange.c shows, there is a bug in the implementation of the SSLVerifySignedServerKeyExchange function. Although the goto fail vulnerability has been discussed in many other places, let’s take a quick look at it here:
The issue is the two consecutive goto fail; statements. Although the indentation of the lines makes it appear as though they’ll both get executed only if the predicate in the if-statement is true, the second one gets executed regardless of whether the predicate is true or false. If the indentation is corrected, the problem becomes more obvious:
Since the SSLHashSHA1.update call will generally not return an error, the value of err will almost always be zero when the second goto fail; statement is executed. And what happens when goto fail is executed?
The return value of zero is provided to the caller, who believes that the signature verification on the “Server Key Exchange” message passed.
Who is affected?
Everybody running recent versions of iOS and Mac OS X seems to be affected. The bug is in code that verifies the signature on the “Server Key Exchange” message in the SSL/TLS protocol when a version of SSL/TLS older than TLS 1.2 is used. The code is called from:
This code will only be executed if an Ephemeral Diffie-Hellman cipher suite is chosen for communication. Also, as you can see above, if TLSv1.2 is used, a different version of the function is executed, which does not have this vulnerability.
However, this vulnerability enables man-in-the-middle attacks for all SSL/TLS connections initiated by affected devices. I’m not going to discuss the details of how the SSL/TLS protocol works, but at a high level, here are the steps that get executed:
- The client sends a list of cipher suites that it supports to the server.
- The server selects the cipher suite it wants to use back to the client. If an Ephemeral Diffie Hellman cipher suite is chosen, the server also provides its certificate and Diffie-Hellman parameters signed using the private key corresponding to its certificate.
- The client verifies the signature on the Diffie-Hellman parameters provided by the server, and then generates its Diffie-Hellman parameter and sends it to the server. If a client certificate is used, this value is signed by the client.
- The client and server generate a session key using the Diffie-Hellman parameters.
- The client and server exchange hashes of all handshake messages over a channel protected using the session key. This is meant to protect against man-in-the-middle attackers modifying otherwise unprotected handshake messages in transit.
Let’s consider the case where an Ephemeral Diffie Hellman cipher suite is not selected by the server. The attacker can replace the cipher suite selected by the server, leave the server’s certificate unmodified, and include a “Server Key Exchange” message with Diffie-Hellman parameters chosen by the attacker. The client will verify the server’s certificate, but will skip verifying the Diffie-Hellman parameters’ signature due to the vulnerability discussed in the previous section. The client will then generate its own Diffie-Hellman parameter and send it to the server; this value will be intercepted by the attacker. At this point, the attacker and the client will generate the same session key (because of how the Diffie-Hellman protocol works) and will exchange hashes of handshake messages. The client will have failed to verify that the Diffie-Hellman parameters provided to it were actually provided by the server whose certificate it received. The attacker can optionally also establish a SSL/TLS connection with the server and proxy traffic between the client and the server.
The same type of man-in-the-middle attack will work if the server selects TLS v1.2 as well. The attacker can cause the client to fall back to TLS v1.1 where the vulnerable code will be executed.
How did this happen?
This is an interesting question. There’s evidence of copied and pasted code in several places in the vulnerable file. For example, note the logging statement in the first screenshot in this blog entry. It’s clear that the code was copied from SSLDecodeSignedServerKeyExchange to SSLVerifySignedServerKeyExchange . It is possible that the developer copied and pasted some code on top of some existing code, but forgot to select one line in the code they were replacing.
How could this have been prevented?
There are several ways in which this problem could have been prevented. Let’s take a look at some of them.
Writing/compiling code
Several people have pointed out the use of goto in the code. Although this is generally a bad practice, I tried modifying similar code and using “better” coding constructs instead. I never got a compiler error, and the code was not necessarily a lot easier to read. I don’t believe that the use of goto significantly contributed to this problem.
Reviewing code
Manual code reviews are a great way to catch these types of problems. The indentation issue does make the code more difficult to read. This is precisely why whenever I manually review code, I use the IDE to automatically fix indentation before I start looking at it. This doesn’t guarantee that the reviewer will catch every problem, but it does make code easier to read and understand. If you perform manual code reviews, I would highly recommend doing this.
Testing
If you’re implementing security protocols, you need to have test cases that test every step of the protocol. Some commercial SSL/TLS fuzzing tools may have test cases for this problem already. If they don’t, I’m sure they will in the near future. Use these tools, or implement your own.
Protocol definition
I was thinking about whether this issue would have been a less severe problem if the SSL/TLS protocol worked slightly differently. For example, if the client sent its Diffie-Hellman parameters to the server encrypted with the server’s public key, this vulnerability wouldn’t have had any impact. The client’s Diffie-Hellman parameter would not be visible to the attacker, and so, the attacker couldn’t establish a SSL/TLS session with the client. This is of course only relevant if the server has a RSA key.
The client side always encrypts the pre-master secret using the server’s public key when RSA is used for key exchange. So why doesn’t it do it for Diffie-Hellman cipher suites? The only explanation I could come up with was that if the SSL/TLS implementation is correct, this is unnecessary and adds unnecessary overhead to the handshake. When Diffie-Hellman is used for key negotiation, the server already has to perform quite a bit of work; it has to generate Diffie-Hellman parameters, sign them, and then combine them with the client’s Diffie-Hellman parameter. These are all slow operations. Adding decryption of the client’s parameter would add one more slow operation to the protocol. Also, this wouldn’t work if the server had a DSA key.
What can you do about it?
End users should apply patches supplied by Apple as soon as possible. If you have an iOS app, you can use the SSLSetEnabledCiphers function to disable Ephemeral Diffie-Hellman cipher suites on the client side in the short term. Of course, this is only helpful if your users are likely to install your app update sooner than Apple’s security patch. Also, you should re-enable the Ephemeral Diffie-Hellman cipher suites once most of your users have applied Apple’s security patch (in a few weeks to a month). These cipher suites provide forward secrecy, which is a good thing. So don’t leave them disabled for too long. Unfortunately, there’s nothing you can do on the server side to mitigate this issue. So people accessing your website from unpatched iOS / Mac OS X devices will be vulnerable.
If you have a custom security protocol implementation, make sure you review and test it thoroughly! You just saw how a single line of code can cause your implementation to be completely broken.
Источник
«goto fail;» considered harmful
The primary benefit from subscribing to LWN is helping to keep us publishing, but, beyond that, subscribers get immediate access to all site content and access to a number of extra site features. Please sign up today!
A serious flaw in the way Apple’s iOS and OS X verify the keys in an HTTPS connection has been a major black eye for the company. The problem is in some of the open-source code that the company releases, so we can actually see the problem—it is eye-opening to be sure. The bug should have been fairly obvious from code inspection/review or could have been found with some intensive testing, so the fact that it went undetected—at least publicly—for so long is rather amazing.
The problem exists in Apple’s Secure Transport API that provides access to SSL/TLS services for both OS X and iOS. It was first introduced in iOS 6, which was released in September 2012, and in OS X 10.9, which was released in October 2013. Updates to iOS 6 and 7, as well as to OS X 10.9, have been released, though the OS X problem went unfixed for several days after the problem was disclosed—which was deemed irresponsible by several observers.
Looking at the code in question should make it quickly apparent to those with even limited knowledge of C that something is amiss. In a function called SSLVerifySignedServerKeyExchange() is the following code: The second «goto fail;» after the SSLHashSHA1.update() call for &signedParams is a bug. While it is indented to seem like it depends on the preceding if statement, that is not the case. There are no curly braces to turn it into a multi-statement if, so the second goto is unconditionally executed, which skips the rest of the signature verification.
But «fail» isn’t quite accurate here. If it had been, the problem would presumably have been noticed quickly as many HTTPS servers would not have passed muster. Instead, the code at the fail label just cleans up a few things and returns err, which is likely to be zero, since the update() probably did not fail. That means that instead of verifying the signed key that the server sent over, the function will just succeed—for any key offered.
The key in question here is the ephemeral session key that is exchanged using the Diffie-Hellman and Elliptic-curve Diffie-Hellman ephemeral (DHE and ECDHE) key exchange protocols. DHE and ECDHE are used to provide forward secrecy. That key should be signed by the private key corresponding to the public key in the server’s certificate. The signature is the proof that the server is actually in possession of that private key—without it, the link between certificate and identity (loosely defined) is broken. The bug allows any signature (thus any key) to validate. That means that a malicious server could use any certificate to spoof that site with impunity—it doesn’t need to sign the ephemeral key with the private key it does not possess.
Google’s Adam Langley has a nice analysis of the bug. As he noted, servers get to choose what cipher suites they support, so an attacker can force clients to use DHE or ECDHE to trigger the bug (if the client refuses to use one of those, it can’t connect at all). The most recent revision of Transport Layer Security (TLS), 1.2, is not affected because the API uses a different function to verify those keys. But earlier versions of TLS and all versions of its predecessor, Secure Sockets Layer (SSL), are affected. Clients could work around the bug by requiring TLS 1.2 (or, less preferably, by disabling the DHE/ECDHE cipher suites)—that would mean they couldn’t connect to some servers, perhaps, but they wouldn’t run afoul of this problem either.
Evidently, code inspection/review did not turn up this bug (there is some speculation by John Gruber that it is the result of a botched merge). What is perhaps more surprising is that no testing with invalid signatures on the ephemeral keys was done. Langley, who works on the Chrome/Chromium browser, noted that the condition is kind of difficult to test for, because that exchange happens well into TLS/SSL handshake. On the other hand, Gruber also speculated that the NSA may well have known about the flaw from its testing, given that it added Apple to the list of companies participating in the PRISM surveillance program shortly after iOS 6 was released.
It is tempting to recite «Linus’s Law» («given enough eyeballs, all bugs are shallow») and believe that this kind of thing could never happen in free software. Tempting, but wrong. The truth of the matter is that plenty of free software only gets cursory (or no) code review, so something like this could slip through. In this case, Apple’s code was available and no one ever publicly complained about it.
As Langley noted, compilers don’t generally complain about unreachable code, which is unfortunate, for sure, but warnings tend to have a high false-positive rate, so they are ignored—or suppressed. Code that implements security protocols clearly needs a higher level of scrutiny, though, so one would hope warnings are actually being used by Apple (and OpenSSL, OpenSSH, . ). An incident like this is clear evidence that delivering bug-free code is a never-ending battle.
Index entries for this article | |
---|---|
Security | Secure Sockets Layer (SSL) |
(Log in to post comments)
«goto fail;» considered harmful
Posted Feb 27, 2014 5:45 UTC (Thu) by flewellyn (subscriber, #5047) [Link]
Источник