标题 | 简介 | 类型 | 公开时间 | ||||||||||
|
|||||||||||||
|
|||||||||||||
详情 | |||||||||||||
[SAFE-ID: JIWO-2025-3169] 作者: 小螺号 发表于: [2022-09-01]
本文共 [305] 位读者顶过
GitHub 页面GitHub Pages是一个静态内容托管服务。它允许用户在username.github.io或自定义域中托管其存储库的内容。它广泛用于托管简单的静态页面,例如文档和博客(例如,此博客托管在 GitHub Pages 上)。 为了帮助用户托管好看的内容,GitHub Pages 支持Jekyll,一个静态站点生成器平台。使用 Jekyll,您不必为博客编写 HTML 和 CSS,但您可以编写 Markdown,Jekyll 会为您将其转换为 HTML 文件。为了更轻松地在网站上应用相同的模板和样式,Jekyll 支持主题。 Jekyll 站点的所有设置(例如主题)都存储在 YAML 配置文件中。GitHub Pages 自动化了部分 Jekyll 设置(包括设置一些设置)。 设置 Jekyll 主题在存储库的 GitHub Pages 设置中,有一个主题选择器 部分:
顾名思义,这会自动执行选择 Jekyll 主题的过程。 更改主题按钮链接到: https://github.com/owner/repo/settings/pages/themes?select=&source=main&source_dir=/ 此 URL 作为三个参数:
如果我们点击更改主题 按钮,我们会被带到一个显示多个 Jekyll 主题预览的新网页:
请注意,访问此页面需要存储库的管理权限。我们稍后讨论这个。 当我们选择完一个主题并点击选择主题 按钮后,GitHub 会发出一个POST请求: POST /owner/repo/settings/pages/theme HTTP/2 Host: github.com ... _method=put&authenticity_token=some_token&page[theme_slug]=cayman&source=main&source_dir=/ 在这里,我们再次看到source和source_dir参数。由于我们无法在主题选择器页面上更改这些值,因此必须直接从将我们带到此页面的链接中获取这些值。 在POST请求之后,GitHub 会自动创建一个新的提交来更改 Jekyll 主题。GitHub 在分支上的source_dir目录中进行这些更改。source反过来,这个提交会触发一个新的 GitHub Pages 构建。下一节将对此进行更多介绍。 在页面设置中,我们只能指定两个目录:(/即分支的根目录)和/docs.
但是如果我们在主题选择器 URL 中指定另一个目录会发生什么?事实证明,这是可接受的行为,GitHub 将使用我们提供的任何目录名称作为源。例如,如果我们使用一个深奥的目录名称,例如source_dir=/"test" test test>,GitHub 将在以下位置创建一个基本的 Jekyll 设置/"test" test test>:
[出自:jiwo.org]
如果我们自己不这样做,GitHub 甚至可以很好地启用 GitHub Pages 并创建目录。 简而言之,我们可以指定任意目录作为 GitHub Pages 源。 部署 GitHub 页面GitHub Pages 构建实际上只是GitHub Actions工作流程,由三个作业组成: build :
actions/upload-pages-artifact很有趣,因为上传工件最常发生在另一个操作 ( actions/upload-artifact) 中。两者有什么区别? 的代码actions/upload-pages-artifact@v0向我们展示了actions/upload-pages-artifact实际使用actions/upload-artifact,但首先运行tar命令: ... steps: - name: Archive artifact shell: bash run: | tar \ --dereference --hard-dereference \ --directory ${{ inputs.path }} \ -cvf ${{ runner.temp }}/artifact.tar \ --exclude=.git \ . - name: Upload artifact uses: actions/upload-artifact@main with: name: github-pages path: ${{ runner.temp }}/artifact.tar retention-days: ${{ inputs.retention-days }} 如果我们查看成功 Pages 部署的 GitHub Actions 管道日志(我们将目录设置为),我们会在命令/docs中看到变量的值:tar tar \ --dereference --hard-dereference \ --directory ./docs/_site \ -cvf /home/runner/work/_temp/artifact.tar \ --exclude=.git \ . 这告诉我们inputs.path等于.<the direcotry we specify>/_site和runner.temp等于/home/runner/work/_temp。 在上一节中,我们看到我们可以完全控制目录名称,并且因为 Linux(GitHub Actions 运行器上使用的操作系统)几乎允许目录名称中的每个字符,我们可以将目录名称设置为任何我们想要的。如果我们将目录设置为类似的内容会发生什么/ --asdf=?这会将tar命令更改为以下命令吗? tar \ --dereference --hard-dereference \ --directory ./ --asdf=/_site \ -cvf /home/runner/work/_temp/artifact.tar \ --exclude=.git \ . 是的,它会的:
正如我们所见,--asdf它被解释为命令行参数,而不是目录名的一部分。我们发现了命令注入。 任意代码执行tartar有一个名为Checkpoints的功能,我们可以使用它来运行任意命令。将--checkpoint=1 --checkpoint-action="exec=<command>"参数添加到tar命令将使其<command>对每个已处理的文件执行。 从手册页: --checkpoint[=N] Display progress messages every Nth record (default 10). --checkpoint-action=ACTION Run ACTION on each checkpoint. 作为测试,让我们执行id. 我们希望tar命令看起来像: tar \ --dereference --hard-dereference \ --directory ./ --checkpoint=1 --checkpoint-action="exec=id" --exclude=_site \ -cvf /home/runner/work/_temp/artifact.tar \ --exclude=.git \ . 这意味着我们的有效负载(即我们指定的目录名称)是/ --checkpoint=1 --checkpoint-action="exec=id" --exclude=. 我们使用主题选择器将目录名称设置为有效负载并等待管道命中tar命令:
伟大的!我们已经成功实现了任意代码执行。 旁注: 使用--checkpoint-action是实现代码执行的一种方式,但不是唯一的方式。由于我们可以完全控制输入,我们可以退出tar命令并执行任意命令。但是通过使用--checkpoint-action,tar命令(以及整个管道)仍然会成功,从而使攻击对受害者来说不那么明显。 示例攻击现在,您可能会想:"您以管理员身份在 GitHub Actions 运行程序上发现了命令注入漏洞。大不了。所以呢?运行用户指定的任意代码正是 CI 运行器的用途。你只是找到了一种通过额外步骤来完成它的方法。" 你是对的。但是,使这种可利用的原因是它可以通过 URL 触发。 假设我们是一名攻击者,想要访问公司私人仓库中的代码。我们可以利用这个漏洞来访问代码:
当然,这里最大的警告是存储库管理员对用户交互的要求。但是,有一些补偿因素:
其他攻击除了读取存储库中的代码外,GitHub Actions 运行器上的代码执行还允许一些其他攻击:
解决问题GitHub 通过删除主题选择器功能解决了这个问题。页面设置现在显示"了解如何将 Jekyll 主题添加到您的网站":
来源:https://blog.nietaanraken.nl/posts/github-pages-command-injection/ |