Docker安全实践指南:从审计到AI保护的6个实验

本文提供六个实用的Docker安全实验,涵盖配置审计、容器加固、漏洞扫描、镜像签名、系统调用过滤和AI工作负载保护,帮助您全面掌握容器安全技术。

Docker安全:从审计到AI保护的6个实用实验

Docker容器共享主机内核。单个配置错误的容器可能暴露敏感数据、提供对主机的root访问权限或危及整个基础设施。本指南提供六个在Linux、macOS和Windows上运行的实用实验。

示例使用开源工具,并演示易受攻击和安全配置。每个实验都是动手可运行的。所有代码和详细说明可在GitHub上获取:https://github.com/opscart/docker-security-practical-guide

本文涵盖六个基本安全实践:

  • 使用Docker Bench Security进行配置审计
  • 使用功能和只读文件系统加固容器
  • 使用Trivy进行漏洞扫描和策略执行
  • 镜像签名以保障供应链安全
  • 用于系统调用过滤的Seccomp配置文件
  • AI/ML工作负载安全

实验01:使用Docker Bench进行安全审计

学习内容

运行全面的安全审计,在错误配置成为漏洞之前识别它们。Docker Bench Security检查主机配置、守护程序设置、文件权限、容器配置和网络设置。

动手练习

克隆仓库并导航到实验01:

1
2
git clone https://github.com/opscart/docker-security-practical-guide.git 
cd docker-security-practical-guide/labs/01-docker-bench-security

步骤1:运行初始审计

1
./run-audit.sh

Docker Bench在七个CIS基准部分运行105项检查。输出显示PASS(合规)、WARN(需要注意)和INFO(手动审查)结果。

步骤2:部署易受攻击的应用程序 部署具有故意安全问题的容器:

1
docker-compose -f demo-vulnerable-app.yml up -d

这会创建具有多个问题的容器:

  • 启用特权模式
  • 共享主机网络命名空间
  • Docker套接字安装在容器内
  • 环境变量中的硬编码凭据
  • 授予所有Linux功能

步骤3:再次审计

1
./run-audit.sh

分数显著下降。出现新的WARN发现,涉及特权容器、暴露的Docker套接字和禁用的安全配置文件。

理解结果

输出格式:

1
2
3
[PASS] 5.1 - Verify AppArmor profile, if applicable 
[WARN] 5.2 - Container running in privileged mode 
[INFO] 5.3 - Restrict Linux Kernel Capabilities within containers

三个类别:

  • PASS:满足CIS基准要求
  • WARN:需要处理的安全问题
  • INFO:需要手动验证

常见问题和修复

1. 问题:特权容器

问题:

1
privileged: true  # 授予完整主机访问权限

修复:

1
2
3
4
5
6
cap_drop: 
  - ALL 
cap_add: 
  - NET_BIND_SERVICE  # 仅所需功能
security_opt: 
  - no-new-privileges:true

2. 问题:Docker套接字挂载

问题:

1
2
volumes: 
  - /var/run/docker.sock:/var/run/docker.sock

这授予容器对Docker守护程序的完全控制——相当于主机上的root访问权限。

修复:完全移除套接字挂载。如果需要Docker API访问,请改用适当的身份验证。

步骤4:清理

1
2
docker-compose -f demo-vulnerable-app.yml down
docker system prune -f

实验02:安全容器配置

目标

比较不安全与安全的容器配置。了解Linux功能的工作原理以及为什么只读文件系统很重要。

理解Linux功能

Linux将root特权划分为称为功能的独立单元。与其以具有完全特权的root身份运行容器,不如仅授予所需的特定功能。

常见功能:

  • CAP_NET_BIND_SERVICE – 绑定到1024以下的端口
  • CAP_CHOWN – 更改文件所有权
  • CAP_SETUID/SETGID – 更改用户/组ID

默认Docker行为授予功能子集。安全方法:删除所有功能,然后仅添加应用程序所需的功能。

动手练习

1
cd labs/02-secure-configs

步骤1:部署不安全容器

1
./deploy-insecure.sh

部署具有所有功能、读写文件系统、以root身份运行且无安全限制的nginx。

步骤2:部署安全容器

1
./deploy-secure.sh

部署具有最小功能、只读根文件系统、用于所需写入的tmpfs挂载和启用no-new-privileges的nginx。

步骤3:比较安全态势

1
./compare-security.sh

输出显示:

1
2
INSECURE Container Capabilities: CapEff: 000001ffffffffff 
SECURE Container Capabilities: CapEff: 00000000000004c1

