Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
cfn_nag — CloudFormation 模板的 lint 检查工具 | Kitploit
工具/GitHubGitHub/stelligent/cfn_nag
静态代码分析 (SAST)配置审计云安全DevSecOps秘密检测错误配置
GitHubstelligent/cfn_nag

cfn_nag

CloudFormation 模板的 lint 检查工具

查看仓库
1.3k2082年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

cfn_nag

背景

cfn-nag 工具用于查找 CloudFormation 模板中可能表明基础设施不安全的模式。大致来说,它会查找:

  • 过于宽松(通配符)的 IAM 规则
  • 过于宽松(通配符)的安全组规则
  • 未启用的访问日志
  • 未启用的加密
  • 密码字面量

关于该工具的更多背景,请参阅 Stelligent 博客上的这篇文章:

利用 "cfn-nag" 在 CloudFormation 模板开发流程早期发现安全问题

安装

Gem 安装

假设已安装 Ruby >= 2.5.x,安装只需:

root@kitploit:~
gem install cfn-nag

Brew 安装

在 MacOS 或 Linux 上,你也可以选择使用 brew 安装:

root@kitploit:~
brew install ruby brew-gem
brew gem install cfn-nag

CodePipeline

要将 cfn_nag 作为 CodePipeline 中的操作运行,可以通过 AWS Serverless Application Repository 进行部署。

用法

执行方式如下:

root@kitploit:~
cfn_nag_scan --input-path <path to cloudformation json>

该路径可以是目录或特定的模板。如果是目录,则将处理所有 .json, .template、.yml 和 .yaml 文件,包括递归到子目录中。

默认输出格式是自由格式文本,但也可以通过 --output-format json 标志选择 JSON 输出。

可选地,--debug 标志会转储规则加载的内部信息。

运行 --help 可查看所有受支持开关的完整列表。

要查看 cfn-nag 当前支持的所有规则列表,可以使用一个命令行工具将它们输出到 stdout:

root@kitploit:~
cfn_nag_rules

结果

  • 结果会输出到 stdout
  • 失败的违规将返回非零退出码。
  • 警告将返回零(成功)退出码。
  • 致命违规会停止(按文件)分析,因为模板存在某种严重格式错误。

在 Docker 中运行

为方便起见,提供了一个 Dockerfile。它已作为 stelligent/cfn_nag 发布在 DockerHub 上。

https://hub.docker.com/r/stelligent/cfn_nag

你也可以在本地构建它。

root@kitploit:~
docker build -t stelligent/cfn_nag .

你可以将包含模板的本地目录挂载到 Docker 容器中,然后在容器中调用 cfn_nag。此示例使用 cfn_nag 单元测试中使用的测试模板:

root@kitploit:~
$ docker run -v `pwd`/spec/test_templates:/templates -t stelligent/cfn_nag /templates/json/efs/filesystem_with_encryption.json
{
  "failure_count": 0,
  "violations": [

  ]
}
$ docker run -v `pwd`/spec/test_templates:/templates -t stelligent/cfn_nag /templates/json/efs/filesystem_with_no_encryption.json
{
  "failure_count": 1,
  "violations": [
    {
      "id": "F27",
      "type": "FAIL",
      "message": "EFS FileSystem should have encryption enabled",
      "logical_resource_ids": [
        "filesystem"
      ]
    }
  ]
}

作为 GitHub Action 运行

cfn_nag_scan 可以作为 GitHub Workflow 的一部分运行,在持续集成流水线中评估代码。

在你的 GitHub Workflow 文件中,创建一个使用 cfn_nag Action 的步骤:

root@kitploit:~
- name: Simple test
  uses: stelligent/cfn_nag@master
  with:
    input_path: tests

有关 GitHub Action 的更多信息,请参见此处。

结果过滤

配置文件

cfn-nag 支持 "profile(配置文件)" 的概念,它实际上是一个要应用的规则允许列表。该配置文件是一个文本文件,每行必须包含一个规则标识符。当通过 --profile-path 命令行参数指定时,cfn-nag 将只返回来自这些特定规则的违规。

创建 "profile" 的动机在于,不同的开发者可能关心不同的规则。例如,"infrastructure_developer" 可能关心 IAM 规则,而 "app_developer" 可能甚至无法创建 IAM 资源,因此不关心这些规则。

以下是一个 profile 示例:

root@kitploit:~
F1
F2
F27
W3
W5

