由苹果的低级Bug想到的
2014年2月22日,在这个“这么二”的日子里,苹果公司推送了 iOS 7.0.6(版本号11B651)修复了 SSL 连接验证的一个 bug。官方网页在这里:http://support.apple.com/kb/HT6147,网页中如下描述:
Impact: An attacker with a privileged network position may capture or modify data in sessions protected by SSL/TLS
Description: Secure Transport failed to validate the authenticity of the connection. This issue was addressed by restoring missing validation steps.
也就是说,这个bug会引起中间人攻击,bug的描述中说,这个问题是因为miss了对连接认证的合法性检查的步骤。
这里多说一句,一旦网上发生任何的和SSL/TL相关的bug或安全问题,不管是做为用户,还是做为程序员的你,你一定要高度重视起来。因为这个网络通信的加密协议被广泛的应用在很多很多最最需要安全的地方,如果SSL/TLS有问题的话,意味着这个世界的计算机安全体系的崩溃。
目录
Bug的代码原因
Adam Langley的《Apple’s SSL/TLS bug 》的博文暴出了这个bug的细节。(在苹果的开源网站上,通过查看苹果的和SSL/TLS有关的代码变更,我们可以在文件sslKeyExchange.c中找到下面的代码)
static OSStatus SSLVerifySignedServerKeyExchange(SSLContext *ctx, bool isRsa, SSLBuffer signedParams, uint8_t *signature, UInt16 signatureLen) { OSStatus err; ... if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0) goto fail; goto fail; if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0) goto fail; err = sslRawVerify(ctx, ctx->peerPubKey, dataToSign, /* plaintext */ dataToSignLen, /* plaintext length */ signature, signatureLen); if(err) { sslErrorLog("SSLDecodeSignedServerKeyExchange: sslRawVerify " "returned %d\n", (int)err); goto fail; } fail: SSLFreeBuffer(&signedHashes); SSLFreeBuffer(&hashCtx); return err; }
注意,我高亮的地方,也就是那里有两个goto fail; 因为if语句没有加大括号,所以,只有第一个goto是属于if的,而第二个goto则是永远都会被执行到的(注:这里不是Python是C语言,缩进不代表这个语句属于同一个语句块)。也就是说,就算是前面的if检查都失败了(err == 0),也会goto fail。我们可以看到fail标签中释放完内存后就会return err;
你想一下,这段程序在SSLHashSHA1.update() 返回成功,也就是返回0 的时候会发生什么样的事?是的,真正干活的 sslRawVerify()被bypass了。而且这个函数SSLVerifySignedServerKeyExchange() 还返回了0,也就是成功了!尼玛!你可能想到宝酷网上之前《一个空格引发的惨剧》的文章。都是低级bug。
这个低级bug在这个周末在网上被炒翻了天,你可以上Twiter上看看#gotofail的标签的盛况。Goto Fail必然会成为历史上的一个经典事件。
如果你喜欢XKCD,你一定会想到这个漫画: