Qwerty-zsw/WatchTower-for-Bug-Bounty-with-UI

GitHub: Qwerty-zsw/WatchTower-for-Bug-Bounty-with-UI

集成了枚举、DNS解析、HTTP探测和漏洞扫描的 Bug Bounty 攻击面持续监控平台,通过单页仪表板和内嵌SQLite实现轻量化、零依赖的资产侦察与告警。

Stars: 0 | Forks: 0

带有 UI 的 Bug Bounty WatchTower

持续的攻击面侦察

映射 · 解析 · 探测 · 监控你的 bug-bounty 范围 —— 尽在一个仪表板。

WatchTower dashboard

## 功能 - **Web 仪表板** —— 程序、子域名、存活主机和 HTTP 服务整合于一个 UI 中,支持搜索、过滤和实时统计。零外部资源(无 CDN/字体)—— 这是一个仅约 36 KB 的独立页面,可在隔离的机器上离线运行。 - **实时扫描器** —— 从浏览器启动任何模块,并通过轻量级轮询实时跟踪工具输出(无需为每次扫描保持长时间运行的 SSE 线程)。 - **内嵌 SQLite 存储** —— 单文件,无守护进程,WAL 模式;Flask 进程和每个独立扫描任务并发对其进行读写。 - **感知程序的流水线** —— 范围按程序定义(范围内、范围外、通配符、CIDR、原始 IP);每个阶段都会自动解析所属程序。 - **全程序处理** —— DNS 解析和 HTTP 探测在程序的整个资产集上运行一次,而不是按根域执行,因此不会遗漏任何内容,也不会重复工作。 - **原始 IP 处理** —— 程序的 IP(和 CIDR 范围)会与发现的域名一起被解析(通过 dnsx 进行反向 DNS)和探测(httpx)。 - **幂等存储** —— 重新运行任何阶段都会更新现有记录,而不是创建重复项。 - **自动同步** —— 将程序 JSON 放入 `programs/`,文件系统监视器会立即将其导入。 - **通知** —— 资产新增/变更时通过 Discord webhook 和 Telegram bot 发送警报。 - **应用内设置** —— API 密钥、通知通道和 subfinder provider 配置均可通过浏览器编辑。 ## 架构 ``` watchTower/ ├── app.py Flask app — web UI, REST API, scan-job control ├── config.py Central config (WATCH_DIR, DB_PATH, webhook) ├── database/ │ ├── db.py SQLite engine + MongoEngine-compat shim + helpers │ ├── scope_utils.py Wildcard → enumerable-root + program resolution │ └── watchtower.db SQLite database file (created at runtime) ├── programs/ Program scope JSON (auto-synced → SQLite) ├── subdomain_enum/ subfinder · crtsh · abuseipdb · wayback · chaos ├── ns/ dnsx DNS resolution → LiveSubdomains ├── http_probe/ httpx HTTP probing → HTTP ├── nuclei/ Nuclei scanning → notifications ├── templates/index.html Single-page dashboard ├── ecosystem.config.js pm2 process definition └── start.sh One-shot installer / deployer ``` ### 数据流 ``` program scope ─► enumeration ─► DNS resolution ─► HTTP probing ─► vuln scan (scopes, (subfinder, (dnsx) (httpx) (nuclei) wildcards, crtsh, ...) │ │ │ CIDRs, IPs) │ ▼ ▼ ▼ ▼ LiveSubdomains HTTP Discord / Subdomains Telegram ``` ## SQLite 表 所有数据都存储在一个文件中(`database/watchtower.db`,WAL 模式)。列表值 列(providers、ips、tech、status codes、headers)以 JSON 文本形式 存储并进行延迟解码,因此为单个字段遍历数十万行记录时,绝不会实体化其余数据。 | 表名 | 内容 | |------------------|--------------------------------------------------------------------| | `programs` | 带有 `ooscopes`、`wildcards`、`cidrs`、`ips`、`domains` 的程序 | | `subdomains` | 原始发现的子域名(DNS 之前),标记有发现来源 | | `livesubdomains` | 带有 IP 和 CDN 信息的 DNS 解析主机 | | `http` | 存活的 HTTP 服务 —— 标题、状态、技术、标头、favicon | 唯一性由 `UNIQUE(program_name, subdomain)`(按表)强制执行,因此 重新运行任何阶段都会执行 upsert,而不是重复创建。Provider 列表作为 集合累积。不涉及外部数据库进程。 范围模型:程序的可枚举根是其 `scopes` 加上每个 `wildcards` 条目的 固定根(`*.example.com` → `example.com`),减去 `ooscopes`。 `_program_for_domain` 解析器将任何根 —— 字面范围、通配符根或 原始 IP —— 映射回其所属程序,因此无论范围是如何 定义的,每个阶段都能正确绑定结果。 ## 模块 ### 枚举 (`subdomain_enum/`) | 模块 | 来源 | 需要密钥 | |-------------|--------------------------------------------------|----------------------------| | `subfinder` | ProjectDiscovery subfinder (`-all -recursive`) | provider 密钥 (可选) | | `crtsh` | crt.sh Certificate Transparency (PostgreSQL) | — | | `abuseipdb` | AbuseIPDB `/check` 反向 DNS 主机名 | **AbuseIPDB 密钥** | | `wayback` | Wayback Machine | — | | `chaos` | ProjectDiscovery Chaos | **PDCP 密钥** | | `enum_all` | 对所有程序运行每个枚举来源 | — | ### DNS 解析 (`ns/`) - `ns` —— 通过 **dnsx** 解析程序的所有子域名及其原始 IP(反向 DNS),写入存活主机。 - `ns_all` —— 跨越每个程序执行相同操作。 ### HTTP 探测 (`http_probe/`) - `http` —— 通过 **httpx** 探测程序的所有存活主机和原始 IP。探测使用发起请求的浏览器的 `User-Agent`。 - `http_all` —— 跨越每个程序执行相同操作。 ### 漏洞扫描 (`nuclei/`) - `nuclei_fresh` —— 扫描最近发现的 HTTP 服务。 - `nuclei_all` —— 扫描每个已存储的 HTTP 服务。 ## 设置 ### 1. 依赖 ``` # Python pip install -r requirements.txt # Go tools (ProjectDiscovery) go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest go install -v github.com/projectdiscovery/dnsx/cmd/dnsx@latest go install -v github.com/projectdiscovery/httpx/cmd/httpx@latest go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest ``` Python 依赖要求:`flask`、`waitress`、`tldextract`、`requests`、 `watchdog`、`pyyaml`、`psycopg2-binary`。**无需 MongoDB,无需数据库服务器** —— 存储使用的是标准库中的 `sqlite3` 模块。 ### 2. 数据库 无需安装或运行任何内容。SQLite 文件会在首次 启动时自动创建于 `database/watchtower.db`(可通过 `WATCHTOWER_DB` 环境变量覆盖)。 ### 3. 配置 - `config.py` —— `WATCH_DIR`、`DB_PATH`、`WEBHOOK_URL`。 - `.env` —— `WATCHTOWER_PORT`、`WATCHTOWER_DIR`。 - **可选环境变量。** 侦察工具 (httpx/dnsx/subfinder/nuclei) 以 其自身的原生并发运行 —— 没有包装器强加的限制。仅有的调节项: | 变量 | 默认值 | 控制 | |-----|---------|----------| | `WATCHTOWER_THREADS` | `4` | waitress WSGI 线程 | | `WT_JOB_WORKERS` | `4` | 每次扫描任务的并行目标数 | | `WATCHTOWER_DB` | `database/watchtower.db` | SQLite 文件路径 | ### 4. 运行 ``` # 开发 (Werkzeug reloader) — 设置 WATCHTOWER_DEBUG=1 WATCHTOWER_DEBUG=1 python app.py # 生产 — waitress (未处于 debug 时自动选择) python app.py # 生产 (pm2) — 参见 ecosystem.config.js pm2 start ecosystem.config.js pm2 save ``` `start.sh` 自动安装/部署到 `/opt/watchtower`,设置 pm2,并添加 shell 别名。 在 `http://localhost:8854`(或你的 `WATCHTOWER_PORT`)打开仪表板。 ## 定义程序 在 `programs/` 中添加一个 JSON 文件(保存时自动导入),或者使用 UI 中的 **程序** 页面: ``` { "program_name": "example", "scopes": ["example.com", "example.io"], "ooscopes": ["cdn.example.com"], "wildcards": ["*.example.com", "vpn.*.example.com"], "cidrs": ["1.2.3.0/24"], "ips": ["8.8.8.8"] } ``` ## 用法 ### Web UI(推荐) 进入 **Scanner**,选择一个目标程序(或单个域名),选择一个模块, 然后点击 **Run**。输出将实时流式传输。建议顺序: ``` enumeration (subfinder / crtsh / …) → ns → http → nuclei ``` ### REST API | Endpoint | 描述 | |-----------------------------------------|--------------------------------------| | `GET /api/stats` | 仪表板计数器 | | `GET /api/programs/all` | 所有程序 | | `POST /api/programs/add` | 添加程序 | | `DELETE /api/programs/` | 删除程序及其资产 | | `GET /api/subdomains/program/