十六进制值表示启用的功能。不安全容器具有所有功能(ffffffffff)。安全容器仅具有四个特定功能(4c1)。这种减少显著限制了攻击者在入侵后的能力。

步骤4:测试安全控制

1
./test-security.sh

测试软件包安装、文件系统写入和特权升级。安全容器在保持功能的同时阻止软件包安装和根文件系统写入。

配置详情

不安全容器命令:

1
2
docker run -d --name insecure-nginx --privileged --cap-add ALL \
--security-opt apparmor=unconfined -p 8080:80 nginx:alpine

安全容器命令:

1
2
3
4
5
6
7
docker run -d --name secure-nginx --read-only --cap-drop ALL \  
--cap-add NET_BIND_SERVICE --cap-add CHOWN --cap-add SETUID --cap-add SETGID \  
--security-opt=no-new-privileges:true \  
--tmpfs /tmp:rw,noexec,nosuid,size=64M \  
--tmpfs /var/cache/nginx:rw,noexec,nosuid,size=64M \  
--tmpfs /var/run:rw,noexec,nosuid,size=64M \  
-p 8081:8081 nginx:alpine

只读文件系统防止恶意软件安装、配置篡改和二进制修改。tmpfs在需要的地方提供内存支持的写空间,带有noexec和nosuid标志防止二进制执行。

实验03:漏洞扫描和策略执行

目标

扫描容器镜像以查找已知漏洞,并在部署前强制执行安全策略。

理解漏洞扫描

容器镜像包含操作系统软件包和应用程序依赖项。每个组件都可能具有CVE跟踪的漏洞。基础镜像通常包含数百个漏洞。依赖项很快过时。某些漏洞具有活跃的利用。

在开发期间、CI/CD流水线中、部署前以及定期对运行中的镜像进行扫描。

使用的工具

Trivy:开源漏洞扫描器。扫描操作系统软件包、应用程序依赖项、基础设施即代码文件和Kubernetes配置。快速扫描(不到1分钟)且具有全面的漏洞数据库。

Open Policy Agent (OPA):用于强制执行安全规则的策略引擎。检查容器配置、运行时设置和合规性要求。

动手练习

1
cd labs/03-vulnerability-scanning

步骤1:安装Trivy

macOS:

1
brew install trivy

Linux:

1
2
3
wget https://github.com/aquasecurity/trivy/releases/latest/download/trivy_Linux-64bit.tar.gz 
tar zxvf trivy_Linux-64bit.tar.gz 
sudo mv trivy /usr/local/bin/

步骤2:扫描容器镜像

1
./scan-image.sh

输出显示库名称、CVE标识符、严重性级别(CRITICAL/HIGH/MEDIUM/LOW)以及当前与修复版本。

步骤3:应用安全策略

安装OPA:

1
brew install opa  # macOS

应用策略:

1
./apply-policy.sh

OPA检查特权模式、root用户、缺少健康检查和过多暴露端口。policy.rego文件定义拒绝规则(阻止部署)和警告规则(标记问题)。

步骤4:测试策略执行

部署特权容器:

1
2
docker run -d --name test-vulnerable --privileged nginx:alpine 
./apply-policy.sh

策略检测到特权模式违规。清理:

1
docker rm -f test-vulnerable

CI/CD集成

GitLab CI示例:

1
2
3
4
5
scan:
  stage: test
  script:
    - trivy image --exit-code 1 --severity CRITICAL,HIGH $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  allow_failure: false

如果找到严重或高度漏洞,流水线失败。

修复过程

找到漏洞时:

  1. 首先关注CRITICAL和HIGH严重性
  2. 检查是否有可用的修复
  3. 将基础镜像更新到最新的修补版本
  4. 使用包管理器更新依赖项
  5. 使用更新重建镜像
  6. 重新扫描以验证解决

示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 找到:openssl 1.1.1t 具有 CVE-2023-12345 (CRITICAL)
# 修复于:1.1.1u

# 更新 Dockerfile
FROM alpine:3.18  # 而不是 3.17
RUN apk add --no-cache openssl

# 重建并验证
docker build -t myapp:fixed .
trivy image myapp:fixed

实验04:镜像签名和验证

为什么镜像签名很重要

容器镜像在传输过程中可能被篡改,被攻击者在注册表中替换,或被受损的构建系统修改。镜像签名提供来源的加密证明并检测未经授权的修改。

针对容器注册表的供应链攻击有所增加。镜像签名现在是许多合规框架的要求。没有签名,您无法验证生产中运行的镜像正是您的构建系统创建的。

理解镜像签名

