otixe/fortigate-policy-auditor

GitHub: otixe/fortigate-policy-auditor

FortiGate 防火墙策略审计工具,专注于发现直接风险及被宽泛子网规则掩盖的间接暴露向量。

Stars: 0 | Forks: 0

# fortigate-policy-auditor
🛡️ **审计 FortiGate 防火墙策略以发现暴露向量** *那些被“subnet: ALL · service: ALL”规则掩盖而无法通过人工审查发现的隐患* [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/cc945e4cd4233842.svg)](https://github.com/otixe/fortigate-policy-auditor/actions/workflows/ci.yml) [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
## 问题所在 你正在审计你的 FortiGate。每一条策略单独看起来都很合理: ``` Policy #42: trust → DMZ:web-server (https) ✓ Policy #43: trust → DMZ:db-server (pgsql) ✓ Policy #44: trust → DMZ:subnet (ALL services) ⚠️ ``` 策略 #44 看起来没问题——它是“内部管理员访问”。但它**默默地授予**了与 #42 *和* #43 相同的访问权限,以及同一个源对 DMZ 子网中所有其他内容的访问权限。当你修补 #42 以移除存在 CVE 漏洞的服务时,#44 仍然允许该访问。 这就是**间接暴露向量**问题。人工策略审查往往会忽略它。而这个工具能发现它。 ## 功能说明 - 🔍 **直接风险检测** — 过度宽松的规则(`ALL` 服务、`0.0.0.0/0` 源、弱 NAT、缺少日志记录) - 🕸️ **间接向量分析** — 通过跨越包含其他目标主机的子网,查找授予*隐式*访问权限的策略 - 📊 **严重性评分** — 根据服务暴露程度 × 源范围综合评定为严重 / 高 / 中 / 低 - 📋 **输出格式** — 终端表格、用于管道传输的 JSON、用于工单/审计的 HTML 报告 - 🔌 **两种接入模式** — 实时 FortiGate API (`fortios-api`) 或静态配置转储 (`config show full-configuration`) - ✅ **适配 CI** — 退出码反映检查结果;可与 GitHub Actions / GitLab CI 集成 ## 快速开始 ``` pip install fortigate-policy-auditor # 审计运行中的设备(只读 API token) fgaudit live \ --host firewall.example.com \ --token-env FORTIGATE_TOKEN \ --output report.html # 从离线配置转储进行审计(推荐用于 change-control) fgaudit dump --input config.txt --output report.html --format html # 通过管道将 JSON 传递给 jq 以进行自定义查询 fgaudit dump --input config.txt --format json | jq '.findings[] | select(.severity=="critical")' ``` ## 示例输出 ``` Audit summary · firewall.example.com · 2026-06-04 14:32 CRITICAL ▰▰ 2 findings HIGH ▰▰▰▰▰▰ 6 findings MEDIUM ▰▰▰▰ 4 findings LOW ▰ 1 finding ┌──────┬─────────────────────────┬──────────┬─────────────────────────────────┐ │ ID │ Policy │ Severity │ Vector │ ├──────┼─────────────────────────┼──────────┼─────────────────────────────────┤ │ FG01 │ #42 vpn → DMZ-subnet │ critical │ Indirect exposure of #99 (CVE) │ │ FG02 │ #88 any → wan1 │ critical │ Direct: ALL services + 0.0.0.0/0│ │ FG03 │ #15 trust → backup-srv │ high │ NAT off + no logging │ │ ... │ ... │ ... │ ... │ └──────┴─────────────────────────┴──────────┴─────────────────────────────────┘ → Full report: report.html → Exit code: 2 (critical findings present) ``` 请参阅 [`docs/sample-report.html`](docs/sample-report.html) 获取完整的 HTML 输出。 ## 为什么需要“间接向量”? 真实的事件模式:服务 X 爆出 CVE 漏洞。你审计了明确允许 X 的策略——却忽略了那条向内部用户开放整个子网(包括运行 X 的主机)访问权限的宽泛策略。这有三种经典形式: ### 1. 子网保护伞 ``` Specific: Engineering → backup-srv (rsync) Implicit: Engineering → backup-subnet (ALL) ← grants rsync + everything else ``` ### 2. 地址组扩展 ``` Group "trusted-admins" = [user1, user2, user3] Policy: trusted-admins → DMZ (ALL ports) Reality: user3's laptop got compromised, full DMZ access ``` ### 3. 服务字段中的 ANY ``` Policy: branch-vpn → finance (ALL) ← legitimate intent: "everything finance needs" Reality: Finance has 12 services across 8 hosts; one runs a CVE ``` 该工具会**自动枚举这些模式**,并将它们与更细化的策略进行比对,从而揭示出隐式授权。 ## 架构 ``` ┌─────────────────┐ │ FortiGate API │ or ┌──────────────────┐ │ (HTTPS + token) │ │ config dump file │ └────────┬────────┘ └────────┬─────────┘ │ │ └──────────┬───────────────┘ ▼ ┌──────────────┐ │ Parser │ normalize policies, address objects, services │ (pydantic) │ └──────┬───────┘ ▼ ┌─────────────────────┐ │ Analyzer │ direct + indirect vectors │ · DirectRisk │ │ · SubnetUmbrella │ │ · GroupExpansion │ │ · ServiceAny │ └──────────┬──────────┘ ▼ ┌──────────────────────┐ │ Reporter │ JSON · HTML · text table └──────────────────────┘ ``` ## 配置说明 ``` # .fgaudit.yaml — 仓库本地审计策略 severity_thresholds: fail_on: critical # CI exit code 2 if any critical found ignore: - rule_id: FG-INFO-001 # informational findings - policy_id: 99 # known-accepted exception (document why) custom_checks: - name: legacy-protocol pattern: service: [telnet, ftp, snmp-v1] severity: high ``` ## 真实用例 - 🔥 **CVE 爆发前审计** — 针对服务 X 的 CVE,查找直接或间接暴露 X 的每一条策略 - 📜 **变更控制审查** — 对比两份配置转储,标记因差异而新增的暴露风险 - 📋 **合规性要求** — 提供可复现的证据,以用于 PCI / ISO 审计 - 🤖 **CI 门禁** — 阻断引入了严重检查结果的防火墙配置提交 请参阅 [`examples/`](examples/) 获取可运行的场景示例。 ## 状态 🚧 **Beta 版** — 正在积极开发中。API 和报告格式已稳定;检查规则每周都在增加。 ## 许可证 MIT — 详见 [LICENSE](LICENSE)。 由 [@otixe](https://github.com/otixe) 构建 — DevOps 与 Agentic 系统工程师 · 🇨🇱
标签:FortiGate, PE 加载器, Python, 对称加密, 插件系统, 无后门, 网络安全, 自动化审计, 逆向工具, 防火墙审计, 隐私保护