PyPI的安全隐患和实现安全Python生态系统的步骤介绍

671 阅读11分钟

作为Python开发者,我们依赖从Python Package Index (PyPI)等公共资源库中获取的软件包(及其依赖性)来构建我们的应用程序。结合其他第三方代码和我们自己的专有代码,PyPI来源的组件构成了我们软件供应链的关键部分--这个链条只有在最薄弱的环节上才会强大。为了构建强大的软件,我们需要确保链条上的所有环节都是安全的,没有任何漏洞。

幸运的是,Python软件基金会认识到了软件供应链安全的极端重要性。他们正在积极努力,通过采取一些重要的措施,成为PyPI生态系统的好管家,包括:

所有这些举措都是受欢迎的补充,为组织提供了更多的方法来帮助确保他们所使用的Python软件包的安全性和完整性。然而,一些常见的漏洞仍然没有得到解决,包括:

  • Typosquatting - 坏人上传被破坏的软件包的过程,其名称与流行的、现有的软件包相似(例如,urlib3与urllib3)。
  • 恶意软件 --不良行为者可以上传含有恶意代码的预构建二进制轮子
  • 依赖性混淆 --当开发者错误地从PyPI上安装了一个与他们组织内部的自定义包名称相同的受攻击的包时,就会发生这种情况。
  • 签名的软件包 --公平地说,没有一个开源的公共资源库提供签名,但这是确保软件包没有被篡改的唯一方法。

在这篇文章中,我们将讨论Python软件基金会为解决Python软件包的安全性和完整性而采取的举措,以及PyPI尚未解决的一些问题。最后,我们将提供一些工具和建议,以帮助你解决这些问题。

PyPI的安全改进

PyPI当然不是唯一一个受到坏人攻击的开源软件库,他们希望破坏自己的用户群。不幸的是,知名度带来了关注,而Python是目前最流行的编程语言之一。其结果是越来越多的黑客、妥协和漏洞,包括:

在一种流行的语言周围有一个活跃的社区,好消息是,问题会被迅速发现、报告和补救。坏消息是,这也意味着大量的组织受到影响,而且有可能被感染。

让我们探讨一下Python软件基金会为提高PyPI的安全性所做的一些努力。

PyPI 2FA和API令牌

Python软件基金会 最近增加了 对双因素认证(2FA)和API令牌的支持 ,以使向现有PyPI项目上传软件包的过程更加安全。

  • 2FA在软件包管理员登录PyPI网站时增加了一个额外的验证级别。除了用密码登录外,启用2FA的用户将需要从认证器应用中提供一个访问代码,或拥有一个物理安全设备,如YubiKey。
  • 为PyPI添加API令牌有助于防止项目被接管,因为API密钥 只能 用于上传新的软件包版本。即使PyPI的API密钥被泄露,它也不能被用来登录PyPI网站,编辑或删除项目,或删除旧版本。

Pip的新依赖性解决方法

Python软件基金会正在为Pip(Python的默认软件包安装程序)推出一个新的依赖性解决方法,以改善依赖性管理。一些改进包括:

  • 严格性 - 当前版本的 pip 更加严格,防止用户在一个环境中同时安装不兼容和/或不安全的软件包。
  • 冲突 - Pip现在会在冲突发生时告诉你,并在可能的情况下提供信息以帮助你手动解决冲突。

但这些变化带来了新的行为,可能给用户带来不便,包括:

  • 解决问题可能需要一些时间,因为现在Pip在发现不兼容的时候会进行回溯。这可能意味着在pip逐步执行解决的过程中可能会安装/删除多个软件包。
  • 有时,pip根本无法解决冲突,让你不得不自己手动解决。如果你希望有一个解决 依赖性地狱的方法,pip还没有做到。

PyPI打包项目经理

Python软件基金会已经 聘请了Shamika Mohanan 作为PyPI的项目经理。该项目经理的任务是使该服务更加实用和可持续。

Shamika还担任社区经理,接受Python社区中利益相关者的反馈。这个职位的发起人Bloomberg的工作重点是 "向左转移",这无疑会对Shamika的举措产生很大影响。

Python漏洞数据库

虽然美国国家漏洞数据库(NVD)是一个一般的开源漏洞库,但有两个数据库更专注于Python,记录和跟踪Python生态系统的漏洞。

  • Python软件包咨询数据库 是一个GitHub漏洞咨询库。NVD要求漏洞报告组织注册成为CVE编号机构(CNA),而Python Package Advisory则不同,它是社区所有。任何人都可以创建一个拉动请求并提交漏洞更新。
  • 谷歌的 开源漏洞 (OSV)数据库跟踪Python、Go、Rust和其他语言的漏洞。它提供了一个API,所以用户可以通过编程查询他们正在使用的软件包版本是否受到漏洞的影响。

这些数据库可以帮助企业追踪与Python依赖关系相关的漏洞,识别有风险的软件包,并在构建其软件时做出适当的选择。

客户端 Python 的自动更新