全局拒绝列表

拒绝列表基本上与 profile 相反:它是一个从不应用的规则列表。当通过 --deny-list-path 命令行参数指定时,cfn-nag 将永远不会返回文件中指定的那些特定规则的违规。

如果某个规则同时在两者中指定,则拒绝列表优先于 profile,并且该规则不会被应用。

格式如下。唯一两个重要字段是 RulesToSuppress 和每个条目的 id。reason 不会被 cfn-nag 解释,但建议用来说明并记录为什么该规则永远不应被应用。

root@kitploit:~
RulesToSuppress:
- id: W3
  reason: W3 is something we never care about at enterprise X

按资源规则抑制

如果有想要抑制的规则,可以在受影响的资源上添加 cfn_nag 的 Metadata 键,告诉 cfn_nag 不要针对该规则引发失败或警告。

例如,如果你正在设置一个面向公众、允许来自互联网的入站连接的 ELB,资源如下所示:

public_alb.yaml

root@kitploit:~
# Partial template
PublicAlbSecurityGroup:
  Properties:
    GroupDescription: 'Security group for a public Application Load Balancer'
    VpcId:
      Ref: vpc
  Type: AWS::EC2::SecurityGroup
PublicAlbSecurityGroupHttpIngress:
  Properties:
    CidrIp: 0.0.0.0/0
    FromPort: 80
    GroupId:
      Ref: PublicAlbSecurityGroup
    IpProtocol: tcp
    ToPort: 80
  Type: AWS::EC2::SecurityGroupIngress

cfn_nag 将引发如下警告:

root@kitploit:~
$ cfn_nag_scan -i public_alb.yaml
------------------------------------------------------------
public_alb.yaml
------------------------------------------------------------------------------------------------------------------------
| WARN W9
|
| Resources: ["PublicAlbSecurityGroup"]
|
| Security Groups found with ingress cidr that is not /32
------------------------------------------------------------
| WARN W2
|
| Resources: ["PublicAlbSecurityGroup"]
|
| Security Groups found with cidr open to world on ingress.  This should never be true on instance.  Permissible on ELB

Failures count: 0
Warnings count: 2

通过添加 metadata,可以抑制这些警告:

public_alb_with_suppression.yaml

root@kitploit:~
# Partial template
PublicAlbSecurityGroup:
  Properties:
    GroupDescription: 'Security group for a public Application Load Balancer'
    VpcId:
      Ref: vpc
  Type: AWS::EC2::SecurityGroup
  Metadata:
    cfn_nag:
      rules_to_suppress:
        - id: W9
          reason: "This is a public facing ELB and ingress from the internet should be permitted."
        - id: W2
          reason: "This is a public facing ELB and ingress from the internet should be permitted."
PublicAlbSecurityGroupHttpIngress:
  Properties:
    CidrIp: 0.0.0.0/0
    FromPort: 80
    GroupId:
      Ref: PublicAlbSecurityGroup
    IpProtocol: tcp
    ToPort: 80
  Type: AWS::EC2::SecurityGroupIngress
root@kitploit:~
$ cfn_nag_scan -i public_alb_with_suppression.yaml
------------------------------------------------------------
public_alb_with_supression.yaml
------------------------------------------------------------
Failures count: 0
Warnings count: 0

设置模板参数值

CloudFormation 模板参数可能会给静态分析带来问题,因为参数值是在部署时指定的。换句话说,静态分析完成时这些值并不可用——静态分析只能查看它面前的“代码”。因此,如果 cidr 被参数化,并且 0.0.0.0/0 在部署时传入,则安全组入站规则 0.0.0.0/0 不会被标记。

为了允许检查参数值,用户可以在通过命令行传给 cfn_nag 和 cfn_nag_scan 的 JSON 文件中指定参数值,使用 --parameter-values-path=<filename/uri> 标志。

JSON 的格式是一个单独的键 "Parameters",其值是一个字典,每个键/值对映射到 Parameters:

root@kitploit:~
{
  "Parameters": {
    "Cidr": "0.0.0.0/0"
  }
}

这将把 "0.0.0.0/0" 提供给以下 Parameter:

root@kitploit:~
Parameters:
  Cidr:
    Type: String

请注意,如果 JSON 中有额外的参数,它们会被静默忽略(以允许 cfn_nag_scan 将同一个 JSON 应用于所有模板)。

