BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

前车之鉴:苹果的GoToFail Bug

| 作者 Sergio De Simone 关注 14 他的粉丝 ,译者 刘君 关注 0 他的粉丝 发布于 2014年3月13日. 估计阅读时间: 8 分钟 | 如何结合区块链技术,帮助企业降本增效?让我们深度了解几个成功的案例。

新近发现的iOS和OS X安全缺陷揭示出编码规范、单元测试、系统测试、代码复查方案、错误管理策略和工具部署方面的缺陷冰山。

ZDNet的Larry Seltzer 称这一缺陷“震撼且尴尬”,苹果同时为iOS 6发布补丁更是从侧面证实了其严重性。“苹果并不愿意iOS用户继续使用iOS 6系统,但尽管如此,他们还是修复了缺陷。这足以说明其严重程度。”Larry说。

到这篇文章完成时,苹果已经为iOS和OS X发布了软件更新,用以修复该问题:一个能让攻击者拦截、获取并修改加密数据的通信漏洞。但从这个故事中,我们还是能够学到某些东西。

谷歌的Adam Langley解释说,这一缺陷位于苹果开源发布的SSL/TLS协议实现——SecureTransport框架中,缺陷的引发原因在于部分代码不可达。试看如下代码:

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;
	...

fail:
	SSLFreeBuffer(&signedHashes);
	SSLFreeBuffer(&hashCtx);
	return err;
}

注意其中有两个连续的goto fail语句。由于if语句没有加大括号,因此执行时,第二处goto fail会让程序直接跳转到fail标签,从而避开if语句之后的验证。这会导致在跳转的那一刻err变量不含任何错误信息,方法也无法返回任何。Adam Langley继续解释道:

签名验证将检查ServerKeyExchange消息中的签名。DHE和ECDHE密文族将这一技术用于连接过程中的临时密钥交换。服务器发起请求:“这里是临时密钥和签名,你可以通过我的证书证实我是发起者。”如果这时临时密钥和证书链之间的关联被破坏,所有的验证都会失效。这种情况下虽然仍然可以向客户端发送正确的证书链,但握手过程可能用错误的私钥签名,甚至没有签名!我们无法证实服务器端是否持有与证书中公钥配对的私钥。

诚如Larry Seltzer所言,因为苹果没有给出更多细节,我们无从知道这一bug是如何被发现的,但这件事让他开始好奇苹果的代码复查实践。他还指出,虽然这个错误一眼就能够发现,但当你面对足有1970行长度的整个文件时,将其识别出来就会很难。

Twitter上#gotofail主题的很多评论者公然视“使用goto”为罪魁祸首,最著名的当属Dijkstra论文中对goto“有害”的定性。这点是无可争议的,荷兰代尔夫特理工大学的软件工程教授 Arie van Deursen试着通过返回错误代码这种惯用法实现一种类似C中的异常机制来解释goto的用法,这样一来,那种惯用法就成了罪魁祸首。

Van Deursen写道,实际上,返回错误代码惯用法普遍存在于含bug的文件中,并且本身存在一定的问题。2005年van Deursen与Magiel Bruntink,Tom Tourwe合著论文的主要成果之一就是,通过审查某相当规模的代码库发现“每千行代码中因为return-error-code惯用法而导致的缺陷密度达2.1”。 这么高的缺陷密度的罪魁祸首是未检查调用、未正确传播的返回值以及未正确处理的错误条件导致的,落实了“这一惯用法相当容易出错”的罪名。

苹果前职员Kevin Marks在van Deursen的跟帖后留言指出,可以使用预处理宏使返回错误代码的方式更安全。这方面的例子包括BailOSErr以及致力于实现C的异常机制方面的工作就是这样用的例子。

说起错误代码的管理,Chris Leishman在评论van Deursen观点时称,错误指示变量被初始化为success,这才是两行goto真正引发漏洞的主要原因。如果错误指示变量的初始化改为OSStatus err = OSUnknownError,系统执行会更安全。

另一方面,Plausible Labs的软件工程师Landon Fuller提供了bug所影响那部分代码的可测性分析并证实SSLVerifySignedServerKeyExchange能够进行隔离性单元测试。C. Keith Ray强调了TDD的一个观点:“如果你要编写一条if语句,那你必须事先准备一个调用这条语句的测试。你需要在条件为真和为假的情况下分别测试”。

Arie van Deursen指出这一事件还有更多值得争议的地方。

他最先注意到含bug的文件“明显不是自动规范化的,其中有大量格式不一的空格、制表符和代码注释”,而“正确的缩进能立刻显示正在发生的可疑事”,并让bug查找更容易。除此之外,他进一步建议“将编码格式作为一项安全特性”,而“将空格作为一项安全关注点”。

Langley在其博客中写道,他认为代码复查是防止这类问题发生的有效手段。但Arie van Deursen指出,先前微软有一项代码复查研究曾证实以下观点:

复查并不是像很多项目成员所想的那样,通常情况下都能找出缺陷;而找出深层、微妙或是“宏”层次的问题就更罕见了。也许依靠这种程度的代码复查来保证质量境况堪忧。

最后一点,这种情况下工具也没起到作用,如Langley所说,Clang的-Wall参数不会发现两行goto和其后的死代码。据Simon Nicolussi所言,Clang提供了能发现该问题的-Weverything标识,但GCC默认去除了这一标识。这点也为Peter Nelson——另一位特定-Wunreachable-code参数存在指出者所证实。Van Deursen指出主要问题在于死代码的删除从根本上讲是一个不可判定问题,这需要完备性和误报间的权衡,也正是因为这一原因,缺省情况下才不含不可达检验。

查看英文原文:Lessons Learned from Apple's GoToFail Bug


感谢邵思华对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ)或者腾讯微博(@InfoQ)关注我们,并与我们的编辑和其他读者朋友交流。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

“goto”恶习 by Ting Seno

对于使用“goto”习惯的同学,只能说“呵呵”;

虽然表现出来是goto惹得祸,但本质上不是goto语句的问题 by 林 大海

本质上是编码风格和测试管理不严格导致,至少有几类问题:
1、初始状态应该为:失败,而不是正常;(文中已提及)
2、错误没有使用异常机制,而是作为正常值的方式返回;(文中已提及)
3、if子句应该无条件使用{},而不允许使用单句;
4、大批量检查应考虑使用责任链模式,而不是并列if;
测试管理上也至少有:
1、自动构建工具没有进行一般性代码检查,如Style和这类基础性逻辑Bug;
2、单元测试用例没有进行覆盖性测试,估计也没有人去检查代码覆盖率;

明显IDE编译器的问题 by 黄 海平

不可达的代码还不报错,eclipse都比他强

微软的代码复审研究 by Wong Peter

复查并不是像很多项目成员所想的那样,通常情况下都能找出缺陷;而找出深层、微妙或是“宏”层次的问题就更罕见了。也许依靠这种程度的代码复查来保证质量境况堪忧。

微软的代码复审研究 by Wong Peter

复查并不是像很多项目成员所想的那样,通常情况下都能找出缺陷;而找出深层、微妙或是“宏”层次的问题就更罕见了。也许依靠这种程度的代码复查来保证质量境况堪忧。

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

5 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT