Apple OSX Mavericks 10.9.x SSL Key Exchange Verification Vulnerability (CVE-2014-1266)
SektionEins released a quick and dirty experimental fix for this vulnerability.
The Vulnerability
Yesterday Apple released iOS 7.0.6 and iOS 6.1.6. Both fix a serious security flaw (CVE-2014-1266) in the SSL handling code inside the Security.framework. The flaw is very serious because it totally compromises the security of SSL and allows for man in the middle attack on otherwise secure SSL connections without any warning on the client side.
Unfortunately it has been discovered that this vulnerability is also present in OSX Mavericks. When you look at the following code snippet that is taken from Security.framework's sslKeyExchange.c you can spot a superfluous "goto fail;" statement. This statement is executed in all cases and completely bypasses the call to sslRawVerify. This means there is actually no verification performed on the signed server key exchange.
static OSStatus SSLVerifySignedServerKeyExchange(SSLContext *ctx, bool isRsa, SSLBuffer signedParams, uint8_t *signature, UInt16 signatureLen) { ... if ((err = ReadyHash(&SSLHashSHA1, &hashCtx)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &clientRandom)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0) goto fail; goto fail; <---- *** DANGER *** if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0) goto fail; err = sslRawVerify(ctx, ctx->peerPubKey, dataToSign, /* plaintext */ dataToSignLen, /* plaintext length */ signature, signatureLen); ... fail: SSLFreeBuffer(&signedHashes); SSLFreeBuffer(&hashCtx); return err; }
You can read more information about this vulnerability over at ImperialViolet.
The Patch
Because Apple decided to just release updates for iOS and leave OSX Mavericks users vulnerable over a weekend, we have looked into this issue and created a little binary patch that fixes this vulnerability by re-adding the removed code.
This is of course just a quick and dirty solution to test the impact of this vulnerability. You should not attempt to run this on production systems. And don't forget that we only patch the 64bit version of the Security.framework. If your code is 32bit you have to port the fix to 32bit.
.text # # This is the original code inside the Security.framework binary # #__text:0000000000086C3B lea r15, _SSLHashSHA1 #__text:0000000000086C42 lea rsi, [rbp+var_C8] #__text:0000000000086C49 mov rdi, r15 #__text:0000000000086C4C call _ReadyHash #__text:0000000000086C51 mov ebx, eax #__text:0000000000086C53 test ebx, ebx #__text:0000000000086C55 jnz short loc_86C9C #__text:0000000000086C57 mov r14, [r15+18h] #__text:0000000000086C5B lea rdi, [rbp+var_C8] #__text:0000000000086C62 lea rsi, [rbp+var_D8] #__text:0000000000086C69 call r14 #__text:0000000000086C6C mov ebx, eax #__text:0000000000086C6E test ebx, ebx #__text:0000000000086C70 jnz short loc_86C9C #__text:0000000000086C72 lea rdi, [rbp+var_C8] #__text:0000000000086C79 lea rsi, [rbp+var_E8] #__text:0000000000086C80 call r14 #__text:0000000000086C83 mov ebx, eax #__text:0000000000086C85 test ebx, ebx #__text:0000000000086C87 jnz short loc_86C9C #__text:0000000000086C89 lea rdi, [rbp+var_C8] #__text:0000000000086C90 lea rsi, [rbp+var_A8] #__text:0000000000086C97 call r14 #__text:0000000000086C9A mov ebx, eax # we insert the hook at 0x86c90 lea -0xa8(%rbp), %rsi # signedParams call *%r14 # SSLHashSHA1.update mov %eax, %ebx test %ebx, %ebx jnz 1f lea -0xc8(%rbp), %rdi # hashCtx lea -0xb8(%rbp), %rsi # hashOut call *0x20(%r15) # SSLHashSHA1.final mov %eax, %ebx test %ebx, %ebx jnz 1f mov -0x1e0(%rbp), %r8 # signature xor %rsi, %rsi inc %rsi inc %rsi mov %r8, %rdi sub %rsi, %rdi call _SSLDecodeInt cwde cdqe mov %rax, %r9 # signatureLen mov %r12, %rdi # ctx mov +0x78(%rdi), %rsi # ctx->peerPubKey mov -0xb0(%rbp), %rdx # dataToSign from hashOut.data mov $20, %rcx # SSL_SHA1_DIGEST_LEN cmpb $0, -0x1a8(%rbp) # isRsa jz 2f sub $16, %rdx # Need MD5 so pos-SSL_MD5_DIGEST_LEN mov $36, %rcx # dataToSignLen = SSL_SHA1_DIGEST_LEN + SSL_MD5_DIGEST_LEN 2: call _sslRawVerify jmp label_86C9A 1: jmp label_86C9C
Download
Please understand that we will not provide further help with applying the patch below. We strongly consider this patch experimental and you should only apply it to your systems if you understand the risk.
Due to popular request we have made the patch a little bit easier to use. Please download the following archive. Double Click to unpack it. Then the usual Ctrl-Click-Open to execute CVE-2014-1266-Patcher.command. This will look like the following.
Download Archive I KNOW WHAT I AM DOING I AM AWARE OF THE RISK
Security.framwork Patcher Patches a Critical SSL Vulnerability in Mac OSX 10.9.1 (CVE-2014-1266) ---------------------------------------------------------------------- Use with caution and at your own risk of breaking your system. Enter uppercase "YES" if you REALLY want to do this: YES [-] This script was not executed as the root user. We therefore cannot patch the Security Framework [!] We will try to re-execute ourselves with 'sudo' [!] You have to enter your password to allow this. [!] checking the Security Framework. [!] creating a backup copy of the Security Framework. [+] backup created now checking if it is okay. [+] Applying the patch. [+] Writing the patched file to disk. [+] Verifying patched file on disk. [+] Replacing the Security.framework. [!] This is a critical step. Lets pray everything works. [+] Verifying one last time. [+] DONE. We suggest you reboot your system now.
Patch in Action
The following images show the patch in action on a VMWARE installation of OSX Mavericks 10.9.1.