PyPI中潜在的远程代码执行漏洞

admin 2021年12月11日13:15:37评论129 views字数 2576阅读8分35秒阅读模式
PyPI中潜在的远程代码执行漏洞点击上方蓝字关注我们


PyPI中潜在的远程代码执行漏洞


概述


PyPI是Python官方的第三方库的仓库,在运行pip install [package name]命令时会引用它。PyPI存储库的GitHub Actions中存在一个漏洞,该漏洞允许恶意拉取请求执行任意命令。这允许攻击者获得对存储库的写权限,从而在pypi.org上实现任意代码执行。

PyPI源代码审计


研究人员阅读了发布在GitHub的PyPI源代码,发现它使用了一个名为Pyramid的 Python网络框架。之后,研究人员继续检查PyPI源代码,并发现了以下两个漏洞。

任意遗留文件删除

PyPI曾具有可用于Python项目的文档功能。该功能之后由于使用率不高被开发人员删除,但他们没有删除现有文档。

因此,删除这些文档的功能可以被请求,并在此拉取请求中实现。此功能通过在内部使用以下代码来删除文档:

def remove_by_prefix(self, prefix):        if self.prefix:            prefix = os.path.join(self.prefix, prefix)        keys_to_delete = []        keys = self.s3_client.list_objects_v2(Bucket=self.bucket_name, Prefix=prefix)        for key in keys.get("Contents", []):            keys_to_delete.append({"Key": key["Key"]})            if len(keys_to_delete) > 99:                self.s3_client.delete_objects(                    Bucket=self.bucket_name, Delete={"Objects": keys_to_delete}                )                keys_to_delete = []        if len(keys_to_delete) > 0:            self.s3_client.delete_objects(                Bucket=self.bucket_name, Delete={"Objects": keys_to_delete}            )

从上面的代码片段中可以看出,它使用带有前缀参数的list_objects_v2函数来获取要删除的对象。并且用户拥有的项目的名称会被传递到前缀参数中。

这意味着如果有人删除了名为examp的项目中的遗留文档,它将删除名称以examp开头的项目文档,例如exampleexampleasdf

任意角色删除

PyPI具有包的权限管理功能。在此功能中,项目所有者可以授予/删除权限。在删除权限过程中存在一个漏洞。数据库中获取权限信息时,PyPI使用以下代码:

role = (    request.db.query(Role)    .join(User)    .filter(Role.id == request.POST["role_id"])    .one())

从上面的代码片段可以看出,它在获取要删除的权限信息时没有指定项目ID。因此,攻击者可以通过假设role_id来删除其他项目的权限。

远程代码执行


以上发现的这些漏洞不会产生太大影响,充其量只能用于骚扰。因此,研究人员决定继续深挖,以寻找一个可用于执行任意代码的漏洞。

一番探索之后,研究人员发现推送到pypa/warehouse存储库主分支的代码会自动部署到pypi.org。这意味着,如果我们能够获得pypa/warehouse存储库的写权限,就可以在pypi.org上执行任意代码。

因此,研究人员检查了GitHub Actions的工作流文件,该文件默认具有pypa/warehouse存储库的写权限,并发现了以下漏洞。

在pypa/warehouse中,有一个名为combine-prs.yml的工作流。该工作流被用于收集分支名称以dependabot开头的拉取请求,并将它们合并为一个拉取请求。

combine-prs.yml工作流中,缺少对拉取请求作者的验证。这意味着,如果有人创建了一个分支名称以dependabot开头的拉取请求,则可以强制此工作流处理精心制作的拉取请求。

但是,此工作流仅将拉取请求合并为一个拉取请求。因此,此工作流生成的拉取请求将由人工审核,如果其中包含恶意更改,他们将直接丢弃它。

因此,这不能直接用于执行任意代码。但是,研究人员在通读代码时发现了另一个漏洞。combine-prs.yml的第119行,有以下代码。

script: |  const prString = `${{ steps.fetch-branch-names.outputs.prs-string }}`;

${{ }}表达式将在被传递到Bash之前进行求值。这意味着${{ }}表达式不关心Bash中的上下文,因此如果steps.fetch-branch-names.outputs.result包含像";curl https://example.com;# 之类的字符串,curl https://example.com将被执行。

因为这个工作流使用了actions/checkout.git/config 包含secrets.GITHUB_TOKEN,该令牌具有写权限。因此,通过执行诸如cat .git/config之类的命令,可能会泄漏具有pypa/warehouse存储库写权限的GitHub访问令牌。

如上所述,如果有人将更改推送到主分支,它将被自动部署到pypi.org。由于steps.fetch-branch-names.outputs.prs-string包含拉取请求的标题,因此可以使用以下攻击步骤,在pypi.org上实现任意命令执行。

1. pypa/warehouse分支存储库
2. 在pypa/warehouse中找到一个以dependabot开头的分支
3. 对步骤2中找到的分支添加无害修改
4. 创建一个名为`;github.auth().then(auth=>console.log(auth.token.split("")))//的拉取请求
5. 等待combine-prs.yml被执行
6. 对pypa/warehouse具有写权限的GitHub访问令牌将被泄露,因此可以在主分支添加任意修改
7. 修改后的代码将自动部署到pypi.org

PyPI中潜在的远程代码执行漏洞

END



PyPI中潜在的远程代码执行漏洞


好文!必须在看

本文始发于微信公众号(SecTr安全团队):PyPI中潜在的远程代码执行漏洞

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年12月11日13:15:37
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   PyPI中潜在的远程代码执行漏洞https://cn-sec.com/archives/445747.html

发表评论

匿名网友 填写信息