GLEP 58:Gentoo 软件分发安全 - 基础设施到用户分发 - 元清单

作者 Robin Hugh Johnson <[email protected]>
类型 标准跟踪
状态 已替换
版本 1
创建日期 2008-10-22
最后修改日期 2018-04-07
发布历史 2009-12-01, 2010-01-31
需要 44 60
被替换为 74
GLEP 源码 glep-0058.rst

摘要

元清单提供了一种从 Gentoo 基础设施到用户系统可验证分发的方法,同时通过扩展 Manifest2 规范,并添加一个支持其他嵌套清单的顶级清单文件,在完全不受信任的网络和系统上传输数据。

动机

作为全面安全计划的一部分,我们需要一种方法来证明源自 Gentoo 组织(读取 Gentoo 拥有的硬件,由基础设施运行)的内容没有被篡改。这允许使用第三方 rsync 镜像,而无需担心它们修改了关键内容(例如,仍然未签名的 eclasses)。

保护不受信任的分发是安全计划中较简单的任务之一 - 简而言之,只需要对树中的每个项目进行哈希处理,并对该哈希进行签名以证明它来自 Gentoo。

具有讽刺意味的是,我们有一个经过哈希和签名的分发版(只是大多数用户由于其缺点而没有使用它):我们的树快照 tarball 具有哈希和签名。

因此,我们现在希望将相同的验证添加到通过 rsync 分发的材料中。我们已经提供了树子集的哈希值 - 我们的清单保护单个软件包。但是,元数据、eclasses 和配置文件目前不受保护。软件包和 distfile 的目录不包括在内,因为它们不是通过 rsync 分发的。

树签名工作的这部分仅提供以下保证:用户可以证明来自 Gentoo 基础设施的树自离开 Gentoo 基础设施后没有被篡改。不提供任何其他明示或暗示的保证。

此外,从受信任的来源分发一组最新的元清单允许验证来自社区镜像的树,并允许检测所有恶意镜像的情况(无论是通过故意延迟、重放 [C08a][C08b] 还是更改)。

规范

由于缺乏更好的名称,以下解决方案应称为元清单。负责命名的人员已被解雇。

元清单基本上包含树中每个文件的哈希值,无论是直接还是间接。直接情况适用于任何未出现在现有清单文件中的文件(例如,eclasses、清单文件本身)。间接情况由现有清单文件的内容涵盖。如果清单本身是正确的,我们知道通过跟踪清单的哈希值,我们可以确保内容受到保护。

在以下内容中,元清单文件是一个名为“Manifest”的文件,位于存储库的根目录。

创建元清单文件的步骤

总结

创建元清单文件(s) 的目的是确保树中的每个文件至少出现在一个清单中。

流程

  1. 从 Gentoo Portage 树的根目录开始(gentoo-x86,尽管此过程也适用于覆盖层)。
  2. 初始化两个无序集合:COVERED、ALL。
    1. “ALL”应包含当前树中存在的每个文件。
    2. “COVERED”应包含现有 Manifest2 中提到的每个文件。如果一个文件在 Manifest2 中被提及,但不存在,它仍然必须包含在内。不应排除任何文件。
  3. 遍历树,深度优先。
    1. 仅在顶层忽略以下目录:distfiles、packages、local。
    2. 如果一个目录包含一个清单文件,则从中提取所有相关的本地文件(目前:AUX、MISC、EBUILD;但应遵循 [GLEP60] 中 Manifest2 条目类型的演变),并将它们放入 COVERED 集合中。
    3. 根据 [GLEP60] 中提到的排除列表,递归地将目录中的每个文件添加到 ALL 集合中。
  4. 生成一个新的集合 UNCOVERED,作为集合差 (ALL)-(COVERED)。这是不受其他清单或排除列表涵盖的每个项目。
  5. 如果存在现有的元清单文件,请将其删除。
  6. 对于 UNCOVERED 中的每个文件,分配一个 Manifest2 类型,生成哈希值,并将其与文件类型一起添加到元清单文件中。
  7. 为了唯一地识别元清单,应包含一个标题行,使用 metadata/timestamp.x 文件的精确内容,以便可以将元清单与 rsync 镜像系统分发的树关联起来。应包含“metadata/timestamp.x”字符串以识别此版本的元清单生成。例如:“Timestamp: metadata/timestamp.x: 1215722461 Thu Jul 10 20:41:01 2008 UTC”包管理器不得使用识别字符串作为文件名。
  8. 元清单最终必须使用 GnuPG 进行签名。
    1. 对于初始实现,与快照 tarball 签名使用的相同密钥就足够了。
    2. 对于将来,基础设施用于完全自动签名的密钥不应与开发人员密钥位于同一个密钥环上。有关详细信息,请参阅 [GLEPxx3]

