RubyGems 导航菜单
指南

如何构建和安装加密签名的 gems - 以及其他安全问题。

安全实践正在积极讨论中。请经常回来查看。

一般

安装 gem 允许该 gem 的代码在你的应用程序上下文中运行。显然,这会带来安全隐患:在服务器上安装恶意 gem 最终会导致该服务器被 gem 作者完全渗透。因此,gem 代码的安全是 Ruby 社区内积极讨论的话题。

RubyGems 从 0.8.11 版本开始就具备了 对 gem 进行加密签名 的功能。这种签名方式使用 gem cert 命令创建密钥对,然后将签名数据打包到 gem 本身。 gem install 命令可以选择设置安全策略,您可以在安装 gem 之前验证其签名密钥。

然而,这种保护 gem 的方法并没有得到广泛使用。它需要开发人员进行一些 手动步骤,而且 gem 签名密钥没有完善的信任链。关于 X509 和 OpenPGP 等新签名模型的讨论正在 rubygems-trust wikiRubyGems-Developers 列表IRC 上进行。目标是改进(或替换)签名系统,使其对作者来说易于使用,对用户来说透明。

使用 Gems

使用信任策略安装。

  • gem install gemname -P HighSecurity: 所有依赖的 gem 必须经过签名和验证。

  • gem install gemname -P MediumSecurity: 所有经过签名的依赖 gem 必须经过验证。

  • bundle --trust-policy MediumSecurity: 与上面相同,只是 Bundler 仅识别较长的 --trust-policy 标志,不识别较短的 -P 标志。

  • 注意:Gem 证书在全局范围内受信任,因此添加一个 cert.pem 文件用于一个 gem 会自动信任所有使用该证书签名的 gem。

验证校验和(如果可用)。

gem fetch gemname -v version
ruby -rdigest/sha2 -e "puts Digest::SHA512.new.hexdigest(File.read('gemname-version.gem'))"

了解被攻击的风险,如 Benjamin Smith 的 Hacking with Gems 演讲 中所述。

构建 Gems

使用 gem cert 签名。

1) 创建自签名 gem 证书

cd ~/.ssh
gem cert --build [email protected]
chmod 600 gem-p*
  • 使用您在 gemspec 中指定的电子邮件地址。

2) 使用证书配置 gemspec

将证书公钥添加到您的仓库。

cd /path/to/your/gem
mkdir certs
cp ~/.ssh/gem-public_cert.pem certs/yourhandle.pem
git add certs/yourhandle.pem

将证书路径添加到您的 gemspec。

s.cert_chain  = ['certs/yourhandle.pem']
s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/

3) 将您自己的证书添加到您的批准列表中,就像其他人一样。

gem cert --add certs/yourhandle.pem

4) 构建 gem 并测试您是否可以安装它。

gem build gemname.gemspec
gem install gemname-version.gem -P HighSecurity
# or -P MediumSecurity if your gem depends on unsigned gems

5) 安装文档的示例文本

MetricFu 经过加密签名。为了确保您安装的 gem 未被篡改

将我的公钥(如果您还没有)添加为受信任的证书

gem cert --add <(curl -Ls https://raw.github.com/metricfu/metric_fu/master/certs/bf4.pem)

gem install metric_fu -P MediumSecurity

MediumSecurity 信任配置文件将验证已签名的 gem,但允许安装未签名的依赖项。

这是必要的,因为并非所有 MetricFu 的依赖项都经过签名,因此我们无法使用 HighSecurity。


在您的仓库中包含已发布 gem 的校验和。

require 'digest/sha2'
built_gem_path = 'pkg/gemname-version.gem'
checksum = Digest::SHA512.new.hexdigest(File.read(built_gem_path))
checksum_path = 'checksum/gemname-version.gem.sha512'
File.open(checksum_path, 'w' ) {|f| f.write(checksum) }
# add and commit 'checksum_path'

有关详细信息,请参阅与 Yorick Peterse 的 讨论

报告安全漏洞

报告他人 gem 的安全漏洞

如果你在别人的 gem 中发现安全漏洞,第一步应该是检查它是否是一个已知的漏洞。一种方法是在 RubySec 上搜索相关公告。

如果看起来像一个新发现的漏洞,你应该私下联系作者(不要通过 pull request 或公共项目上的 issue),解释问题,如何利用它,以及理想情况下提供如何修复它的指示。

报告你自己的 gem 的安全漏洞

首先,通过电子邮件联系 这些地方之一 或通过在 GitHub 上创建 安全公告 来请求一个 CVE 标识符。这个标识符将使你在谈论漏洞时更容易地唯一识别它。

其次,弄清楚依赖你 gem 的人应该采取什么措施来解决漏洞。这可能包括发布一个你推荐他们升级的 gem 修补版本。

最后,你需要告诉人们这个漏洞。目前还没有一个专门的地方来广播这些信息,但一些好的开始地方可能是:

  • 发送电子邮件到几个列表,包括 [email protected][email protected][email protected],概述漏洞、它影响的 gem 版本以及依赖 gem 的人应该采取的行动。确保使用一个主题,其中包含 gem 名称、漏洞的简短摘要以及 CVE ID(如果有)。

  • 将其添加到 ruby-advisory-db。你可以按照 CONTRIBUTING 指南提交一个 pull request 来完成此操作。

致谢

本指南的内容参考了多个来源