容器安全
Docker 运行时安全
容器安全基础
权限隔离
容器内 root 与逃逸风险
5.1.1.1 功能简介
Docker 容器默认可能以 root(UID 0)运行进程。容器通过 namespace、Linux capabilities、seccomp 和其他机制限制进程,但仍共享宿主机内核。容器内的 UID 0 不会自动等同于宿主机 root;风险取决于 user namespace、额外权限、挂载内容、运行时配置和内核漏洞。成功利用逃逸漏洞或获得宿主机敏感接口访问权,才可能进一步控制宿主机。
容器内 root 仍可能:
-
对容器内文件系统有完全读写权限;
-
可以操作容器内的进程;
-
如果挂载了宿主机目录(如-v /:/host),容器内root可以直接修改宿主机文件;
-
如果挂载了
/var/run/docker.sock且可访问 Docker API,容器内进程通常可以获得近似宿主机 root 的控制能力; -
存在内核漏洞时,容器内root可以直接提权到宿主机root。
5.1.1.2 攻防思路
常见逃逸途径
| 逃逸方式 | 原理 |
|---|---|
--privileged 特权容器 |
获得大量 capabilities 和设备访问权,并削弱默认安全限制;风险接近宿主机管理权限 |
挂载 docker.sock |
容器内可通过 Docker API 控制宿主机 |
| 挂载宿主机目录 | 直接读写宿主机文件 |
| 内核漏洞 | namespace隔离被内核漏洞绕过 |
防御思路:业务进程使用非 root 用户运行,避免不必要的特权、宿主机目录和 Docker socket 挂载,并及时更新宿主机内核及容器运行时。非 root 能缩小影响范围,但不能单独保证容器无法逃逸。
示例:以非 root 用户运行
自定义镜像已创建 UID 888 的 nginx 用户。先检查默认启动身份,再显式以该用户启动:
docker run -d --name nginx-test nginx-alpine:1.29
docker exec nginx-test id
docker rm -f nginx-test
docker run -d --name nginx-user --user 888:888 nginx-alpine:1.29
docker exec nginx-user id
docker exec nginx-user ps -o pid,user,args
docker rm -f nginx-user
以非 root 用户运行时,还要检查镜像目录权限、Nginx PID 和临时目录、监听端口。低端口能否绑定取决于进程 capabilities 及网络命名空间中的 net.ipv4.ip_unprivileged_port_start;不要假设 Docker 一定会给非 root 进程 CAP_NET_BIND_SERVICE。可让应用监听高端口,再由宿主机或代理发布 80/443。
只读根文件系统
5.1.2.1 功能简介
默认情况下,容器根文件系统可写。攻击者可能修改其中的程序、配置或临时文件。使用 --read-only 可以阻止对根文件系统的写入;挂载卷、tmpfs、套接字和外部服务仍有各自的写入能力,需单独限制。
为什么需要只读根文件系统?
- 业务进程运行时不需要修改自己的程序文件和配置文件;
- 如果容器被入侵,攻击者无法写入恶意文件到磁盘;
- 容器重建时,未挂载为持久化卷的数据通常会丢失;卷和宿主机挂载中的数据不会因此恢复或清除。
应用可能需要写临时文件、PID 或缓存。只为确有需要的路径挂载 --tmpfs 或受控卷,并按需设置容量、权限和 noexec 等选项。tmpfs 内容在容器停止后消失。
Nginx场景下需要写入的目录:
| 目录 | 用途 | 处理方式 |
|---|---|---|
| /tmp | 临时文件 | tmpfs挂载 |
| /data/server/nginx/logs | Nginx日志 | 配置日志输出到stdout/stderr,不写文件 |
| /data/server/nginx/conf/nginx.conf | 配置文件 | 只读,不需要写入 |
示例:只读运行
docker run -d --name nginx-ro --read-only \
--tmpfs /tmp:rw,noexec,nosuid,size=64m \
nginx-alpine:1.29
镜像若还要写 PID、缓存或日志目录,需按实际配置增加有限的可写挂载。只读根文件系统不会自动把日志转到 stdout/stderr。
[root@ubuntu24-13 ~ ]# docker logs 16bffd10faa5
nginx: [alert] could not open error log file: open()
"/data/server/nginx/logs/error.log" failed (30: Read-only file system)
... [emerg] 1#0: mkdir() "/data/server/nginx/client_body_temp" failed (30: Read-only file system)
验证只读根文件系统
docker run --rm busybox sh -c 'echo hello > /tmp/test.txt && cat /tmp/test.txt'
docker run --rm --read-only busybox sh -c 'echo hello > /tmp/test.txt'
docker run --rm --read-only --tmpfs /tmp:rw,noexec,nosuid,size=16m \
busybox sh -c 'echo hello > /tmp/test.txt && cat /tmp/test.txt'
Linux capabilities
5.1.3.1 功能简介
Linux capabilities 将传统 root 特权拆分为独立权限。Docker 的默认集合通常包含下列 14 项,但会受引擎版本和安全配置影响;不要把默认集合当作应用所需权限清单。
| capability | 作用 |
|---|---|
CHOWN |
修改文件所有者 |
DAC_OVERRIDE |
绕过常规文件读写和执行权限检查 |
FOWNER |
绕过要求进程 UID 与文件所有者匹配的检查 |
FSETID |
修改文件时保留 setuid/setgid 位 |
KILL |
向不属于当前用户的进程发送信号 |
MKNOD |
创建设备文件 |
NET_BIND_SERVICE |
绑定特权端口;实际还受网络命名空间 sysctl 影响 |
NET_RAW |
使用 RAW 和 packet socket |
SETFCAP |
设置文件 capabilities |
SETGID |
设置进程 GID 和补充组 |
SETPCAP |
修改进程 capability 集合 |
SETUID |
设置进程 UID |
SYS_CHROOT |
使用 chroot |
AUDIT_WRITE |
写入内核审计日志 |
高风险权限包括 SYS_ADMIN、SYS_MODULE、SYS_PTRACE 和 NET_ADMIN。它们分别涉及大量系统管理操作、内核模块、进程调试和网络配置;是否能影响宿主机还取决于 namespace、设备和其他隔离措施。除非有明确需求,不要添加。
最小权限做法是先 --cap-drop=ALL,再按应用实际功能逐项添加,并在目标运行环境验证。
查看与限制 capabilities
查看当前容器默认的 capabilities
docker run --rm nginx-alpine:1.29 sh -c 'grep "^Cap" /proc/1/status'
docker run --rm --user 888:888 --cap-drop=ALL \
nginx-alpine:1.29 sh -c 'id; grep "^Cap" /proc/1/status'
CapEff 是当前生效集合,CapBnd 是后续可获得能力的边界;十六进制值会随运行时配置变化。需要解码时,可在宿主机安装 libcap2-bin 后运行 capsh --decode=0x<CapEff值>。普通用户进程通常没有有效 capabilities,即使 CapBnd 仍列出可用上限。
确实需要绑定低端口时,先检查容器网络命名空间中的 net.ipv4.ip_unprivileged_port_start。只有该值不允许普通用户绑定且应用必须监听低端口时,才尝试添加 NET_BIND_SERVICE;更简单的方案通常是让应用监听高端口并映射到宿主机 80/443。
--privileged 会显著扩大容器权限,不应用作 capability 测试的默认方式。
容器加固案例
5.2.1 案例概述
5.2.1.1 案例介绍
RuoYi-Vue 项目由四个容器化服务组成。下面的端口和认证配置只用于说明风险,不能直接用于生产。
| 服务 | 镜像 | 端口 | 数据目录 |
|---|---|---|---|
| Redis | ruoyi-vue-redis:v1 | 6379 | /data |
| MySQL | mysql:oraclelinux9 | 3306 | /var/lib/mysql |
| 后端 | ruoyi-admin:v1 | 8080 | /data/ruoyi/uploadPath |
| Nginx | ruoyi-vue-nginx:1.29.0 | 80, 443 | /data/ruoyi/web/dist |
未加固的启动示例
# 以下命令省略认证,仅用于隔离测试环境;端口只绑定本机
docker run -d -p 127.0.0.1:6379:6379 --name ruoyi-vue-redis ruoyi-vue-redis:v1
docker run -d -p 127.0.0.1:3306:3306 --name ruoyi-vue-mysql mysql:oraclelinux9
docker run -d -p 127.0.0.1:8080:8080 --name ruoyi-admin ruoyi-admin:v1
docker run -d -p 127.0.0.1:8081:80 --name ruoyi-vue-nginx ruoyi-vue-nginx:1.29.0
5.2.1.2 风险列表
上面的命令存在以下安全隐患
未使用非 root 身份:进程被攻破后的影响范围可能更大
数据库端口对外发布:增加未授权访问和暴力破解风险
根文件系统可写、权限未收敛:可能扩大入侵后的持久化能力
未限制日志大小:日志增长可能占满磁盘
未配置健康检查和重启策略:故障不易发现或恢复
加固思路
1. 镜像安全:Trivy 漏洞扫描
2. 非root运行:使用镜像支持的普通用户
3. 只读根文件系统:--read-only + --tmpfs
4. Capabilities最小化:--cap-drop=ALL --cap-add=...
5. 日志管理:--log-opt max-size/max-file
6. 健康检查:--healthcheck-*
7. 重启策略:--restart
5.2.2 安全加固
5.2.2.1 镜像安全
运行时加固不能消除镜像已知漏洞带来的风险。Trivy 首次扫描需要下载漏洞数据库;网络受限时,可配置组织维护且可信的镜像仓库,不要默认信任任意第三方数据库镜像。
在宿主机安装 Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh \
| sudo sh -s -- -b /usr/local/bin
ls /usr/local/bin/trivy
命令格式
trivy image <镜像:标签>
# 仅在组织信任并维护该镜像源时,替换默认漏洞数据库仓库
trivy image \
--db-repository ghcr.nju.edu.cn/aquasecurity/trivy-db:2 \
--java-db-repository ghcr.nju.edu.cn/aquasecurity/trivy-java-db:1 \
<镜像:标签>
# 输出 JSON,供 CI 归档或后续处理
trivy image --format json --output result.json <镜像:标签>
# 让指定严重级别的漏洞使命令返回非零状态,供 CI 阻断
trivy image --exit-code 1 --severity HIGH,CRITICAL <镜像:标签>
镜像名字
trivy image --severity HIGH,CRITICAL ruoyi-vue-redis:v1
trivy image --severity HIGH,CRITICAL mysql:oraclelinux9
trivy image --severity HIGH,CRITICAL ruoyi-admin:v1
trivy image --severity HIGH,CRITICAL ruoyi-vue-nginx:1.29.0
发现漏洞后,先确认受影响组件、可利用条件和修复版本,再升级基础镜像或依赖并重新构建扫描。精简镜像可减少组件数量,但不能替代漏洞修复和更新。
5.2.2.2 Redis加固
以下示例假设镜像支持 REDIS_PASSWORD 环境变量、默认以非 root 用户运行,并在同一 Docker 网络中供后端访问。请按实际镜像配置调整。生产环境优先使用 Docker secrets 或权限受限的环境文件;有 Docker API 权限的用户仍可读取容器环境变量。
read -rsp 'Redis password: ' REDIS_PASSWORD; export REDIS_PASSWORD; echo
docker network inspect ruoyi-internal >/dev/null 2>&1 || docker network create ruoyi-internal
docker run -d --name ruoyi-vue-redis --network ruoyi-internal \
--restart=unless-stopped --read-only --tmpfs /tmp:rw,noexec,nosuid,size=16m \
--cap-drop=ALL --security-opt no-new-privileges \
--log-opt max-size=10m --log-opt max-file=3 \
-e REDIS_PASSWORD -v /data/ruoyi-vue/redis/data:/data \
ruoyi-vue-redis:v1
参数解读
--read-only # 根文件系统只读,防止篡改
--tmpfs /tmp # Redis临时文件写到内存,重启即清
--cap-drop=ALL # Redis不需要任何特权能力
--log-opt max-size=10m # 日志单文件最大 10MB
--log-opt max-file=3 # 最多保留 3 个日志文件
--restart=unless-stopped # 崩溃自动重启,手动停止后不自动拉起
示例未配置 Redis 健康检查;不同镜像的认证参数和健康检查工具不同,应按镜像文档补充。
测试效果
REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h ruoyi-vue-redis info Replication
5.2.2.3 MySQL加固
MySQL 镜像的启动用户、数据目录权限和写入需求因版本而异。不要假定 UID/GID 或 capability;先按所用镜像文档初始化数据目录并验证权限。以下示例将数据库限制在内部网络,初始化和检查通过 docker exec 执行,不发布数据库端口。
read -rsp 'MySQL root password: ' MYSQL_ROOT_PASSWORD; export MYSQL_ROOT_PASSWORD; echo
read -rsp 'RuoYi database password: ' MYSQL_PASSWORD; export MYSQL_PASSWORD; echo
docker run -d --name ruoyi-vue-mysql --network ruoyi-internal \
--restart=unless-stopped -e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD -e MYSQL_DATABASE=ry_vue \
-e MYSQL_USER=ruoyi -e MYSQL_PASSWORD \
--log-opt max-size=10m --log-opt max-file=3 \
-v /data/ruoyi-vue/mysql/sql:/tmp/sql:ro \
-v ruoyi-mysql-data:/var/lib/mysql mysql:oraclelinux9 \
--character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
参数解读
--restart=unless-stopped # 崩溃自动重启,手动停止后不自动拉起
数据库需要写入数据目录,因此不能直接将整个根文件系统设为只读,除非已为数据及其他必要路径配置可写挂载。命名卷提供数据持久化,不代表数据自动加密或访问受控。
环境初始化(使用已创建的 root 密码)
# 数据库初始化
docker exec -i -e MYSQL_PWD="$MYSQL_ROOT_PASSWORD" ruoyi-vue-mysql mysql -uroot ry_vue < /data/ruoyi-vue/mysql/sql/ry_schema.sql
# 确认效果
docker exec -e MYSQL_PWD="$MYSQL_ROOT_PASSWORD" ruoyi-vue-mysql mysql -uroot -e "show tables from ry_vue;"
docker exec -e MYSQL_PWD="$MYSQL_ROOT_PASSWORD" ruoyi-vue-mysql mysql -uroot -e "select menu_name from ry_vue.sys_menu;"
5.2.2.4 ruoyi-admin加固
后端和数据库应加入同一内部网络;如需从宿主机调试,将端口绑定到 127.0.0.1。JAVA_OPTS 是否生效取决于镜像入口脚本。
docker run -d --name ruoyi-admin --network ruoyi-internal --restart=unless-stopped \
-p 127.0.0.1:8080:8080 -e TZ=Asia/Shanghai \
-e JAVA_OPTS="-Xms256m -Xmx512m" ruoyi-admin:v1
测试效果
浏览器访问:http://127.0.0.1:8080/druid
5.2.2.5 Nginx加固
以下示例假设镜像存在 nginx 用户,并已配置日志和临时目录权限。是否需要 NET_BIND_SERVICE 取决于容器网络命名空间的低端口设置;本例仅发布到本机高端口,供宿主机代理访问。
docker run -d --name ruoyi-vue-nginx --network ruoyi-internal --restart=unless-stopped \
-p 127.0.0.1:8081:80 -e TZ=Asia/Shanghai --user nginx:nginx --cap-drop=ALL \
--security-opt no-new-privileges --log-opt max-size=10m --log-opt max-file=3 \
--health-cmd="wget -q --spider http://127.0.0.1:80/" \
--health-interval=30s --health-timeout=3s --health-retries=3 \
ruoyi-vue-nginx:1.29.0
参数解读
--cap-drop=ALL # 移除默认 capabilities;需验证服务是否仍能正常运行
--log-opt max-size=10m # 单个日志文件最大 10MB
--log-opt max-file=3 # 最多保留 3 个文件
健康检查命令依赖镜像中存在 wget,不适用时应替换为镜像内可用的检查方式。
测试效果
浏览访问:http://127.0.0.1:8081
镜像与运行时检测

