ArmyCyberInstitute/cmgr

GitHub: ArmyCyberInstitute/cmgr

cmgr 是一个基于 Go 和 Docker 的 Jeopardy 式 CTF 题目开发与管理后端,通过 CLI 和 REST API 简化题目创建、测试和比赛托管流程。

Stars: 17 | Forks: 10

# cmgr **cmgr** 是一个全新的后端,旨在简化 Jeopardy 式 CTF 的题目开发与管理。它提供了一个用于开发和管理后端题目服务器上可用题目的 CLI (`cmgr`),以及一个 REST 服务器 (`cmgrd`),后者暴露了前端 Web 界面进行比赛或训练平台托管所需的最低限度命令集。 ## 快速开始 假设你已经安装了 Docker,以下代码片段将下载示例题目和 **cmgr** 二进制文件,初始化一个用于跟踪这些题目元数据的数据库文件,然后运行测试套件以确保系统正常工作。测试套件可能需要几分钟时间运行,且并非开始工作所必需。然而,在你首次于系统上使用 `cmgr` 时,运行该套件可以帮助识别权限及其他错误,强烈建议执行。 ``` wget https://github.com/ArmyCyberInstitute/cmgr/releases/latest/download/examples.tar.gz wget https://github.com/ArmyCyberInstitute/cmgr/releases/latest/download/cmgr_`uname -s | tr '[:upper:]' '[:lower:]'`_amd64.tar.gz tar xzvf examples.tar.gz cd examples tar xzvf ../cmgr_`uname -s | tr '[:upper:]' '[:lower:]'`_amd64.tar.gz ./cmgr update CMGR_LOGGING=info ./cmgr test --require-solve ``` **注意:** 如果你是在基于 ARM 架构的计算机上运行此程序,则需要将 cmgr 压缩包中的 `amd64` 修改为 `arm64`。 此时,你可以通过查找你想体验的题目的挑战 ID 并运行 `./cmgr playtest ` 来开始查看题目。这将构建并启动题目,同时运行一个最小化的 Web 服务器(默认为 `localhost:4200`),你可以使用它来查看内容并进行交互。你也可以使用 `./cmgrd` 在 4200 端口启动 REST 服务器,或者使用 `./cmgr test --no-solve` 从 CLI 启动所有示例,这将启动每个示例题目的实例并打印相关的端口信息。 ## 配置 **cmgr** 使用环境变量进行配置。具体来说,它目前使用以下变量: - *CMGR\_DB*:cmgr 数据库文件的路径(默认为 'cmgr.db') - *CMGR\_DIR*:包含所有题目的目录(默认为 '.') - *CMGR\_ARTIFACT\_DIR*:用于存储产物包的目录(默认为 '.') - *CMGR\_LOGGING*:命令客户端的日志详细程度(`cmgr` 默认为 'disabled',`cmgrd` 默认为 'warn';有效选项包括 `debug`、`info`、`warn`、`error` 和 `disabled`) - *CMGR\_INTERFACE*:发布的题目端口应绑定到的宿主机接口/地址(默认为 '0.0.0.0')(*注意*:如果指定的地址未绑定到运行 Docker 守护进程的宿主机,此值将被 Docker 静默忽略,并且暴露的端口将绑定到回环接口。) - *CMGR\_PORTS*:专用于提供题目服务的端口范围;cmgr 将假定它完全拥有这些端口,且没有其他程序会尝试使用它们(即,不在临时端口范围内,也不与宿主机上运行的服务重叠);格式为 '1000-1000'。可以使用 `cat /proc/sys/net/ipv4/ip_local_port_range` 枚举 Linux 宿主机上的临时端口,并使用 `sysctl` 进行调整。调整内核参数后,某些程序(例如 `docker`)需要重新启动。 - *CMGR\_ENABLE\_DISK\_QUOTAS*:设置后启用[磁盘配额](examples/markdown_challenges.md#challenge-options)容器选项。磁盘配额仅在使用 `overlay2` Docker 存储驱动和启用了 [pquota](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/storage_administration_guide/xfsquota) 的 XFS 后端存储时有效。否则,在运行时创建带有磁盘配额的容器将会失败。未设置时,任何指定的配额都将被忽略。 此外,我们依赖于 Docker SDK 根据环境变量进行自配置的能力。有关这些变量的文档可以在 [https://docs.docker.com/engine/reference/commandline/cli/](https://docs.docker.com/engine/reference/commandline/cli/) 找到。 ### Seccomp OCI 拦截器 大多数部署不需要额外的 seccomp 设置:当题目省略 `seccomp` 选项时,Docker 会直接应用其当前的默认配置文件。遗留和完整的题目提供配置文件也使用 Docker 的常规 `security-opt` 支持。 命名的 seccomp `tweaks` 需要将 `cmgr-oci-interceptor` 二进制文件安装在运行 Docker 守护进程的 Linux 宿主机上。拦截器在 Docker 扩展其当前的 seccomp 默认设置后接收 OCI 配置,应用所请求的微小更改,从容器环境中移除 cmgr 的控制值,然后调用 `runc`。 从 cmgr 发布归档文件中安装该二进制文件,并将其放置在 Docker 宿主机上属于 root 用户的可执行目录中: ``` sudo install -o root -g root -m 0755 cmgr-oci-interceptor /usr/local/bin/cmgr-oci-interceptor ``` 然后让拦截器安全地将自身合并到 Docker 的配置中并重新加载守护进程: ``` sudo cmgr-oci-interceptor register ``` `/etc/docker/daemon.json` 中生成的条目等同于: ``` { "runtimes": { "cmgr-oci-interceptor": { "path": "/usr/local/bin/cmgr-oci-interceptor", "runtimeArgs": [ "--cmgr-interceptor-protocol=seccomp-v1", "--cmgr-runtime-path=/usr/bin/runc" ] } } } ``` 确切路径取决于宿主机。默认情况下,该命令会解析被调用的 `cmgr-oci-interceptor` 可执行文件和 `runc` 的规范绝对路径。使用 `--runtime-path=/absolute/path/to/cmgr-oci-interceptor` 或 `--runc-path=/absolute/path/to/runc` 显式选择不同的已安装可执行文件。其他选项允许指定替代的 `--config` 路径,使用 `--force` 替换冲突的注册,或使用 `--no-reload` 延迟 Docker 的重新加载。 对于系统 Docker 配置,注册操作会拒绝非 root 用户拥有,或属于组可写/全局可写权限的可执行文件或父目录。它会在持有注册锁的同时原子性地更新 `daemon.json`,重新加载 Docker,并验证守护进程报告的路径和协议参数是否完全一致。当已安装的 `dockerd` 支持配置验证时,该命令还会在重新加载之前验证合并后的文件。如果验证、重新加载或验证失败,它会恢复之前的配置;在尝试重新加载后,它也会重新加载恢复后的配置。 对于远程 Docker 守护进程,必须在守护进程宿主机上安装这两个二进制文件并运行注册命令,而不仅仅是在 Docker 客户端机器上执行。 启动时,如果未注册命名的 runtime,cmgr 会发出警告并打印注册命令。这不会阻止没有 tweaks 的题目运行。cmgr 仅针对具有 `seccomp.tweaks` 设置的题目容器选择该 runtime,如果 runtime 不可用,它会直接报错,而不是静默忽略所请求的 tweak。构建器、产物和解题器容器会继续使用 Docker 的默认 runtime。 拦截器的设计改编自 [`picoCTF/oci-interceptor`](https://github.com/picoCTF/oci-interceptor),基于 Apache License 2.0 使用。具体的来源声明记录在拦截器包和项目的 `NOTICE` 中。 ## 开发中... ### 题目 我们的设计目标之一是使 CTF 题目的开发尽可能简单,以便开发者可以专注于内容本身,而不是平台的特殊行为。我们提供了特定的题目类型,使得尽可能轻松地创建特定风格的新题目成为可能,每种类型的文档及其使用方法都在 [示例](examples/) 目录中。 此外,我们提供了一个简单的接口来为你的题目创建自动化解题器。这就像创建一个名为 `solver` 的目录并在其中放入一个名为 `solve.py` 的 Python 脚本一样简单。这个脚本将在与其正在检查的实例相同的网络中拥有自己的 Docker 容器,并在其工作目录中包含所有产物文件和提供给参赛者的附加信息。一旦它解决了题目,只需将 flag 的值写入其当前工作目录中名为 `flag` 的文件中,**cmgr** 就会验证答案并将其报告给用户。 在题目和解题器这两种情况下,我们都支持题目作者使用自定义 Dockerfile,以支持超越最常见题目类型的创意挑战。为了支持系统的其他自动化功能,在 Docker 镜像的构建阶段需要创建某些文件,这些要求已在 `custom` 题目类型示例中进行了说明。 测试题目的目的在于使其像在单个题目的目录或包含活动所有题目的目录中执行 `cmgr test` 一样简单。这旨在为开发者提供快速反馈循环,并支持在活动准备期间进行自动化的质量控制。 ### 前端 该项目的另一个设计初衷是让 CTF 的自定义前端界面更容易重用现有的内容/题目,而不是强迫组织者在不同系统之间进行移植。为了实现这一点,`cmgrd` 暴露了一个非常简单的 REST API,允许前端管理运行比赛或训练环境的所有重要任务。OpenAPI 规范可以在[这里](cmd/cmgrd/swagger.yaml)找到。 ### 后端 如果你有兴趣贡献代码、修改或扩展 **cmgr**,该项目的核心功能是在 `cmgr` 目录下的单个 Go 库中实现的。你可以在 [go.dev](https://pkg.go.dev/github.com/ArmyCyberInstitute/cmgr/cmgr) 上查看 API 文档。 此外,_SQLite3_ 数据库旨在作为只读 API 使用,其 schema 可以在[这里](cmgr/database.go)找到。 后端开发需要 Go 1.25 或更高版本;发布版本是使用 Go 1.26 构建的。SQLite 驱动是纯 Go 实现的,因此不需要 C 工具链。cmgr 支持的 Docker 守护进程最低版本为 Engine 25。要开始使用,请运行: ``` git clone https://github.com/ArmyCyberInstitute/cmgr cd cmgr go mod download go mod verify mkdir bin go build -trimpath -o bin/ ./cmd/... go test -v ./... ``` ## 生成式 AI 披露 请注意,从 v0.14.0 开始的发布版本是在生成式 AI 的辅助下进行现代化的。 在使用生成式 AI 的提交信息中,每一条都描述了过程中使用的模型、测试工具和配置。此外,生成式 AI 还被用于在一套题目中运行确定性的回归测试。 具体在 v0.14.0 中,生成式 AI 使得一项修改成为可能,即支持为每个单独的容器提供自定义 seccomp 配置文件,并默认使用 docker 运行时的 seccomp 配置文件。此外,此版本中相关库和示例题目的版本号提升至 2026。 ## 致谢 本项目深受 [picoCTF](https://github.com/picoCTF/picoCTF) 平台的启发,并力求成为采用其风格构建的 CTF 平台的下一代 _hacksport_ 后端实现。 ## 贡献 请仔细阅读 [NOTICE](NOTICE)、[CONTRIBUTING](CONTRIBUTING.md)、[DISCLAIMER](DISCLAIMER.md) 和 [LICENSE](LICENSE) 文件,以了解有关如何为本项目做出贡献,以及在贡献时有关版权和许可情况的详细信息。
标签:Docker, REST API, 后端开发, 安全防御评估, 日志审计, 请求拦截, 赛事管理, 逆向工具