数字签名使用非对称密码学:

  • 私钥签名镜像
  • 公钥验证签名
  • 任何修改都会破坏签名
  • 只有密钥持有者可以签名

本实验使用来自Sigstore项目的Cosign。Cosign支持传统的基于密钥的签名和使用OIDC提供商的无密钥签名。

动手练习

1
cd labs/04-image-signing

步骤1:安装Cosign

macOS:

1
brew install cosign

Linux:

1
2
3
wget https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 
chmod +x cosign-linux-amd64 
sudo mv cosign-linux-amd64 /usr/local/bin/cosign

步骤2:设置签名基础设施

1
./setup-signing.sh

在端口5001上启动本地注册表并生成签名密钥(cosign.key和cosign.pub)。

步骤3:构建和签名镜像

1
./sign-image.sh

脚本构建示例镜像,将其推送到本地注册表,并使用Cosign签名。系统将提示您输入密码以保护私钥。

步骤4:验证签名

1
./verify-image.sh

验证确认:

  • 镜像来自预期来源
  • 自签名以来无修改
  • 签名与公钥匹配

步骤5:测试未签名镜像 尝试验证未签名镜像:

1
2
docker pull nginx:latest 
cosign verify --key cosign.pub nginx:latest

返回"Error: no signatures found",阻止使用不受信任的镜像。

策略执行

在生产中,使用Kubernetes准入控制器或注册表策略强制执行签名镜像。未签名镜像应在部署前被拒绝。

Kubernetes示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
metadata:
  name: require-signed-images
spec:
  images:
  - glob: "registry.company.com/**"
  authorities:
  - key:
      data: |
        -----BEGIN PUBLIC KEY-----
        [your public key]
        -----END PUBLIC KEY-----

实验05:Seccomp配置文件

理解Seccomp

安全计算模式(seccomp)是Linux内核功能,用于过滤系统调用。应用程序进行系统调用以请求内核服务。限制容器可以进行哪些系统调用可以减少攻击面。

Linux有300多个系统调用。大多数应用程序需要少于100个。阻止不必要的系统调用可以防止整个类别的攻击。

工作原理

当容器尝试系统调用时:

  • 内核检查seccomp配置文件
  • 如果允许:调用执行
  • 如果阻止:操作失败或进程终止

Docker的默认配置文件阻止约44个危险系统调用,同时允许常见操作。

动手练习

1
cd labs/05-seccomp-profiles

步骤1:测试默认配置文件

1
./test-default-profile.sh

默认配置文件允许文件操作、网络操作和基本进程操作。它阻止重新启动、挂载和系统时间修改。

步骤2:测试限制性配置文件

1
./test-restrictive-profile.sh

限制性配置文件仅允许所需的最少系统调用。它阻止套接字创建、进程分叉和文件权限更改。此配置文件适用于非常受限的环境。

步骤3:生成应用程序特定配置文件

1
./generate-profile.sh

为nginx创建具有适当系统调用的配置文件。配置文件阻止危险的调用,如挂载和重新启动,同时允许nginx需要的网络和文件操作。

配置文件结构

