cybersecify/OpenEASD

GitHub: cybersecify/OpenEASD

OpenEASD 是一个开源自托管平台,自动化检测和分析组织外部攻击面,解决外部安全风险可视化和管理问题。

Stars: 4 | Forks: 9

# OpenEASD [![GitHub 星标](https://img.shields.io/github/stars/cybersecify/OpenEASD?style=social)](https://github.com/cybersecify/OpenEASD/stargazers) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/a1019fc1f2094808.svg)](https://github.com/cybersecify/OpenEASD/actions/workflows/ci.yml) [![Docker 镜像](https://ghcr-badge.egpl.dev/cybersecify/openeasd/latest_tag?trim=major&label=ghcr.io)](https://github.com/cybersecify/OpenEASD/pkgs/container/openeasd) **开放式外部攻击面检测** - 一个用于发现和分析您组织外部攻击面的自动化平台。 OpenEASD 扫描域名以发现子域名、解析 IP、扫描端口、检测服务,并在网络攻击面中寻找漏洞。 ## 功能 - **自动化流水线** — 从域名到发现结果的 13 工具扫描工作流 - **网络攻击面扫描** — CVE、TLS/证书问题、SSH 配置、网络协议漏洞 - **动态工作流** — 创建自定义扫描配置,按工作流启用/禁用工具 - **工具自动注册** — 零核心修改添加新工具 - **实时扫描进度** — 带逐工具步骤跟踪的实时流水线状态 - **扫描停止/取消** — 工具步骤间的优雅取消 - **统一发现结果** — 所有工具写入带生命周期跟踪的单一 Finding 模型 - **持续监控** — 可配置计划(6 小时/12 小时/24 小时/48 小时/每周)的按域名重新扫描 - **子扫描** — 在现有扫描资产上重新运行特定工具,无需完全重新发现 - **报告** — CSV 和 PDF 导出 - **警报** — Slack 和 Teams webhook,带可配置严重性阈值;UI 中的测试按钮和警报历史 - **调度** — 一次性、定期和每日自动扫描 - **JWT 认证** — 无状态 Bearer 令牌认证,带刷新令牌轮换 - **强制密码更改** — 默认 `admin/admin` 密码必须在首次登录时更改 ## 扫描流水线 ``` Phase 1 Domain Security - DNS, email (SPF/DMARC/DKIM), RDAP checks Phase 2 Subfinder - Passive subdomain enumeration Phase 2 Amass - Active subdomain enumeration Phase 3 DNSx - DNS resolution, public IP filtering Phase 4 Naabu - TCP port scanning (top 100) Phase 5 Service Detection - Classify ports as web/non-web via nmap -sV (auto) Phase 7 Nmap - CVE scanning via NSE vulners (non-web ports) Phase 7 TLS Checker - Certificate, cipher, and protocol analysis Phase 7 SSH Checker - SSH configuration audit Phase 7 Nuclei Network - Service-aware nuclei network templates against non-web ports Phase 8 httpx - Web probing, URL discovery Phase 9 Nuclei - Web vulnerability scanning (community templates) Phase 9 Web Checker - Security headers, cookies, CORS analysis ``` ## 架构 ``` apps/core/ - Infrastructure (never changes) api/ - Django Ninja API, JWT auth, error handlers api/tokens/ - BlacklistedToken model (JWT JTI blacklist) assets/ - Network assets: Subdomain, IPAddress, Port web_assets/ - Web assets: URL service_detection/ - Classifies ports as web/non-web (core, always runs) findings/ - Unified Finding model scans/ - ScanSession, pipeline orchestrator workflows/ - Dynamic workflow engine + tool registry scheduler/ - Django-Q2 scheduling, daily/weekly scans, per-domain monitoring, stuck scan watchdog notifications/ - Slack/Teams alerts insights/ - Scan summaries, charts reports/ - CSV/PDF export domains/ - Domain management dashboard/ - UI home apps/ - Tool apps (add/remove freely) domain_security/ - DNS, email, RDAP checks subfinder/ - Passive subdomain enumeration amass/ - Active subdomain enumeration dnsx/ - DNS resolution naabu/ - Port scanning nmap/ - CVE scanning (NSE vulners) tls_checker/ - TLS/cert/cipher analysis ssh_checker/ - SSH configuration audit nuclei_network/ - Network protocol vuln scanning httpx/ - Web probing nuclei/ - Web vulnerability scanning web_checker/ - Security headers, cookies, CORS frontend/ - React 18 + Vite SPA src/pages/ - Page components src/components/ - Shared UI primitives (Badge, Spinner, Pagination, ConfirmButton) src/components/ui/ - shadcn/ui primitives (Button, Card, Table, AlertDialog, …) src/hooks/ - useFetch, usePolling src/api/client.js - JWT apiFetch wrapper src/auth.js - localStorage token helpers ``` ## 快速开始 ### Docker(推荐) ``` docker run -d \ -p 8000:8000 \ -v openeasd-data:/app/data \ -v openeasd-logs:/app/logs \ -e SECRET_KEY="$(openssl rand -hex 32)" \ -e ALLOWED_HOSTS="*" \ --cap-add NET_RAW \ --restart unless-stopped \ --name openeasd \ ghcr.io/cybersecify/openeasd:latest ``` 打开 http://localhost:8000 — 使用 `admin` / `admin` 登录。在访问应用之前,您将被强制设置新密码。 #### 更新到最新版本 ``` docker pull ghcr.io/cybersecify/openeasd:latest docker stop openeasd && docker rm openeasd # 重新运行上述 docker run 命令 — volumes 会保留所有数据 ``` #### 环境变量 | 变量 | 默认值 | 描述 | |---|---|---| | `SECRET_KEY` | 不安全默认值 | Django 密钥 — **生产环境请设置此项** | | `ALLOWED_HOSTS` | `localhost,127.0.0.1` | 逗号分隔的主机名(添加您的服务器 IP/域名) | | `CSRF_TRUSTED_ORIGINS` | — | 如果通过域名访问则必需,例如 `https://openeasd.example.com` | | `DEBUG` | `False` | 仅在本地开发时设置为 `True` | | `DB_NAME` | `data/openeasd.db` | SQLite 路径,相对于 `/app` | | `SLACK_WEBHOOK_URL` | — | 用于扫描警报的 Slack 传入 webhook(也可在通知 UI 中设置) | | `MS_TEAMS_WEBHOOK_URL` | — | 用于扫描警报的 Teams 传入 webhook(也可在通知 UI 中设置) | | `ALERT_SEVERITY_THRESHOLD` | `high` | 触发警报的最低严重性 — 由通知 UI 设置覆盖 | | `SCAN_DAILY_HOUR` | `2` | 每日计划扫描的小时(24小时制,UTC) | | `SCAN_DAILY_MINUTE` | `0` | 每日计划扫描的分钟 | ### Kubernetes Manifests 位于 `k8s/`。需要一个带 nginx Ingress 控制器的集群。 **1. 设置您的密钥** 编辑 `k8s/secret.yaml` 并将 `REPLACE_WITH_OPENSSL_RAND_HEX_32` 替换为真实密钥: ``` openssl rand -hex 32 ``` **2. 设置您的域名** 编辑 `k8s/configmap.yaml`(`ALLOWED_HOSTS`,`CSRF_TRUSTED_ORIGINS`)和 `k8s/ingress.yaml`(`host`)以匹配您的域名。 **3. 部署** ``` kubectl apply -k k8s/ ``` **4. 更新到最新镜像** ``` kubectl rollout restart deployment/openeasd-web deployment/openeasd-worker -n default ``` #### 架构 单 Pod,两个容器,一个 `ReadWriteOnce` PVC: | 容器 | 命令 | 资源 | |---|---|---| | `web` | `gunicorn`(2 个 worker) | 256Mi–512Mi | | `worker` | `manage.py qcluster` | 512Mi–1Gi,`NET_RAW` 能力 | 一个 init 容器在主容器启动前运行迁移和管理员用户设置。`worker` 容器获得 `NET_RAW` 能力用于 nmap/naabu 端口扫描。 #### 健康检查 `GET /health/` 返回 `{"status": "ok"}` — 由 K8s 就绪性和活跃性探针使用(无需认证)。 ### 独立(无 Docker) 在 Linux 服务器或 macOS 上无需 Docker 即可运行的最快方式: ``` git clone https://github.com/cybersecify/OpenEASD.git cd OpenEASD # Linux (安装所有依赖项及 systemd 服务) sudo ./install.sh # macOS ./install.sh # 如果不需要活跃子域名枚举可跳过 amass (节省约10分钟) sudo ./install.sh --skip-amass ``` 该脚本安装:Python/uv, Node.js, nmap, ProjectDiscovery 工具(subfinder, dnsx, naabu, httpx, nuclei),amass,构建前端,生成带随机 `SECRET_KEY` 的 `.env`,运行迁移,创建 `admin` 用户,为 nmap/naabu 授予 `NET_RAW`,并在 Linux 上设置 `systemd` 服务。 安装后,编辑 `.env` 将您的域名添加到 `ALLOWED_HOSTS` 和 `CSRF_TRUSTED_ORIGINS`,然后重启: ``` sudo systemctl restart openeasd-web openeasd-worker ``` 在 macOS 上,手动启动: ``` uv run gunicorn openeasd.wsgi:application --bind 0.0.0.0:8000 --workers 2 uv run manage.py qcluster # second terminal ``` ### 开发模式 ``` # 终端 1 — Django + Django-Q2 worker uv run python main.py # 终端 2 — Vite 开发服务器 (将 /api/ 代理到 8000 端口的 Django) cd frontend && npm run dev # React 应用运行于 http://localhost:5173 ``` ### main.py 标志 ``` uv run python main.py --build # npm build then start uv run python main.py --build-only # npm build only uv run python main.py --port 9000 # custom port uv run python main.py --no-worker # web server only (no worker) ``` ## CI/CD GitHub Actions 在每次推送到 `main` 和 `v*` 标签时运行: - **pytest** — 快速测试套件(约 522 个测试,排除慢速 DNS/RDAP 测试) - **bandit** — Python SAST 扫描 - **pip-audit** — 依赖项 CVE 扫描 - **前端构建** — `npm ci && npm run build` - **Docker 构建** — 每次推送的 amd64 冒烟构建 - **发布到 GHCR** — 在每次 `main` 推送和版本标签时发布多架构(`amd64` + `arm64`)镜像 ## API REST API 通过 Django Ninja 在 `/api/` 提供服务,使用 JWT Bearer 认证。 - **文档:** http://localhost:8000/api/docs (OpenAPI/Swagger UI) - **认证:** `POST /api/token/pair` → `{access, refresh}` 令牌 - **令牌刷新:** `POST /api/token/refresh` ## 添加新工具 创建一个在其 AppConfig 中带有 `tool_meta` 的工具应用 — 无需修改核心文件: ``` # apps/my_tool/apps.py from django.apps import AppConfig class MyToolConfig(AppConfig): name = "apps.my_tool" label = "my_tool" verbose_name = "My Tool" tool_meta = { "label": "My Tool", "runner": "apps.my_tool.scanner.run_my_tool", "phase": 6, "requires": ["naabu"], "produces_findings": True, } ``` 然后将 `"apps.my_tool"` 添加到 `openeasd/settings.py` 的 `INSTALLED_APPS` 中。该工具会自动注册到工作流系统中。 ### 工具应用结构 ``` apps/my_tool/ apps.py - AppConfig with tool_meta models.py - Empty (uses core Finding/asset models) scanner.py - Orchestrator: collect -> analyze -> save collector.py - Runs binary or probes, returns raw data analyzer.py - Parses data, builds Finding/asset objects ``` ## 运行测试 ``` # 快速测试 (排除缓慢的 DNS 测试,约629个测试) uv run pytest tests/ --ignore=tests/unit/test_domain_security.py # 全部测试 (总计约670个) uv run pytest tests/ ``` ## 技术栈 **后端:** - **Django 5** — Web 框架 - **Django Ninja** — 带 OpenAPI 文档的 REST API - **Django-Q2** — 后台任务队列和调度器(ORM 代理,替代 APScheduler) - **croniter** — 用于 Django-Q2 CRON 调度的 Cron 表达式解析 - **WhiteNoise** — 在生产环境(Docker)中提供带 gzip 压缩的静态文件 - **SQLite** — 数据库(开发),可通过 `DB_NAME` 配置 - **paramiko** — SSH 协议检查 - **cryptography** — X.509 证书分析 - **xhtml2pdf** — PDF 报告生成 - **django-ninja-jwt** — 用于 Ninja API 的 JWT 认证(包装 `djangorestframework-simplejwt`);访问 + 刷新令牌,登出时黑名单 **前端:** - **React 18 + Vite** — 带热模块替换的 SPA - **Tailwind CSS 3 + shadcn/ui** — 带 Radix UI 组件原语的实用程序优先样式 - **sonner** — Toast 通知 - 原生 popstate 路由器(无 react-router) ## 许可证 MIT 许可证 - 详见 [LICENSE](LICENSE) ## 作者 [Rathnakara G N](https://cybersecify.com) / [CyberSecify](https://cybersecify.com)
标签:Claude, CVE检测, DInvoke, GPT, TLS检测, Web漏洞扫描, 动态工作流, 动态插桩, 占用监测, 反取证, 安全评估, 报告导出, 持续监控, 攻击面检测, 数据统计, 漏洞管理, 端口扫描, 网络安全, 自动化安全扫描, 自托管, 警报通知, 请求拦截, 调度任务, 资产管理, 运行时操纵, 逆向工具, 隐私保护