如果 JSON 格式错误或不符合上述规范,解析将以 FATAL 违规失败。

映射

在 0.5.55 之前,对 Fn::FindInMap 的调用实际上会被忽略。底层模型会保留它们,因此它们会以 Hash 值的形式出现在规则中。例如:{ "Fn::FindInMap" => [map1, key1, key2]}

从 0.5.55 开始,模型会尝试计算 FindInMap 调用的值,并将该值提供给规则。此评估支持以下键:

  • 静态文本
  • 对参数的引用(带参数替换)
  • 对 AWS 伪函数的引用(见下一节)
  • 嵌套映射

如果评估逻辑无法确定某个键的值,它将默认采用旧行为,即返回整个表达式的 Hash。

AWS 伪函数

同样在 0.5.55 之前,对 AWS 伪函数的调用实际上被忽略。底层模型会保留它们,因此它们会以 Hash 值的形式出现在规则中。例如:{"Ref"=>"AWS::Region"}。一个常见的用例是按区域组织映射,因此伪函数求值对于更好地支持映射评估很重要。

从 0.5.55 开始,模型将向规则提供以下 AWS 伪函数及其默认值:

root@kitploit:~
'AWS::URLSuffix' => 'amazonaws.com',
'AWS::Partition' => 'aws',
'AWS::NotificationARNs' => '',
'AWS::AccountId' => '111111111111',
'AWS::Region' => 'us-east-1',
'AWS::StackId' => 'arn:aws:cloudformation:us-east-1:111111111111:stack/stackname/51af3dc0-da77-11e4-872e-1234567db123',
'AWS::StackName' => 'stackname'

此外,最终用户可以通过传统的参数替换机制覆盖所提供的值。例如:

root@kitploit:~
{
  "Parameters": {
    "AWS::Region": "eu-west-1"
  }
}

控制条件的行为

在 cfn_nag 0.4.66 版本之前,底层模型不会对模板中的 Fn::If 做任何处理。这意味着,如果属性具有条件值,则需要规则来解析 Fn::If。鉴于 Fn::If 几乎可以出现在任何地方,这给规则开发者带来了一种“打地鼠”式的困境。充其量,规则逻辑可以忽略那些为 Hash 的值——前提是该值原本就不是 Hash。

为了解决此问题,cfn_nag 现在的默认行为是用 true 分支的结果替换 Fn::If。这意味着默认情况下,规则不会检查 false 分支结果中的安全违规。

除了在属性值级别替换 Fn::If 之外,同样的行为也应用于 Properties 顶层的 Fn::If。例如:

root@kitploit:~
Resource1:
  Type: Foo
  Properties: !If
    - IsNone
    - Description: Up
    - Description: DOwn

看起来将与以下内容相同:

root@kitploit:~
Resource1:
  Type: Foo
  Properties:
    Description: Up

为了对上述行为提供一定控制,用户可以在通过命令行传给 cfn_nag 和 cfn_nag_scan 的 JSON 文件中指定条件值,使用 --condition-values-path=<filename/uri> 标志。

该 JSON 的格式是一个字典,每个键/值对映射到 Conditions:

root@kitploit:~
{
  "Condition1": true,
  "Condition2": false
}

Stelligent 策略复杂度指标(spcm)

SPCM 的基础在博客文章 IAM 策略文档复杂度度量的思想实验 中有所描述。

从 cfn_nag 0.6.0 版本开始:

  • spcm_scan 可以扫描 CloudFormation 模板目录(类似 cfn_nag_scan),并生成包含 SPCM 指标的 JSON 或 HTML 格式报告
  • 新增了一个规则(添加到 cfn_nag),用于对 SPCM 分数 >= 50(默认值)的 IAM::Policy 或 IAM::Role 发出警告
  • 规则的阈值可以通过命令行控制:cfn_nag_scan --rule-arguments spcm_threshold:100
  • 自定义规则开发者现在可以通过相同的 --rule-arguments 机制开发规则,以接受最终用户对设置的配置值。Rule 对象只需声明一个 attr_accessor,例如 attr_accessor :spcm_threshold,cfn_nag 将处理从 --rule-arguments 注入值的细节。

自定义规则的分发

0.5.x 版本在自定义规则的分发和加载方式上引入了一些重大变化。在此版本之前,规则有两个加载位置:核心 cfn_nag gem 中的 lib/cfn-nag/custom_rules 目录,以及命令行中指定的 custom-rule-directory。