基本seccomp配置文件格式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "defaultAction": "SCMP_ACT_ERRNO",
  "architectures": ["SCMP_ARCH_X86_64"],
  "syscalls": [
    {
      "names": ["read", "write", "open", "close"],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}

关键元素:

  • defaultAction:未列出的系统调用发生什么
  • architectures:支持的CPU架构
  • syscalls:显式允许的系统调用
  • action:SCMP_ACT_ALLOW(允许)或SCMP_ACT_ERRNO(阻止)

应用配置文件

Docker运行:

1
docker run --security-opt seccomp=profile.json nginx:alpine

Docker Compose:

1
2
3
4
5
services:
  web:
    image: nginx:alpine
    security_opt:
      - seccomp=profile.json

攻击预防

示例:攻击者在容器中获得shell访问权限。

没有seccomp:

1
2
attacker$ mount /dev/sda1 /mnt  # 成功 - 访问主机磁盘
attacker$ reboot                # 成功 - 重新启动主机

有seccomp:

1
2
attacker$ mount /dev/sda1 /mnt  # 阻止:操作不允许
attacker$ reboot                # 阻止:操作不允许

即使具有shell访问权限,攻击者也无法执行危险操作。

实验06:AI模型安全

为什么AI模型安全很重要

机器学习容器具有独特的安全要求。模型消耗大量CPU/GPU/内存资源。推理输入可能包含敏感数据。模型权重代表知识产权。API暴露攻击面,用于对抗性输入和模型提取。

AI特定威胁

  • 模型提取:攻击者重复查询模型以重新创建它,而无需训练数据访问。
  • 对抗性攻击:精心制作的输入导致不正确预测。
  • 资源耗尽:大型批处理请求消耗所有可用资源。
  • 数据中毒:恶意训练数据损坏模型。

动手练习

1
cd labs/06-ai-model-security

步骤1:构建ML容器

1
./build-ml-container.sh

构建具有Python ML框架、推理服务器和示例模型的容器。使用多阶段构建、非root用户和最小依赖项。

步骤2:使用安全控制部署

1
./deploy-secure.sh

部署具有以下功能的容器:

  • 内存限制:4GB
  • CPU限制:2核心
  • 只读文件系统
  • 用于临时文件的tmpfs
  • 启用no-new-privileges

步骤3:测试模型推理

1
2
3
curl -X POST http://localhost:5001/predict \
  -H 'Content-Type: application/json' \
  -d '{"text":"sample text for prediction"}'

返回带有预测、置信度和元数据的JSON。

步骤4:压力测试

1
./stress-test.sh

发送并发请求以验证资源限制是否正确工作。容器在定义的限制内处理请求而不会崩溃。

安全配置

部署命令:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
docker run -d --name ml-inference \
  --read-only \
  --tmpfs /tmp:rw,noexec,nosuid,size=2g \
  --memory="4g" \
  --cpus="2" \
  --pids-limit="100" \
  --security-opt=no-new-privileges:true \
  --cap-drop=ALL \
  -p 5001:5000 \
  ml-inference:secure

资源限制防止耗尽攻击。只读文件系统防止篡改。进程限制防止fork炸弹。

输入验证

防止恶意输入:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from pydantic import BaseModel, validator

class PredictionRequest(BaseModel):
    features: List[float]
    
    @validator('features')
    def validate_features(cls, v):
        if len(v) > 100:
            raise ValueError('Too many features')
        if any(abs(x) > 1000 for x in v):
            raise ValueError('Feature values too large')
        return v

验证防止过大的输入和可能导致问题的极端值。

速率限制

防止模型提取和资源耗尽:

1
2
3
4
5
6
7
8
9
from slowapi import Limiter

limiter = Limiter(key_func=get_remote_address)

@app.post("/predict")
@limiter.limit("10/minute")
def predict(request: Request, data: PredictionRequest):
    # 处理请求
    pass

限制每个客户端的请求以防止滥用。

实施路线图

按顺序开始实施这些实践:

  • 第1-2周:在所有系统上运行Docker Bench Security。处理WARN发现。添加到CI/CD流水线。
  • 第3-4周:实施容器加固。删除功能。尽可能启用只读文件系统。
  • 第5-6周:设置漏洞扫描。将Trivy集成到构建过程中。创建OPA策略。
  • 第7-8周:实施镜像签名。在CI/CD中设置Cosign。在部署时配置验证。
  • 第9-10周:创建和测试seccomp配置文件。从默认配置文件开始。为关键服务创建自定义配置文件。
  • 第11-12周:如果运行ML工作负载,实施资源限制和输入验证。添加监控和速率限制。
  • 持续进行:定期安全审计。更新依赖项。监控新漏洞。优化安全策略。

开始使用

完整实验说明和工作代码:https://github.com/opscart/docker-security-practical-guide

仓库包括:

  • 所有六个实验练习与脚本
  • 配置示例(易受攻击和安全)
  • 故障排除指南
  • 额外安全资源

按顺序完成实验以获得全面理解。每个实验都建立在先前概念之上。所有实验在Linux、macOS和Windows上工作。

关键要点

  • 实验01:每周运行Docker Bench。处理所有WARN发现。集成到CI/CD。
  • 实验02:默认删除所有功能。使用只读文件系统。为所需写入添加tmpfs。
  • 实验03:在部署前扫描镜像。使用OPA强制执行策略。关注CRITICAL和HIGH漏洞。
  • 实验04:签名所有生产镜像。安全存储密钥。在部署时强制执行验证。
  • 实验05:从Docker的默认seccomp配置文件开始。为敏感工作负载创建自定义配置文件。彻底测试。
  • 实验06:为ML容器设置资源限制。验证输入。实施速率限制和监控。

结论

Docker安全需要跨多个层级的关注。本指南提供六个实用实验,涵盖配置审计、容器加固、漏洞扫描、镜像签名、seccomp配置文件和AI模型安全。

安全不是一次性的实施。定期审计、更新和监控至关重要。本系列中的实践为生产Docker部署提供了坚实的基础。

立即开始实施这些技术:https://github.com/opscart/docker-security-practical-guide

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计