Debian/OpenSSL灾难的教训
发布于2008年5月21日星期三。
char buf[100]; fd=打开(“/dev/random”,O_RDONLY); n=读取(fd,buf,sizeof buf); 闭合(fd); RAND_add(buf,大小buf,n);
i=弗雷德(buf,1,n,in); 如果(i<=0)中断; /*即使n!= i、 使用完整数组*/ RAND_ad(buf,n,i);
char buf[100]; n=RAND_bytes(buf,大小buf);
#ifndef净化 MD_更新(&m,buf,j);/* purify投诉*/ #结尾
主题:随机数生成器、未初始化数据和valgrind。 日期:2006-05-01 19:14:00 使用 valgrind,它可以显示关于执行条件 基于统一值的跳跃。 这些统一化的价值观是 在随机数生成器中生成。 它添加了一个 池的未初始化缓冲区。 有问题的代码如下2 crypto/rand/md_rand.c中的代码片段: 247: MD_更新(&m,buf,j); 467: #ifndef净化 MD_更新(-m,buf,j);/* purify投诉*/ #结尾 由于瓦尔格林的工作方式(以及必须工作的方式) 首先使用单位化价值的地方,是 报告的错误可能完全不同,也可能是 很难找到问题所在。 ... 我目前认为最好的选择是实际发表意见 这两行代码。 但我不知道这有什么影响 真的对RNG有影响。我看到的唯一影响是游泳池 可能接收较少的熵。 但另一方面,我甚至没有 确定一些统一化数据的熵有多大。 你们觉得删除这两行代码怎么样?
列表:openssl-dev 主题:回复:随机数生成器、未初始化数据和valgrind。 日期:2006-05-01 22:34:12 >我目前认为最好的选择是实际发表意见 >这两行代码。 但我不知道这有什么影响 >真的对RNG有影响。我看到的唯一影响是游泳池 >可能会收到较少的熵。 但另一方面,我甚至没有 >确定一些统一化数据的熵有多大。 > 不多。 如果它有助于调试,我支持删除它们。 (然而,我最后一次检查时,瓦尔格林德报告了数千个虚假信息 错误消息。 情况好转了吗?)
列表:openssl-dev 主题:Re:随机数生成器,未初始化的数据和valgrind。 日期:2006-05-02 6:08:10 >不多。 如果它有助于调试,我支持删除它们。 >(然而,我最后一次检查时,瓦尔格林德报告了数千个虚假信息 >错误消息。 情况好转了吗?) 我最近用-DPURIFY=1在Debian上编译了vanilla OpenSSL 0.9.8a 带有valgrind版本3.1.1的GNU/Linux“sid”能够调试一些 应用程序同时使用TLS/SSL作为S/MIME而没有任何警告或错误 关于OpenSSL代码。 没有-DPURIFY你真的被淹没了 警告。 所以是的,我认为不要使用未初始化的内存(它只是一个 行,另一个事件已经被注释掉)帮助了valgrind。
OpenSSL代码太聪明了一半。 故意未初始化 内存引用模糊了代码并使其难以 测试真正的bug。 OpenSSL代码组织得不是很好。 两者都有代码 RAND_添加 和 RAND_字节 要更新 熵,而不是将该功能分解到一个位置。 一个实例并不重要,这让它看起来很像 就像另一个例子不重要一样。 OpenSSL代码的偏执隐藏了Debian引入的错误。 在每次调用时将pid放入熵池 随机字节(_B) 实际上并没有帮助创建熵,但它确实让bug继续存在 Debian版本完全确定。 如果它是完全确定的,那么bug 可能早就被注意到了,可能早在很久以前 它得到了稳定的释放。 Debian维护人员请求帮助处理他没有提供的代码 理解,但他在OpenSSL列表中的帖子片段 没有足够的上下文来理解 MD_更新 调用确实在代码中。 每次通话都要显示几行字 情况更清楚,因为这两个代码段看起来很漂亮 类似。 提及包含每个函数的函数名称 打电话可能会有帮助。 OpenSSL开发人员的响应可能不正确 没有真正查看代码以查看哪些调用 正在被谈论。 #ifdef PURIFY的存在 在一个电话上,很可能很容易假设另一个 电话也同样不重要。
尽量不要写聪明的代码。 尝试编写组织良好的代码。 不可避免的是,您将编写聪明、组织混乱的代码。 如果有人来问这个问题, 用它来表示代码可能太聪明了,或者 组织得不够好。 把它改写得更简单、更容易理解。 避免巫毒代码。 多次将变量归零,例如, 现在不影响正确性,但它确实使代码更难 理解并且容易在没有注意的情况下打破。 邮件列表讨论并不能替代真正的代码审查。 人们在疲倦或出门时回复电子邮件。 代码审查应该是彻底的和经过考虑的。 显示前后的并排文件差异 的版本 md_土地。 c(c) OpenSSL开发人员 因为真正的代码审查可能会发现错误。 Debian等发行版必须维护自己的 一些程序至少是暂时的。 这是不可避免的,因为 并非所有项目都会在Debian的时间限制下运行。 但我很惊讶OpenSSL开发人员没有跟进 一旦创建了补丁,就试图让他们接受它 主树。 这也可能引发代码审查。 如果失败了,我很惊讶Debian没有一个工程师 它是为了理解OpenSSL和其他安全关键代码 并在正式程序中审查当地的变化。
-
杰克·纳尔逊 (2008年5月21日上午6:32) “如果它有助于调试”甚至与“继续并删除它以进行生产部署”不太一样,并且这样描述它是虚伪的。
-
莱斯特 (2008年5月21日上午6:46) 另一种策略可能是对缓冲区中剩余的“未接触”字节进行异或。 这可能对每个人都有用。
-
俄罗斯考克斯 (2008年5月21日上午6:52) 这很有趣。 我读到的讨论是关于清理代码的生产版本,以便更容易调试。 直到你发表评论,我才注意到,但当然可以把讨论理解为只是为了调试而进行的临时更改。 这只是强调了邮件列表讨论不能替代代码审查。
-
托尼特曼 (2008年5月21日上午7:27) 首先,我不明白为什么Debian首先需要更改openssl。 也许我不理解这一部分。 其次,valgrid/purize是一个工具。 盲目地遵循这个或任何其他源代码分析工具的建议并不是任何真正的包开发人员上游的人的业务。 对不起的。 如果你不理解某事,不要改变它。 我以前曾与狂热者一起工作过,他们将Java源代码分析器当作武器使用。 这是一个笑话,他们是一个玩笑。 用你的头。 思考、思考、思考。 只是因为valgrind/prify说它做得不对。 Lint也是这样,其他所有源代码分析工具也是如此。
-
马赫特 (2008年5月21日上午7:50) 依赖魔法是一种不好的形式,不记录魔法是自杀。 一个简单的 //使用未初始化的数据作为熵 在有人过来说“让我们把堆归零”以获得额外的安全性之前,这会有所帮助。
-
乔什·里奇 (2008年5月21日上午8:03) 谢谢你的来信。 它很有趣,写得很好。 现在,我对盲目更新我的debian机器而不进行进一步挖掘并不感到难过。
-
贾斯汀·梅森 (2008年5月21日上午8:46) 很好地说明了“聪明代码”的危险性。 关于邮件列表不能很好地替代适当的代码审查——这是真的,但开源项目只是简单地使用列表,没有其他选择。 从经验来看,一个运行正常、成熟的开源项目可能会有跨越多个大洲的开发人员,鉴于此,这种并行代码审查的机会最多每隔几年就会出现一次。 也许随着基于谷歌Mondrian的开源代码审查工具的新趋势,我们可能很快就会推出一种比补丁和漏洞跟踪器或邮件列表更好的分布式代码审查机制。 希望在这里。 顺便说一句,我想指出,因为我在其他地方看到过一些评论,表明这种问题永远不会出现在专有软件中——遗憾的是,情况并非如此。 我曾在一些公司工作过,在那里旧软件进入了其生命周期的“维护阶段”,并立即被移交给了一个由刚起步的大学初级开发人员组成的团队,他们很少或根本没有提前接触过产品,对代码知识甚少,对如何系统地修复错误了解甚少, 并且没有与原始开发人员联系进行审查。 正如你可能想象的那样,结果有时是灾难性的。。。 但由于它是专有软件,它远没有开源领域偶尔发生的灾难那么明显。
-
加博 (2008年5月21日上午9:29) 另外,我们不要忘记这个补丁的原因:消除一些valgrind警告。 我认为debian不应该仅仅因为一些code-checker工具显示了一些警告就对包(尤其是如此重要的中央包)进行修补。 如果openssl会崩溃,或者以其他方式无法使用,那么好吧,做点什么吧。但只是为了一个警告? 简单地向上游提交补丁会是一个更好的解决方案。
-
杰夫·沃尔登 (2008年5月21日上午9:58) 不要编写过于聪明的代码是一个好主意,但更好的做法是确保您编写的每一段代码都有测试。 如果您知道什么是正确的行为,请确保该行为是可复制的,并且不会进入发布。 (请注意,即使对于随机性算法也可以这样做,尽管这是非确定性的,如 回归-211590.js 。这在这里可能会有效,尽管这可能不太可能。) 这并不是干净代码(更重要的是,干净API)的真正替代品,但至少现在或最终重写代码时不会倒退。
-
我们是Dave (2008年5月21日上午10:07) 托尼特曼、马赫特和加博都取得了优异的成绩。 还有两点尚未得到足够重视-- *OpenSSL的家伙们的“大教堂”态度——直接来自BSD魅力学校——必须承担一些责任。 每个项目都需要一个一站式反馈机制,由多个核心维护人员遵循。 像Debian维护者这样的超级用户是开源的alpha和omega; 把它们当作一种不方便的分心方式不仅是粗鲁的,而且是自我毁灭的。 *Debian对修补的态度仍然是一个等待发生的意外。 许多其他供应商也有类似的错误态度。 修补应该是分销商最终绝望的行为,而不是市场差异或政策问题。 如果您需要更改,请向上游提交,如果上游拒绝更改,请找出原因。
-
俄罗斯考克斯 (2008年5月21日上午10:39) @Jeff Walden:关于这个bug,最有趣和微妙的一点是PRNG会通过我能想象的任何单进程随机性测试。 (当然 回归-211590.js .) PRNG仍在生成一个单独的字节流,该字节流是加密随机的。 问题是,如果你运行它,我运行它,我们很有可能得到相同的字节流。 我很想知道一个看似合理的测试会发现这个问题。 我想不出一个。
-
山姆 (2008年5月21日下午4:29) 卢西亚诺偶然发现了这个错误:他需要为自己的一个项目生成许多素数,并对自己得到许多重复感到惊讶。
-
俄罗斯考克斯 (2008年5月21日下午4:40) @山姆:你有一个链接来描述卢西亚诺到底在做什么吗? 我相信你,但用一种显而易见的方法(使用一个过程)生成大量素数是不会出现这种情况的。
-
亚伦·丹尼 (2008年5月21日10:42 PM) 关于您不应该听取源代码分析工具的抱怨通常是正确的,但在这种特定情况下是错误的。 在C语言中,从未初始化的内存中读取会调用未定义的行为。 瓦尔格林德恰当地警告说,发生了令人难以置信的事情。
-
萨姆·霍泽瓦尔 (2008年5月22日凌晨1:43) @恐怕你必须向卢西亚诺询问细节。 我只有几天前关于#debian-devel的对话: 这是怎么发现的? 检查,还是有人两次生成了相同的密钥? <卢西亚诺>真的出了事故。 我需要很多素数。。。 0:-) 你每次都得到相同的数字? 塞塞,不是每次都这样:P
-
克拉根 (2008年5月22日凌晨3:01) 我看到很多评论指责库尔特想关闭瓦尔格林德 向上。 例如: >其次,valgrid[sic]/prify是一个工具。 盲目追随 >这个或任何其他源代码分析器工具的建议不是 >任何处于真实包裹上游的人的业务 >开发人员。 撇开Valgrind和Purify都没有分析源代码, 有一个很好的理由修改代码以关闭它:如果它 发出许多警告,但这些警告并不表示 程序,则无法使用它来查找实际错误。 Valgrind是一个 非常有用的工具,值得花点功夫来实现 工作,以及软件的生产版本的工作,尤其是 安全关键型软件,如OpenSSL,其中缓冲区溢出或 double-free可能会导致未经认证的远程磁孔。 我认为卢西亚诺正在生成一系列SSL证书。 这个 显而易见的方法是使用shell脚本; 我不知道 他就是这么做的。 他说他在 24小时生成证书!
-
克拉根 (2008年5月22日凌晨3:01) 哇,Blogger的评论真糟糕。 对此我很抱歉。
-
画 (2008年5月22日上午5:53) 最近github.com上的人也注意到了这一点,他们注意到看似无关的用户生成了相同的公共SSH密钥。 (此处简要提及。)
-
哑光 (2008年5月22日上午7:14) 将getpid()放入混合是(很可能)明智的设计决策,否则,如果程序派生()s并继续使用相同的池,那么子级和父级将生成相同的“随机”字节。
-
Resuna公司 (2008年5月22日上午7:31) 对我来说,最大的失败是没有记录你的聪明。 有时你必须聪明,使用聪明的代码,但你应该解释为什么要这样做。如果所有这些注释都是作者认为自己聪明的地方,并解释了原因,我宁愿阅读一段平均每个文件只有0.8条注释的代码。 如果你写了聪明的代码,就在评论中吹嘘它。 这将帮助一些不理解它的可怜的家伙,即使事实证明你并不聪明,他们也会更喜欢你,因为你解释了为什么它只是晦涩难懂的,所以他们知道简化它是否安全。五年后,这个“可怜的家伙”很可能就是你。 关于评论的评论: *中世纪的大教堂实际上是使用集市系统建造的。 结果他们中的许多人倒下了。 这个术语真的很可怕。 *我同意任何人的建议,如果一个调试工具告诉你你正在做一些愚蠢的事情,也许你是。 *Bug跟踪器是做这类事情的好地方。 当我在谷歌上搜索一个bug时,把我扔到了bug跟踪器的某个地方,我总是利用这个机会阅读一些类似的bug,因为我当时正在考虑这个问题,并根据需要添加评论和补丁。 *如果(a)您确定这是您最后一次分叉的地方,或者(b)您在分叉()之后再做,那么将getpid()放入混合中可能会很有用。
-
作记号 (2008年5月22日下午12:13) “另外,我们不要忘记这个补丁的原因:让一些valgrind警告沉默。 我认为debian不应该仅仅因为一些code-checker工具显示了一些警告就对包(尤其是如此重要的中央包)进行修补。 " 这里的问题不是关于OpenSSL的警告,而是当您在使用OpenSSL的软件上运行valgrind时,就会收到警告。 由于大量与OpenSSL相关的警告,因此很难看到软件的任何潜在问题。 这大概也是为什么“如果它有助于调试”被解释为可以在生产部署中使用的原因——它是OpenSSL的生产部署,可能用于调试某些客户端代码。
-
病毒的 (2008年5月23日上午10:00) 在这里,你们(所有人)谈谈如何评论代码。。。 我想加一些便士。。。 有一次我得到了一个很好的教训: -代码是问题的解决方案。 在注释中,如果您编写代码解决的问题是什么,这将有所帮助。 如果评论只解释了解决方案,那也没什么帮助。 对我来说,/*即使n!= i、 使用完整数组*/是冗余注释的另一个示例,而不是解释下一行解决的问题:使用缓冲区的未初始化部分增加熵,正如我们已经用RAND_add计算过的那样。 (如果我理解正确的话)
-
米 (2008年5月24日上午1:14) 2贾斯汀: 并排评审不仅是“并排坐在桌边”,而且是“新旧版本并排看”。 基本上,我认为在跨越多个大陆的开源团队中建立适当的软件审查流程没有任何问题。 1.发送补丁以供审查。 2.评审员对变更进行彻底检查,包括差异等,并对其进行评论。 3.寄件人处理意见。 重复第2和第3步,直到审核人明确批准。 4.发送方将代码提交到中继。 审核人的批准意味着他与发送者共同负责引入的任何错误。 我想知道,为什么像Debian这样的大人物仍然没有复习的想法。
-
米 (2008年5月24日上午1:18) 持续的。。 这不是一个工具的问题,这个过程可以用一个简单的差异来设置。我真的不知道障碍是什么。 顺便说一句,吉多·范·罗苏姆(Guido van Rossum)有一个蒙德里安克隆人,名叫里特维尔(Rietveld)。
-
怪物 (2009年8月8日上午11:13) 嘿,异常处理得很好。。 从未想过这样。。 很好。/。 www.spyfree.info。 你会得到更多的细节。。
-
欧文 (2011年4月19日上午7:26) 为什么没有人提到测试是这里的问题之一? 如果有一个测试生成了10万个密钥,并进行了一些统计分析,那么这个问题将有95%以上的几率被发现。