注释

[GLEP33] 中包含的提案与上述内容不冲突,该提案重构了 eclasses 以包含子目录和清单文件,因为如果 [GLEP33] 重构得以实现,则上述清单规则仍然为所有文件提供间接验证。

需要其他级别的清单,例如每个类别,以及在 eclasses、配置文件和元数据目录中。这确保对单个文件的更改会导致清单在传播时发生尽可能小的总体更改。其他级别清单的创建使用与上述相同的过程,只是从不同的根点开始。

元清单生成将作为基础设施现有流程的一部分进行,该流程获取 CVS 的内容并将其准备通过 rsync 分发,包括生成元数据。此时不会验证树内清单文件,因为假定它们是正确的。

验证元清单中的一个或多个条目

这可能发生在两个时间点:首先,在 rsync 完成后立即 - 这具有内核文件缓存处于活动状态的优点,并且可以快速完成对整个树的检查。其次,应在安装软件包期间检查元清单。

验证元清单中条目的步骤

在以下内容中,我使用术语“M2-verify”来表示遵循 Manifest2 格式定义的哈希验证过程 - 包括检查文件长度以及哈希值是否匹配。在 [GLEP60] 中讨论了哪些文件类型可以在丢失时被忽略。

  1. 针对 Gentoo 自动密钥密钥环检查元清单上的 GnuPG 签名。有关 GnuPG 签名的完整验证详细信息,请参阅 [GLEPxx3]。1. 如果签名检查失败,则中止。
  2. 检查时间戳标题。如果它与本地时钟或受信任来源相比明显过时,则停止或需要用户手动干预。
  3. 对于 rsync 后树的验证
    1. 构建一个包含 rsync 覆盖的每个文件的集合“ALL”。(排除 distfiles/、packages/、local/)
    2. M2-verify 元清单中的每个条目,根据需要向下进入下级清单。将每个已检查条目的相对路径放入集合“COVERED”中。
    3. 通过 ALL 和 COVERED 集合之间的集合差构建集合“UNCOVERED”。
    4. 对于 UNCOVERED 集合中的每个文件,分配一个 Manifest2 文件类型。
    5. 如果 UNCOVERED 集合中任何文件的类型需要在出错时停止,则中止并显示合适的错误。
    6. 已完成验证
  4. 如果在安装软件包时进行检查
    1. M2-verify 元清单中清单的条目
    2. 如果以任何方式使用 metadata/,则 M2-verify 所有相关的 metadata/ 内容(可选地在依赖项检查之前完成)。
    3. M2-verify 清单的内容。
    4. 执行 ebuild 直接或间接使用的所有 eclasses 和配置文件的 M2-verify。