` | 程序的原始子域名 | | `GET /api/lives/program/

` | 程序的 DNS 解析主机 | | `GET /api/http/program/

` | 程序的 HTTP 服务 | | `POST /api/scan/start` | 启动独立扫描任务 | | `GET /api/scan/jobs` | 列出最近的扫描任务 | | `GET /api/scan/job/` | 单个任务的状态 | | `GET /api/scan/log?job=&offset=` | 增量日志跟踪 (poll) | | `POST /api/scan/stop?job=` | 停止运行中的任务 | | `GET\|POST /api/settings` | 读取 / 更新设置 | | `GET\|POST /api/subfinder-config` | 读取 / 更新 subfinder provider | 通过 API 运行模块: ``` # 启动 job curl -s -X POST http://localhost:8854/api/scan/start \ -H 'Content-Type: application/json' \ -d '{"tool":"subfinder","program":"example"}' # tail 其 log (使用返回的 offset 重复执行) curl -s "http://localhost:8854/api/scan/log?job=&offset=0" ``` 扫描作为**独立进程**运行,并写入日志文件,因此在浏览器关闭后 扫描仍会继续运行,甚至在 Flask 重启后也能幸存 —— UI 通过轮询日志重新附加。 ## 设置 可从 **Settings** 页面配置(持久化到 `settings.json`): - **通知** —— Discord webhook、Telegram bot token + chat ID。 - **系统** —— 监视目录、程序自动同步开关。 - **API 密钥** —— ProjectDiscovery (Chaos/PDCP)、AbuseIPDB。 - **Subfinder provider** —— 在模态 YAML 编辑器中直接编辑 `provider-config.yaml`(保存时验证)。 ## 注意事项 - crt.sh 的公共 PostgreSQL endpoint 不稳定;`crtsh` 模块会自动重新连接并重试。 - `abuseipdb` 模块使用真实的 AbuseIPDB API 并需要密钥 —— 它将域名解析为其 IP,并存储在范围内发现的反向 DNS 主机名。 - `ns` 和 `http` 是有状态的消费者:它们对枚举已经发现的内容进行操作,因此请先运行枚举。 ## 免责声明 仅用于对你已获得授权测试的目标(例如,在其声明范围内的 bug-bounty 程序)进行操作。你对如何使用此工具负责。

标签:Bug Bounty, Flask, GitHub, SQLite, Web面板, 可自定义解析器, 实时处理, 密码管理, 攻击面测绘, 数据可视化, 网络测绘, 自动化侦察, 运行时操纵, 逆向工具