写点什么

前车之鉴:苹果的 GoToFail Bug

  • 2014-03-12
  • 本文字数:2344 字

    阅读完需:约 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 )关注我们,并与我们的编辑和其他读者朋友交流。

2014-03-12 08:063654

评论

发布
暂无评论
发现更多内容

Redis持久化机制

量贩潮汐·WholesaleTide

redis

揭秘区块链浏览器开发:从架构到落地的全链路指南

区块链软件开发推广运营

交易所开发 dapp开发 链游开发 公链开发 代币开发

JAVA实现读取最后几行日志

电子尖叫食人鱼

Java

报名|清华大学大数据产业论坛——航空航天专场

Apache IoTDB

Python打包

安信无限

Python 打包工具

解剖DeepSeek四把刀,一场深到源码,大到行业,细到人心的手术盛宴

京东科技开发者

欢迎新朋友,通义灵码 AI IDE 来了 | 附 QA 答疑

阿里云云效

ide 通义千问 通义灵码

狄耐克与鸿蒙生态深度战略合作 并启动“百城万户鸿蒙社区家庭战略”

新消费日报

在鸿蒙开发中实现自定义进度条

幽蓝计划

备战金九银十,Java面试题总结,苦战30天拿下高薪Java岗!

程序员高级码农

Java 程序员 java面试

做「长期主义者」的技术人们

京东科技开发者

如何在 DataGrip 中 连接 Databend

Databend

Spring AI Alibaba + Nacos 动态 MCP Server 代理方案

阿里巴巴云原生

阿里云 微服务 云原生 Spring AI Alibaba

Java面试题及答案整理(金九银十突击版)

Geek_Yin

Java 程序员 java面试 Java面试题

大数据-02-Hadoop集群 XML配置 超详细 core-site.xml hdfs-site.xml 3节点云服务器 2C4G HDFS Yarn MapRedece

武子康

大数据 hadoop mapreduce hive

1688寻原通API接口攻略

tbapi

1688寻原通 1688寻原通API 1688寻原通系统

11Labs 发布对话式 AI 2.0,集成话轮转换和知识库,多语言多角色多模态;通义公布空间音频生成模型 OmniAudio

声网

Taro on Harmony C-API 版本正式开源

京东科技开发者

欢迎新朋友,通义灵码 AI IDE 来了 | 附 QA 答疑

阿里巴巴云原生

ide 通义灵码

接口重试的7种常用方案!

量贩潮汐·WholesaleTide

php 服务器

一文简述:低代码是什么?低代码开发平台的分类、功能与构成

优秀

低代码 低代码开发平台 低代码平台

基于YOLOv8的坐姿标准姿态检测项目【完整源码数据集+PyQt5界面+完整训练流程+开箱即用!】

申公豹

yolo

区块链交易所开发:开启数字货币交易新时代

区块链软件开发推广运营

交易所开发 dapp开发 区块链开发 公链开发 代币开发

什么是链游,链游系统开发价格以及方案

区块链软件开发推广运营

交易所开发 dapp开发 链游开发 公链开发 代币开发

产品更新丨谷云科技ETLCloud 3.9.3 版本发布

谷云科技RestCloud

API 组件 ETL 数据集成工具

微店商品详情API接口指南

tbapi

微店商品API接口 微店API 微店详情接口

心怀热爱,共绽光芒——鲲鹏昇腾开发者大会 2025 印象记

猫头虎

鲲鹏 昇腾 昇腾AI 鲲鹏云 昇腾CNN

DeepSeek-R1-0528正式上线网心科技算力云平台

网心科技

工作三年Java程序员的一点点体会与建议

Geek_Yin

Java 程序员 java面试 Java面试题

Web前端入门:JavaScript 各种对象定义与对象取值方法

不在线第一只蜗牛

JavaScript 前端 Web

TextIn OCR Frontend前端开源组件库发布!

合合技术团队

人工智能 算法 #大数据

前车之鉴:苹果的GoToFail Bug_安全_Sergio De Simone_InfoQ精选文章