注释

  1. 对于初始实现,可以检查 eclass 和配置文件目录中的每个项目,而不是跟踪每个 eclass 使用的确切文件(请参阅注释 #2)。以后的实现应努力仅根据需要验证单个 eclasses 和配置文件。
  2. 确切文件的跟踪对于 libtool eclass 具有特殊的意义,因为它将补丁存储在 eclass/ELT-patches 下,因此不会被 inherit 函数的任何跟踪捕获。这可以通过以后的 eclass 和 ebuild 变量来缓解,该变量明确声明树中的哪些文件被软件包使用。

实施说明

对于树签名工作的这部分,单个 Gentoo 开发人员无需执行任何操作。他们将继续像现在一样进行开发和提交,元清单由基础设施在树生成过程中添加,并分发给用户。

生成清单文件和元清单文件的任何脚本都可能会发现并行生成多个级别的清单文件非常有用,并且这是明确允许的,前提是树中的每个文件都至少包含在一个清单文件或元清单文件中。最上层的清单文件(元清单文件)是唯一一个不在任何其他清单文件中出现的项目,而是使用 GPG 签名以启用其验证。

元清单和新的 Manifest2 文件类型

虽然[GLEP60] 描述了添加新的文件类型,但这些对于元清单提案的实现**并非**必需。如果没有新的文件类型,元清单中的所有条目都将是 'MISC' 类型。

时间戳和元清单的其他分发

[C08a][C08b] 中所讨论的,恶意第三方镜像可能会利用排除和重放的原理来拒绝向客户端提供更新,同时记录客户端的身份以进行攻击。

应该通过在元清单文件的头部包含时间戳,以及通过可信渠道分发最新的元清单文件来防止这种情况。

在由 Gentoo 基础设施直接维护的所有 rsync 镜像上(社区镜像除外),应该有一个新的模块 'gentoo-portage-metamanifests'。在这个模块中,应该保留最近一段时间(例如一周)的所有元清单文件,命名为 "MetaManifest.$TS",其中 $TS 是文件内部的时间戳。最新的元清单文件应该始终被符号链接为 MetaManifest.current。还应该探索通过 HTTPS 提供最近的元清单文件的可能性,以减轻中间人攻击。

包管理器应该获取 MetaManifest.current 并使用它来确定树是否过时(根据验证过程的操作 #2)。关于新旧程度的决定应该是一个用户配置设置,并且可以覆盖。

元清单大小注意事项

如果只有两个级别的清单文件(每个包一个,顶级一个),那么每次 rsync 都会导致大量流量来传输修改后的顶级元清单文件。为了减少这种情况,需要第一级目录清单文件。或者,如果分发方法能够有效地处理现有文件中小的补丁式更改,那么使用未压缩的元清单文件可能是可以接受的(这主要用于分布式版本控制系统)。欢迎提出其他减少此流量的建议。

向后兼容性

  • 没有向后兼容性问题,因为旧版本的 Portage 不会在树的顶级查找清单文件。
  • 支持 Manifest2 的 Portage 版本会忽略所有它们不确定如何处理的条目。使标题和 PGP 签名能够轻松进行。

致谢

我要感谢以下人员对这个 GLEP 的投入。

  • Patrick Lauer (patrick):督促我完成所有树签名工作,并帮助编辑。
  • Ciaran McCreesh (ciaranm):Paludis Manifest2
  • Brian Harring (ferringb):pkgcore Manifest2
  • Marius Mauch (genone) & Zac Medico (zmedico):Portage Manifest2
  • Ned Ludd (solar) - 安全概念审查

参考文献

[C08a](1, 2) Cappos, J 等人。(2008)。“包管理安全”。亚利桑那大学技术报告 TR08-02。可在以下网址在线获取:ftp://ftp.cs.arizona.edu/reports/2008/TR08-02.pdf
[C08b](1, 2) Cappos, J 等人。(2008)。“对包管理器的攻击”可在以下网址在线获取:http://www.cs.arizona.edu/people/justin/packagemanagersecurity/
[GLEP33](1, 2) Eclass 重构/重新设计 https://gentoolinux.cn/glep/glep-0033.html
[GLEP60](1, 2, 3, 4) Manifest2 文件类型 https://gentoolinux.cn/glep/glep-0060.html
[GLEPxx2]关于开发流程安全的未来 GLEP。
[GLEPxx3](1, 2) 关于 GnuPG 策略和处理的未来 GLEP。