有两个用例促使重新设计了自定义规则的加载方式和位置。规则加载机制已通用化,使得自定义规则仓库可用于发现规则。

  1. 从传统软件开发的角度来看,一堆“规则文件”散落在文件系统中并不理想。这些文件没有版本或可追溯性,因此 0.5.x 引入了 “cfn_nag rule gem” 的概念。开发者可以在一个独立的 gem 中开发自定义规则、为其设定版本并安装……只要 gem 元数据包含 cfn_nag_rules => true,cfn_nag 就会引用这些规则。对于类似 "cfn-nag-hipaa-rules" 的 gem,lib/cfn-nag-hipaa-rules 下的任何 *.rb 文件都会被加载。任何自定义规则都应继承自 cfn-nag/base_rule 中的 CfnNag::BaseRule(不是 cfn-nag/custom-rules/base)。如果规则必须继承自其他类,定义一个返回 true 的 cfn_nag_rule? 方法也会使其作为规则被加载。

  2. 当 cfn_nag 在 AWS Lambda 中运行时,传统意义上并不存在真正的文件系统(除了 /tmp)。因此,Lambda 中只能使用核心规则。为了支持自定义规则,cfn_nag 支持从 S3 存储桶而不是文件系统发现规则。

你可能见过的关于如何在 Ruby 中开发自定义规则的所有内容仍然适用。

要从 S3 存储桶发现规则,请创建一个包含以下内容的 s3.yml 文件:

root@kitploit:~
---
repo_class_name: S3BucketBasedRuleRepo
repo_arguments:
  s3_bucket_name: cfn-nag-rules-my-enterprise
  prefix: /rules

要应用存储桶 cfn-nag-rules-my-enterprise 中前缀为 /rules(例如 /rules/MyNewRule.rb)的 *Rule.rb 文件,请在命令行中按如下方式向 cfn_nag 指定此文件:

root@kitploit:~
cat my_cfn_template.yml | cfn_nag --rule-repository s3.yml

如果规则位于多个存储桶中,则创建多个 s3*.yml 文件,并在 --rule-repository 参数中指定它们。

如果环境中的 AWS 凭据有权访问存储桶 cfn-nag-rules-enterprise,它将找到所有类似 /rules/*Rule.rb 的规则。如果应使用特定的 aws_profile,请将其作为 repo_arguments 下的一个键添加,例如 aws_profile: my_aws_profile。

除了文件系统、gem 安装和 S3 之外,新架构理论上还支持开发其他“规则仓库”,以从 DynamoDb、关系数据库或其他 Web 服务加载规则。

开发

新规则

要为个人使用和/或社区贡献编写新规则,请参阅 自定义规则开发 了解详情。

这里有一段演示从零到一进行 TDD 自定义规则开发的录屏:

https://www.youtube.com/watch?v=JRZct0naFd4&t=1601s

Specs

要运行 specs,你需要确保已安装 Docker,并通过以下方式安装 cfn_nag 依赖:

root@kitploit:~
gem install bundle
bundle install

然后,要运行所有 specs,只需运行 rake test:all。

要运行端到端测试,请运行 rake test:e2e。该脚本将捆绑 Gemfile 中的所有 gem,在本地构建并安装 cfn_nag gem,安装 spec 依赖项,然后执行标记为 'end_to_end' 的测试。它还会拉取 Amazon 提供的示例模板,并对其运行 cfn_nag_scan,以查看是否有任何已知良好的模板在 cfn-nag 中引发异常。

本地安装

要在本地安装当前 git 分支:

root@kitploit:~
bundle install
scripts/deploy_local.sh

VS Code 远程开发

这里提供了一个完整的远程开发环境,所有工具和设置均已预先配置,便于规则的开发和创建。你可以通过使用 VS Code 远程开发功能启用它。

  • 安装 VS Code Remote Development 扩展包
  • 在 VS Code 中打开仓库
  • 当提示 Folder contains a dev container configuration file. Reopen folder to develop in a container 时,点击 Reopen in Container 按钮
  • 以后打开时,使用 [Dev Container] cfn_nag Development 选项

有关 VS Code 远程开发设置的更多信息,请参见 VS Code Remote Development。

支持

要报告 bug 或请求功能,请通过 GitHub 仓库提交 issue:https://github.com/stelligent/cfn_nag/issues/new

下载工具