Trivy 漏洞扫描
8.1.1.1 工具简介
Trivy 是 Aqua Security 开源的安全扫描器,可检查镜像中的操作系统软件包和语言依赖,也可扫描文件系统、代码仓库及 IaC 配置。
在 CI 流水线中,可按项目策略对 HIGH、CRITICAL 漏洞设置阻断门槛。扫描结果仍需结合是否可利用、是否有修复版本和业务暴露面判断。
在宿主机安装 Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh \
| sudo sh -s -- -b /usr/local/bin
ls /usr/local/bin/trivy
8.1.1.2 功能梳理
常用扫描目标
| 命令 | 作用 | 典型场景 |
|---|---|---|
trivy image <镜像:tag> |
扫描容器镜像 | 镜像构建后、推送前 |
trivy filesystem <路径> |
扫描本机目录或文件系统 | 主机目录、解包后的文件系统 |
trivy repo <git-url> |
扫描 Git 仓库 | 代码提交阶段 |
CVE 严重级别与修复优先级
| 级别 | 含义 | 处置建议 |
|---|---|---|
| CRITICAL | 可被远程利用、易导致沦陷 | 立即修复/阻断上线 |
| HIGH | 高危,常被攻击链利用 | 尽快修复 |
| MEDIUM | 中危,需结合场景评估 | 计划性修复 |
| LOW | 低危 | 评估后可延后 |
| UNKNOWN | 无明确分级 | 人工研判 |
优先级不能只按 CRITICAL、HIGH、MEDIUM、LOW 排序;还要结合是否可从外部触达、是否存在利用条件及是否有修复版本。
命令格式
# 扫描镜像
trivy image <镜像:tag>
# 网络受限时,仅使用组织维护且信任的漏洞数据库镜像
trivy image --db-repository <可信数据库仓库> <镜像:tag>
镜像名字
# 筛选高危和严重漏洞,并在发现时返回非零状态
trivy image --severity HIGH,CRITICAL --exit-code 1 <镜像:tag>
# 输出 JSON 报告
trivy image --format json --output result.json <镜像>
8.1.1.3 简单实践
镜像扫描
trivy image --severity HIGH,CRITICAL ruoyi-admin:v1
CI场景下实践命令
if trivy image --severity HIGH,CRITICAL --exit-code 1 ruoyi-admin:v1; then
echo '扫描通过'
else
echo '发现高危或严重漏洞,阻断推送'
exit 1
fi
其他的测试命令
# 扫描部署项目的目录
trivy filesystem /data/ruoyi-vue/ruoyi-admin/file/
# 输出 JSON 报告供归档,并查看漏洞名称
trivy image --format json --output /tmp/trivy-ruoyi-admin.json ruoyi-admin:v1
jq '.Results[].Vulnerabilities[] | select(.Severity=="CRITICAL") |
.VulnerabilityID' /tmp/trivy-ruoyi-admin.json
8.1.1.4 漏洞处理
优先升级受影响的基础镜像或依赖,验证后重新构建并扫描。多阶段构建可减少最终镜像中的构建依赖,但不会自动修复运行时依赖漏洞。无法立即修复时,应记录漏洞编号、影响评估、补偿控制、责任人和复核日期;只对已评估的漏洞使用 .trivyignore,不要为了让扫描通过而批量忽略。
# 输出 JSON 报告供归档
trivy image --severity HIGH,CRITICAL --format json --output alpine-report.json alpine:3.24.0
生成报告供人工研判,以 ruoyi-admin:v1 为例
[root@ubuntu24-13 ~ ]# trivy image --format json --output /tmp/trivy-ruoyi-admin.json ruoyi-admin:v1
[root@ubuntu24-13 ~ ]# jq '.Results[].Vulnerabilities[] |
select(.Severity=="CRITICAL") | .VulnerabilityID' /tmp/trivy-ruoyi-admin.json
8.1.2 镜像安全基线
8.1.2.1 工具简介
Dockerfile安全基线不是某个软件,而是一组编写Dockerfile时必须遵守的安全规范。它解决 "镜像从源头就带病" 的问题 -- 很多漏洞/隐患是在构建期被写进镜像的 硬编码密码、保留编译工具、以 root 运行等。
| 基线 | 要求 | 反例 --> 正例 |
|---|---|---|
| 使用官方基础镜像 | 优先 alpine 、distroless 、官方版本镜像 | FROM node --> FROM node:20-alpine |
| 定期更新基础镜像 | 版本写死并纳入升级计划,及时换新 | FROM ubuntu:22.04 长期不升级 --> 追踪新patch |
| 不硬编码密码/密钥 | 用Build Secret或运行时环境变量注入 | ENV MYSQL_PWD=123 --> --secret 或-e 注入 |
| 最小化镜像层 | 合并同类 RUN、减少层数 | 多个RUN apt-get --> 合并为一个RUN |
| 删除构建工具与缓存 | 装完即清、多阶段构建剥离编译链 | 保留 gcc/make --> 多阶段构建只留产物 |
| 非 root 运行 | 用 USER 切换到普通用户 | root 跑进程 --> USER appuser |
合理的 Dockerfile 可以减少镜像中的冗余组件和攻击面,但仍需持续更新并扫描。
8.1.2.2 简单实践
定制一个能用的,但是出现各种问题的Dockerfile
# 非官方精简版、版本不固定
FROM nginx:latest
# 硬编码密码
RUN echo "root:123456" | chpasswd
# 保留编译工具
RUN apt-get update && apt-get install -y gcc make
# 层未合并
RUN apt-get install -y curl zip
EXPOSE 80
# root 运行
CMD ["nginx"]
改造后的Dockerfile
以下示例假设 nginx-alpine:1.29 是已配置为普通用户监听 8080、日志输出到标准输出且 PID/缓存目录可写的基础镜像。仅设置 USER nginx 并不会自动完成这些配置。
# ===== 运行阶段 =====
FROM nginx-alpine:1.29
ENV NGINX_DIR=/data/server/nginx
# 版本固定,多层合并
RUN apk --no-cache add tzdata && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# 创建运行时目录并设置所有者
RUN mkdir -p ${NGINX_DIR} && chown nginx:nginx ${NGINX_DIR} && chmod 750 ${NGINX_DIR}
# 非root用户运行
USER nginx
EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]
构建测试
# 构建镜像
docker build -t nginx-base-safe:v1 .
# 检查是否非 root
docker run --rm nginx-base-safe:v1 id
# 扫描镜像漏洞
trivy image nginx-base-safe:v1
8.1.3 Falco运行时安全
8.1.3.1 工具简介
Falco 是 CNCF 云原生计算基金会项目,最初由 Sysdig 开源。它通过监控系统调用检测匹配规则的异常行为并告警;告警本身不会阻止攻击,也不能替代隔离、补丁和访问控制。
Falco 常部署在 Kubernetes 或 Docker 宿主机上,检测例如读取敏感文件、启动异常 shell 或写入敏感目录等行为。能否告警取决于启用的驱动和规则。
典型异常行为
容器内启动Shell: 攻击者常先起/bin/bash做后续操作
敏感文件读取: 如读取/etc/shadow、/etc/passwd
特权容器创建: 检测到--privileged容器被拉起
非预期出站连接: 容器向未知外部IP发起连接
写入敏感目录: 如写入/etc、/root
8.1.3.2 功能解读
falco规则的结构解读
文件名:falco_rules.yaml
规则内容:
- rule: 规则名字
desc: 规则描述
condition: 规则判断条件
output: 输出信息
priority: 问题级别
容器方式安装falco
docker pull falcosecurity/falco:<固定版本>
Falco 的驱动部署方式取决于宿主机内核、驱动版本和运行时。容器化部署可能需要高权限、内核模块或 eBPF 相关能力,以及宿主机路径挂载;不要直接复制 --privileged 启动命令。应按 Falco 官方部署文档选择当前环境支持的驱动和最小权限配置。挂载 Docker socket 会授予 Docker API 的控制能力,应避免非必要挂载。
检查运行效果
docker logs -f falco
8.1.3.3 简单实践
在另一个终端进入一个普通容器并读取敏感文件
# 容器A:故意读取/etc/shadow
docker run --rm --name victim -it alpine:3.24 sh -c "cat /etc/shadow"
检查Falco日志
[root@ubuntu24-13 ~ ]# docker logs falco
...
# 出现如下信息提示
...: Warning Sensitive file opened for reading by non-trusted program |
file=/etc/shadow gparent=systemd ...
8.1.3.4 规则实践
- list: my_private_files
items: [/etc/shadow, /etc/gshadow]
- rule: Read sensitive account files
desc: Detect reads of local account database files
condition: evt.type in (open, openat) and fd.name in (my_private_files) and evt.is_open_read=true
output: "Sensitive account file opened for reading (file=%fd.name user=%user.name process=%proc.name container=%container.name)"
priority: WARNING
使用规则启动
# 按本机内核和驱动选择官方启动参数,将规则文件只读挂载到 /etc/falco/rules.d/。
在另一个终端进入一个普通容器并读取敏感文件
# 容器A:故意读取/etc/shadow
docker run --rm --name victim -it alpine:3.24 sh -c "cat /etc/shadow"
检查Falco日志
[root@ubuntu24-13 ~ ]# docker logs falco
...
# 可以看到如下的信息内容
...: Warning Sensitive account file opened for reading (file=/etc/shadow ...)
评论