更新框架 (TUF)是在客户端系统上运行的软件更新系统的Python实现,可以自动连接到PyPI,下载和安装软件包更新。TUF还可以防止攻击者破坏存储库或签名密钥。

目前正在更新到现代Python,当这个软件被整合到PyPI时,软件开发者将能够把它纳入他们的软件,以提供一个快速、安全和方便的更新机制。

Python Pip-audit

pip-audit 是一个新的漏洞扫描器,让开发者快速扫描Python环境中安装的任何软件包的漏洞。一旦发现漏洞,开发者就可以做出明智的决定,即是否要继续使用该软件包,切换到不同的版本,或完全替换该软件包。

pip-audit可以通过提高对开发环境中的漏洞的认识,并提供可以帮助开发者快速修复漏洞的选项,来帮助组织转变安全左。如果你曾经 在JavaScript项目上使用过 npm-audit ,那么你已经对pip-audit为Python项目提供的功能有了很好的了解。

当前Python供应链面临的挑战

尽管有这些努力,Python 供应链仍然不安全。公平地说,在安全方面,Python并不比其他大多数开源生态系统好或差。问题是,开源是基于公共资源库的,这些资源库有几十万个开发者上传的几百万行未签名的代码,几乎不能保证这些软件资产的安全性或完整性。

认为任何由志愿者管理的非营利组织能够控制这种狂野的西部方法是不公平的。但这并不意味着你可以忽视PyPI安全方面的漏洞。让我们来看看其中的一些。

PyPI的漏洞

尽管Python软件基金会做出了最大的努力,但 PyPI仍然有定期暴露出来 的 漏洞。这些漏洞有可能让黑客获得用户的机密数据,或者让他们破坏系统。

域名抢注

Typosquatting 是一种社会工程攻击,针对的是在互联网上访问内容时出现排版错误的用户。

在Python中,当用户在输入安装命令时出现错误,这个问题就会浮现出来。例如,用户可能输入 "pip install matplatlib",而不是 "pip install matplotlib"。坏人已经多次将含有恶意软件的打字错误的软件包上传到PyPI,以便利用打字错误的人。

解决这个问题的一个方法是使用一个私人仓库,而不是PyPI,该仓库只包含你的开发人员所需要的软件包。这样一来,输入错误的安装命令就会失败,而不是下载一个被破坏的软件包。

依赖关系的混淆

在上述涉及内部仓库的情况下,你应该注意到pip有一个不幸的默认行为,即首先检查PyPI。这就是依赖关系混乱的地方。

  • 一个坏的行为者可以猜测一个内部包的名字(比如shopify_requests),然后上传一个同名的受损包到PyPI。由于 pip 不支持域名,当你输入 "pip install shopify_requests "时,它可能会错误地从 PyPI 安装 shopify_requests,而不是安装你的私有仓库。

解决依赖关系混乱的一个方法是将 pip 设置为只从你的本地仓库安装。

盗用Python轮子

Python轮子比源码发行版更小,安装速度也更快,但由于其内容对开发者是不透明的,所以潜在的安全性较低。当你把二进制轮子导入到你的应用程序中时,你无法看到将被执行的内容,这使得你很容易被轮子劫持。轮 子劫持 发生在开发者被欺骗安装一个被破坏的轮子,在导入时执行恶意代码。

轮子劫持可以与依赖性混淆一起使用,当坏的行为者识别/猜测到一个组织内部使用的软件包时。然后,他们可以在PyPI上创建一个名称相同的软件包,一旦导入,就可以访问开发中的应用程序所能看到的任何系统和数据。

避免轮子劫持的最好方法是始终从源代码构建二进制包。

结论 - 一个更安全的 Python 生态系统

尽管PyPI软件基金会已经发现了安全漏洞,并在不断努力提高软件包库的安全性,但有些问题可能始终存在。作为一个资源有限的志愿者组织,他们很可能总是落后于不断演变的供应链威胁。毕竟,一个坏的行为者只需要利用一个薄弱环节,但PyPI的维护者需要堵住所有的环节。

与其实施多种变通方法、最佳解决方案和自定义代码来弥补Python生态系统的安全缺陷,不如考虑使用第三方Python生态系统,比如ActiveState Platform提供的生态系统。

ActiveState Platform为Python实现了一个交钥匙的安全供应链,其中包括:

  • 进口控制 --一个开放的源码目录包含了受保护的Python软件包,这些软件包已经被检查过,以确保它们得到了良好的维护和适当的商业使用许可。
  • 构建控制 --一个安全的构建服务从Windows、Linux和macOS的源代码中自动构建Python包(包括链接的C和Fortran库)。开发人员不再需要安装可能被破坏的二进制文件。
  • 运行控制 --在整个构建步骤中对所有构建工件进行校验,确保最终构建的软件包没有被破坏。

ActiveState平台是一个易于实现和简单采用的服务,可以帮助你解决这里讨论的许多常见的漏洞,包括错别字、依赖性混乱和轮子劫持。