kingkyylian/linwarden

GitHub: kingkyylian/linwarden

Linwarden 是一款无 root 权限的 Linux 安全加固扫描工具,专为 CI 流水线和资产快速分诊而设计,能在零依赖下检测常见的风险配置。

Stars: 2 | Forks: 1

# Linwarden [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/kingkyylian/linwarden/actions/workflows/ci.yml) [![PyPI](https://img.shields.io/pypi/v/linwarden.svg)](https://pypi.org/project/linwarden/) [![Python](https://img.shields.io/badge/python-3.9%2B-blue.svg)](pyproject.toml) [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE) Linwarden 是一款无 root 权限的 Linux 强化扫描工具,专为 CI 和资产分诊设计。它读取普通系统文件(如 `/etc/os-release`、`/etc/ssh/sshd_config` 以及选定的 `/proc/sys` 值),随后生成 Markdown、JSON 或 SARIF 产物,全程无需安装任何 agent、daemon、特权辅助程序、数据库或网络服务。 本项目的目标非常务实:为维护者提供一款小巧且可审计的工具,用于揭示存在风险的 Linux 默认配置,且无需依赖 agent、daemon、特权服务、外部数据库或网络访问。 ## 为什么选择 Linwarden 当您需要快速了解安全态势信号,而不是一个笨重的合规平台时,请使用 Linwarden。 | 需求 | Linwarden 方案 | | --- | --- | | 对 CI 友好的输出 | 提供用于 GitHub 代码扫描的 JSON、Markdown 和 SARIF 格式。 | | 低运营风险 | 以只读方式从普通 Linux 文件中收集信息。 | | 离线分析 | 可扫描已挂载的根目录、解压的镜像、容器以及测试固件。 | | 可解释的发现结果 | 每条规则均包含证据、影响、修复建议及参考来源。 | | 极简供应链 | 除 Python 3.9+ 外,零运行时依赖。 | Linwarden 并非要替代 CIS 或 STIG。它是一款轻量级的“第一道防线”工具,可在运维人员动用更重型的扫描器之前,告知他们哪些问题值得关注。 ## 30 秒信号展示 Linwarden 旨在让审查者在阅读冗长报告之前,就能直观地发现存在风险的 Linux 默认配置。针对合成的测试固件根目录运行的结果如下: ``` $ linwarden scan --root tests/fixtures/linux-root --format markdown --fail-on off # Linwarden 报告 - Host: `fixture-box` - Score: `0/100` - Findings: `17` | Severity | Rule | Title | Evidence | | --- | --- | --- | --- | | HIGH | LNX-SSH-001 | SSH root login is permitted | PermitRootLogin yes | | MEDIUM | LNX-SSH-002 | SSH password authentication is enabled | PasswordAuthentication yes | | HIGH | LNX-KRN-001 | Address space layout randomization is disabled | kernel.randomize_va_space=0 | | MEDIUM | LNX-FW-001 | Host firewall is disabled | ufw firewall disabled | ``` 如需了解 SARIF/代码扫描工作流,请查看完整的[合成终端演示](docs/assets/terminal-demo.md)以及 [GitHub Actions 示例](docs/github-actions.md)。 ## 发布来源 当前版本的发布产物发布在 [GitHub 发布页面](https://github.com/kingkyylian/linwarden/releases/tag/v0.15.0),该包也可从 [PyPI](https://pypi.org/project/linwarden/) 获取。 每个标签版本的发布都包含 `SHA256SUMS` 校验和文件,以及针对构建的源码和 wheel 文件的 GitHub 产物证明(artifact attestations)。验证指南详见 [docs/release.md#artifact-attestations](docs/release.md#artifact-attestations),其中包括 `gh attestation verify` 命令的使用方法。 ## 功能 - 以无 root 权限方式从 `/etc`、`/proc` 以及 procfs sysctl 路径中收集信息。 - 为 CI 流水线和定时主机扫描提供确定性的 JSON 输出。 - 提供 Markdown 格式输出,适合用于 GitHub 作业摘要(job summaries)和 Issue 附件。 - 提供 SARIF 格式输出,适合 GitHub 原生安全检测结果接入。 - 支持 JSON 配置文件,可用于配置 profiles、禁用规则以及合理的抑制项。 - 可选的有效 OpenSSH 配置收集功能(通过 `sshd -T` 实现),包含 Match 上下文。 - 在无 root 权限文件可见的情况下,提供包更新和主机防火墙的安全态势信号。 - 针对常见的包管理器缓存标记,进行包元数据的新鲜度检查。 - 基于 procfs sysctls 进行反向路径过滤(reverse-path filtering)和源路由(source-route)安全态势检查。 - 针对容器主机,进行网桥接口及网桥防火墙钩子的安全态势检查。 - 针对暴露的 Docker 或 Podman API 以及 Docker 用户组成员资格,进行静态容器运行时安全态势检查。 - 支持通过本地 JSON 数据源提供可选的包漏洞扫描结果。 - 提供发布校验和清单,并支持可选的分离式 GPG 签名。 - 提供基于严重程度的评分机制,分为 `critical`(严重)、`high`(高)、`medium`(中)和 `low`(低)等级别。 - 通过 `--fail-on` 参数提供对 CI 友好的退出阈值控制。 - 提供复合式 GitHub Action 封装,可通过 `uses: kingkyylian/linwarden@v0.15.0` 使用。 - 支持针对固件根目录(fixture-root)进行扫描,适用于测试、容器、取证副本以及离线分析场景。 - 除 Python 3.9+ 外,零运行时依赖。 ## 快速开始 从 PyPI 安装: ``` python3 -m pip install linwarden linwarden --version linwarden scan --format markdown ``` 进行隔离的 CLI 安装: ``` pipx install linwarden ``` 从开发检出版本运行: ``` python3 -m venv .venv . .venv/bin/activate python -m pip install -e . linwarden scan --format markdown ``` 针对内置的固件运行扫描: ``` PYTHONPATH=src python3 -m linwarden scan \ --root tests/fixtures/linux-root \ --format json \ --fail-on high ``` 退出码 `2` 表示至少有一条发现结果达到了选定的阈值。 请查看[合成终端演示](docs/assets/terminal-demo.md),了解基于该固件根目录生成的 Markdown 扫描记录。 ## 常见工作流 | 工作流 | 命令或文档 | | --- | --- | | 文档索引 | [docs/index.md](docs/index.md) | | 本地分诊 | `linwarden scan --format markdown` | | CI 失败阈值 | `linwarden scan --format json --fail-on high` | | GitHub 代码扫描 | `uses: kingkyylian/linwarden@v0.15.0` | | Actions 故障排查 | [docs/github-actions.md#troubleshooting](docs/github-actions.md#troubleshooting) | | JSON 报告结构 | [docs/assets/json-report-example.json](docs/assets/json-report-example.json) | | 报告产物处理 | [docs/report-artifacts.md](docs/report-artifacts.md) | | 挂载镜像扫描 | [docs/mounted-root-scans.md](docs/mounted-root-scans.md) | | 有效 SSH 扫描 | `linwarden scan --sshd-mode effective --sshd-match user=deploy` | | 工具定位 | [docs/comparison.md](docs/comparison.md) | ## CLI ``` linwarden profiles [--format markdown|json] linwarden scan [--root PATH] [--proc-root PATH] [--etc-root PATH] [--sys-root PATH] [--config PATH] [--format markdown|json|sarif] [--vulnerability-feed PATH] [--vulnerability-feed-format linwarden|trivy|grype|osv] [--sshd-mode static|effective|auto] [--sshd-binary PATH] [--sshd-match KEY=VALUE] [--output PATH] [--fail-on off|low|medium|high|critical] ``` 常见示例: ``` linwarden profiles linwarden scan --format markdown --output linwarden-report.md linwarden scan --format json --fail-on high linwarden scan --config linwarden.json --format sarif --output linwarden.sarif linwarden scan --sshd-mode effective --format json linwarden scan --sshd-mode effective --sshd-match user=deploy --sshd-match addr=203.0.113.10 linwarden scan --root /mnt/server-image --format json linwarden scan --proc-root /host/proc --etc-root /host/etc --sys-root /host/sys --format markdown linwarden scan --vulnerability-feed ./linwarden-vulnerabilities.json --format sarif linwarden scan --vulnerability-feed ./trivy-report.json --vulnerability-feed-format trivy --format sarif linwarden scan --vulnerability-feed ./grype-report.json --vulnerability-feed-format grype --format sarif linwarden scan --vulnerability-feed ./osv-scanner-report.json --vulnerability-feed-format osv --format sarif ``` ## 配置 Linwarden 接受无额外依赖的 JSON 配置文件: ``` { "profile": "router", "disabled_rules": ["LNX-NET-002"], "suppressions": [ { "rule_id": "LNX-SSH-002", "reason": "Temporary migration host; password auth removed after cutover." } ] } ``` Profiles: | Profile | 行为 | | --- | --- | | `server` | 适用于常规 Linux 服务器的默认选项。无 profile 抑制规则。 | | `workstation` | 适用于交互式台式机或笔记本电脑的安全态势。无 profile 抑制规则;SSH、防火墙、软件包以及内核相关的发现结果均会显示。 | | `router` | 适用于有意进行流量路由的主机。抑制有关 IPv4、IPv6 以及网桥转发的发现结果。 | | `container` | 适用于容器或镜像根目录扫描,此时可能会继承主机内核的 sysctl 值。抑制有关内核和文件系统 sysctl 的发现结果。 | 被抑制的发现结果在 JSON 和 Markdown 报告中依然可见。SARIF 输出仅包含处于活动状态的发现结果。 ## 退出码 | 代码 | 含义 | | --- | --- | | `0` | 扫描完成,且未触发选定的阈值。 | | `1` | 参数解析导致的 CLI 使用错误。 | | `2` | 扫描完成,且达到了 `--fail-on` 设定的阈值。 | ## 当前规则 | 规则 | 严重程度 | 领域 | 概要 | | --- | --- | --- | --- | | `LNX-SSH-001` | high | SSH | 启用了 `PermitRootLogin yes`。 | | `LNX-SSH-002` | medium | SSH | 启用了 `PasswordAuthentication yes`。 | | `LNX-SSH-003` | high | SSH | 启用了 `PermitEmptyPasswords yes`。 | | `LNX-SSH-004` | medium | SSH | `MaxAuthTries` 大于 `4`。 | | `LNX-SSH-005` | medium | SSH | 启用了 `AllowTcpForwarding yes` 或设为 `all`。 | | `LNX-KRN-001` | high | Kernel | `kernel.randomize_va_space=0` 禁用了 ASLR。 | | `LNX-KRN-002` | high | Kernel | `vm.mmap_min_addr` 小于 `65536`。 | | `LNX-KRN-003` | medium | Kernel | `kernel.kptr_restrict=0` 暴露了内核指针。 | | `LNX-FS-001` | high | Filesystem | `fs.protected_hardlinks=0` 禁用了硬链接保护。 | | `LNX-FS-002` | high | Filesystem | `fs.protected_symlinks=0` 禁用了符号链接保护。 | | `LNX-NET-001` | medium | Network | 启用了 `net.ipv4.ip_forward=1`。 | | `LNX-NET-002` | low | Network | 启用了 `net.ipv4.conf.all.accept_redirects=1`。 | | `LNX-NET-003` | medium | Network | 启用了 `net.ipv6.conf.all.forwarding=1`。 | | `LNX-NET-004` | low | Network | 启用了 `net.ipv6.conf.all.accept_redirects=1`。 | | `LNX-NET-005` | medium | Network | 存在网桥接口时,网桥 IPv4 防火墙钩子被禁用。 | | `LNX-NET-006` | medium | Network | 存在网桥接口时,网桥 IPv6 防火墙钩子被禁用。 | | `LNX-NET-007` | medium | Network | 某个网桥接口启用了转发功能。 | | `LNX-NET-008` | medium | Network | `net.ipv4.conf.all.rp_filter=0` 禁用了 IPv4 反向路径过滤。 | | `LNX-NET-009` | medium | Network | `net.ipv4.conf.all.accept_source_route=1` 允许接收 IPv4 源路由数据包。 | | `LNX-NET-010` | medium | Network | `net.ipv6.conf.all.accept_source_route` 允许接收 IPv6 源路由数据包。 | | `LNX-PKG-001` | medium | Packages | 存在可用的软件包更新。 | | `LNX-PKG-002` | high | Packages | 存在可用的安全软件包更新。 | | `LNX-PKG-003` | medium | Packages | 软件包元数据已过期。 | | `LNX-PKG-004` | feed severity | Packages | 本地漏洞数据源报告了受影响的软件包。 | | `LNX-FW-001` | medium | Firewall | 已知的常用主机防火墙被禁用。 | | `LNX-SVC-001` | medium | Services | 已启用的 systemd unit 显示存在外部绑定。 | | `LNX-CTR-001` | high | Containers | 容器运行时 API 绑定到了非本地回环(non-loopback)的 TCP 端口。 | | `LNX-CTR-002` | high | Containers | Docker 用户组为非 root 用户授予了 daemon 级别的访问权限。 | | `LNX-CTR-003` | medium | Containers | Docker 用户命名空间重映射(user namespace remapping)被显式禁用。 | 详细的规则说明请参阅 [docs/rules.md](docs/rules.md)。 ## 报告评分 Linwarden 每份报告的初始分数为 `100`,并根据发现的问题扣除固定的惩罚分数: | 严重程度 | 扣分 | | --- | --- | | critical | 35 | | high | 20 | | medium | 10 | | low | 3 | 该评分机制特意设计得很简单。它是一个用于分诊的参考信号,而不是合规性评级。 ## 项目结构 ``` src/linwarden/ cli.py command line entry point config.py profiles, disabled rules, and suppressions collectors.py host snapshot collection parsers.py small parsers for Linux files rules.py built-in hardening checks reporters.py JSON, Markdown, and SARIF rendering models.py report data structures tests/ fixtures/ deterministic Linux fixture root docs/ architecture.md implementation overview configuration.md profile and suppression config comparison.md positioning against adjacent Linux security tools contributor-ideas.md scoped contribution backlog github-actions.md CI and SARIF workflow examples launch.md copy and checklist for public announcements positioning.md maintainer messaging guide release.md release artifact and publishing workflow rules.md rule catalog report-schema.md JSON report contract schemas/ report.schema.json machine-readable JSON report schema ``` ## 开发 ``` make test make compile make lint make typecheck make smoke make smoke-sarif make check ``` 如果通过项目的虚拟环境运行,请使用 `make check PYTHON=.venv/bin/python`。 测试套件不需要网络服务或特权权限。 ## 安全模型 Linwarden 默认是只读的。它不会修改主机状态、加载内核模块、调用包管理器或发送遥测数据。由于报告中可能包含主机配置的详细信息,因此请将生成的产物视为敏感运营数据。 请通过 [SECURITY.md](SECURITY.md) 报告漏洞;请勿针对敏感报告提交公开的 Issue。 ## 已知限制 - 静态 SSH 模式会读取 `sshd_config` 以及简单的 `Include` 指令;其 `Match` 行为可能与实际有效的 OpenSSH 配置有所不同。 - 有效 SSH 模式会执行 `sshd -T`;请仅在有意扫描实时主机时此模式。 - 软件包元数据的新鲜度依赖于本地缓存标记的 mtime,并不会调用包管理器命令。 - 软件包漏洞扫描需要显式提供本地 JSON 数据源,且绝不获取远程 CVE 数据。 - 网桥安全态势检查依赖于被扫描根目录内的 procfs 和 sysfs 文件;如果缺少网桥数据,将被视为未知状态。 - 当存在 systemd 启用标记时,会从中推断 Firewalld 和 nftables 的服务状态;如果仅能进行基于配置的检测,其启用状态将被视为未知。 - 已启用的 systemd 服务暴露检测是静态的,仅标记服务 unit 的 `ExecStart` 行中常见的通配符绑定选项。 - 容器运行时安全态势检查仅报告来自配置、用户组或已启用的 unit 文件中明确的静态证据;如果缺少运行时文件,状态为未知,而非安全。 - 缺失的文件被视为数据不存在,从而确保扫描可以在容器和固件根目录中正常运行。 - Linwarden 是一款用于安全强化的分诊工具,不是完整的 CIS 或 DISA STIG 合规扫描器。 ## 路线图 - 基于测试固件,扩大对软件包元数据和防火墙安全态势的发行版覆盖范围。 - 仅在证据可靠且无需 root 权限时,增加静态容器运行时信号。 - 完善发布检查,确保 GitHub 产物、证明(attestations)以及 PyPI 安装过程均可验证。 如需提出首发反馈和无 root 权限规则的建议,请访问[首发讨论区](https://github.com/kingkyylian/linwarden/discussions/57)。适合贡献者参与的想法已发布在 [docs/contributor-ideas.md](docs/contributor-ideas.md) 中,您可以从 [Ubuntu 测试固件 Issue](https://github.com/kingkyylian/linwarden/issues/56) 开始了解。 请查阅 [CONTRIBUTING.md](CONTRIBUTING.md) 了解以 Issue 为导向的工作流、规则质量标准以及本地验证检查清单。 ## 许可证 MIT。详见 [LICENSE](LICENSE)。
标签:GitHub Advanced Security, Python, SARIF, 关系图谱, 基线检查, 子域名枚举, 安全加固, 无后门, 系统安全