Karan-1708/SentinelAI---Autonomous-Threat-Intelligence-Incident-Response-Platform

GitHub: Karan-1708/SentinelAI---Autonomous-Threat-Intelligence-Incident-Response-Platform

SentinelAI 是一个自主威胁情报与事件响应平台,通过两阶段 ML 推理对日志进行异常检测与威胁分类,并生成附带补救步骤的可解释事件报告,充当自动化 Tier-1 SOC 分析师。

Stars: 0 | Forks: 0

# SentinelAI — 代码库指南 ## 项目概述 自主威胁情报与事件响应平台。充当 Tier-1 SOC 分析师: 摄入日志 → 检测异常 → 分类威胁 → 映射至 MITRE ATT&CK → 生成 包含补救 playbook 的可解释事件报告。 **目标受众**:面向 SOC/安全工程岗位(Splunk、CrowdStrike、 Microsoft Sentinel)的代表作。ISO27001 背景强调了为何在受监管行业中 SHAP 可解释性至关重要。 ## 架构 ``` Browser (https) ─┐ │ Logs → ELK (Logstash → Elasticsearch) ┐ ├─ nginx (TLS + CSP) │ │ │ ├─ https → FastAPI (/api, JWT) │ │ → IsolationForest + XGBoost │ │ → MITRE ATT&CK mapping │ │ → SHAP explanation │ │ → PostgreSQL (Incident) │ └─ wss → WebSocket feed (JWT-authed) └─ static → React 18 dashboard (zod-validated) ``` 两阶段 ML 推理: 1. **IsolationForest**(仅在 BENIGN 数据上训练):标记异常,捕获 zero-day 攻击 2. **XGBoost**(监督多分类):对已知攻击类型进行标记(DDoS、PortScan 等) 如果 IsolationForest 返回“normal”,则跳过 XGBoost(为保证性能提前退出)。在运行 `joblib.load` 之前,每个模型 artifact 都会针对 `MODEL_MANIFEST_PATH` 进行 SHA-256 验证 —— 模型文件被视为不受信任的输入。 ## 关键目录 | 目录 | 用途 | |-----------|---------| | `ingestion/` | CICIDS-2017 标准化,ES 批量索引器,合成日志生成器 | | `models/` | sklearn 预处理器,IsolationForest,XGBoost,MITRE 映射器,MLflow 训练器 | | `explainability/` | SHAP TreeExplainer,ReportLab PDF 报告生成器 | | `api/` | FastAPI 异步后端 —— 摄入 / 预测 / 事件 / 报告 / WebSocket | | `api/auth/` | JWT + argon2id 认证模块及 FastAPI 依赖 | | `dashboard/` | React 18 + Vite + Tailwind —— 实时 SOC dashboard | | `dashboard/src/schemas/` | 对每个服务器 payload 进行 zod 运行时验证 | | `docker/` | 特定于服务的配置(logstash pipeline、kibana.yml、nginx.conf、TLS) | | `data/` | 数据集下载脚本 + SHA-256 清单;原始数据被 gitignore | | `notebooks/` | EDA、特征选择、模型实验、SHAP 分析 | | `requirements/` | 按关注点拆分的固定 Python 依赖(base/ml/api/dev) | | `scripts/` | 用于训练、数据库填充、开发证书生成的 CLI 入口点 | | `tests/integration/` | 需要完整 Docker 环境的端到端测试 | | `.github/workflows/` | GitHub Actions CI(ruff、bandit、pip-audit、pytest、vitest、build) | ## 本地运行 ### 前置条件 - **Docker Desktop** ≥ 4.x(Windows / macOS / Linux),推荐 8 GB 内存 - **Git** - PATH 中需包含 **openssl**(用于生成开发 TLS 证书和密钥) 无需本地安装 Python —— 一切均在 Docker 内运行。 ### 步骤 1 — 克隆并配置环境 ``` git clone https://github.com/Karan-1708/SentinelAI.git cd SentinelAI # Windows copy .env.example .env # macOS / Linux cp .env.example .env ``` 打开 `.env` 并为每个 `REPLACE_ME_*` 占位符生成一个新的密钥: ``` # 32 字节高熵随机数据 — 每个 secret 运行一次 openssl rand -hex 32 ``` 如果缺少任何必需的密钥或仍保留占位符值,API 将拒绝在 `staging` 或 `production` 环境中启动(`api/config.py` —— `model_validator` 会强制执行此操作)。 ### 步骤 1.5 — 为内部面板引导开发 TLS + basic-auth ``` bash scripts/gen_dev_certs.sh ``` 幂等操作。写入: - `docker/nginx/certs/server.crt` + `server.key` —— 用于 `sentinelai.local` / `localhost` 的自签名证书。Nginx 在 443 端口通过 HTTPS 提供 dashboard 和 `/api` 服务。 - `docker/nginx/htpasswd` —— 保护 `/mlflow` 和 `/kibana` 的开发凭据(`admin` / `dev`)。在部署前请务必替换。 这两个路径均被 gitignore。 ### 步骤 2 — 启动完整的开发栈 ``` docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d ``` 这将启动 9 个服务。**Elasticsearch 需要 60–90 秒**才能通过健康检查。 在继续操作之前,请等待其变为健康状态: ``` docker inspect --format="{{.State.Health.Status}}" sentinelai-elasticsearch-1 # 持续运行直到 output 为:healthy ``` ### 步骤 3 — 一次性操作:设置 kibana_system 密码 首次启动时必须执行此操作,以便 Kibana 能够向 Elasticsearch 进行身份验证。后续启动可跳过 —— `esdata` 卷会将其持久化。 ``` docker compose exec elasticsearch bash -c ' curl -s -X POST -u "elastic:${ELASTIC_PASSWORD}" \ -H "Content-Type: application/json" \ https://localhost:9200/_security/user/kibana_system/_password \ --cacert /usr/share/elasticsearch/config/certs/ca/ca.crt \ -d "{\"password\":\"${KIBANA_PASSWORD}\"}" ' ``` 预期响应:`{}` ### 步骤 4 — 填充初始管理员用户 系统没有开放的自注册功能 —— 用户配置由管理员控制。直接在数据库中创建第一个管理员: ``` docker exec -it sentinelai-api-1 ` python scripts/seed_postgres.py --admin analyst@example.com ``` `seed_postgres.py` 从 stdin 读取密码(绝不回显、绝不记录、绝不作为命令行参数)。它会验证数据库连接,以幂等方式创建表,然后插入管理员。重新运行是安全的 —— 现有的电子邮件将保持不变。 ### 步骤 5 — 训练模型 训练在 API 容器内运行(Python 3.12、sklearn 1.5.2、XGBoost 2.0.3)。 **选项 A —— 合成样本(速度快,约 30 秒,适合测试)** ``` # Windows docker cp data\sample\cicids_sample.csv sentinelai-api-1:/tmp/cicids_sample.csv # macOS / Linux docker cp data/sample/cicids_sample.csv sentinelai-api-1:/tmp/cicids_sample.csv docker exec -u root sentinelai-api-1 python -m models.trainer ` --data-dir /tmp --model-dir /models --max-rows 1000 ` --mlflow-uri http://mlflow:5000 ``` **选项 B —— 真实 CICIDS-2017 数据集(约 8 GB 下载量,准确率最高)** ``` # 首次运行:bootstrap SHA-256 manifest(需要受信任的网络)。 docker exec sentinelai-api-1 python data/download_cicids.py --skip-hash-check # 然后提交生成的 data/cicids_sha256.txt,以便验证未来的每次 download。 docker exec -u root sentinelai-api-1 python -m models.trainer ` --data-dir data/cicids --model-dir /models ` --mlflow-uri http://mlflow:5000 ``` 训练器会在每个模型 artifact(SHA-256、sklearn / xgboost 版本、类列表、trained_at)旁边写入一个配套的 `manifest.json`。将 `.env` 中的 `MODEL_MANIFEST_PATH` 指向它,以便 API 在启动时验证每个 artifact。 训练完成后,修复模型文件所有权并重启 API: ``` docker exec -u root sentinelai-api-1 chown -R appuser:appuser /models docker compose -f docker-compose.yml -f docker-compose.dev.yml restart api ``` ### 步骤 6 — 验证一切是否正常 每个修改型 endpoint 都需要 bearer token。基于 nginx 的流程: ``` # 1. 登录并捕获 JWT $login = curl -s -k -X POST https://localhost/api/auth/login ` -H "Content-Type: application/x-www-form-urlencoded" ` --data "username=analyst@example.com&password=" $token = ($login | ConvertFrom-Json).access_token # 2. Health check(设计上为 unauthenticated) curl -k https://localhost/api/health # 预期:{"status":"ok","database":"ok","prediction_service":"ready"} # 3. 测试一个 prediction(authenticated) curl -k -X POST https://localhost/api/predict ` -H "Content-Type: application/json" ` -H "Authorization: Bearer $token" ` --data-binary "@scripts/test_payload.json" # 预期:threat_label "DDoS", mitre_techniques [T1498, T1499], top_shap_features [...] ``` 打开 **https://localhost/** —— React dashboard 会加载登录界面。使用在步骤 4 中创建的管理员凭据登录,实时事件流将通过 `wss://` 传输。 ### 服务 URL(开发模式) | 服务 | URL | 凭据 | |---------|-----|-------------| | React dashboard | https://localhost/ | 步骤 4 中创建的 admin | | FastAPI(通过 nginx) | https://localhost/api/ | 来自 `/api/auth/login` 的 JWT | | FastAPI(直接开发) | http://localhost:8000 | JWT(无 TLS —— 仅限开发) | | Vite 开发服务器 | http://localhost:3000 | — (代理 `/api` 和 `/ws`) | | MLflow UI | https://localhost/mlflow/ | `admin` / `dev` (htpasswd) | | Kibana | https://localhost/kibana/ | `admin` / `dev` (htpasswd) | | MinIO console | http://localhost:9001 | .env 中的 `MINIO_ROOT_USER` / `MINIO_ROOT_PASSWORD` | | Elasticsearch | https://localhost:9200 | .env 中的 `elastic` / `ELASTIC_PASSWORD` | | PostgreSQL | localhost:5432 | .env 中的 `sentinel` / `POSTGRES_PASSWORD` | ### 停止运行环境 ``` # 停止所有 containers(保留 volumes) docker compose -f docker-compose.yml -f docker-compose.dev.yml down # Full reset — 同时删除所有 data volumes docker compose -f docker-compose.yml -f docker-compose.dev.yml down -v ``` ## 身份验证模型 - **角色**:`viewer` < `analyst` < `admin`(层级定义在 `api/auth/dependencies.py` 中)。 - **令牌**:HS256 JWT,默认 TTL 为 30 分钟,使用 `API_SECRET_KEY` 签名。声明包含 `sub`(用户 UUID)、`role`、`iss`、`aud`、`iat`、`exp`。 - **密码哈希**:通过 `argon2-cffi` 使用 Argon2id。对于未知的电子邮件,`/auth/login` 会针对一个虚拟哈希进行验证,以消除否则会暴露哪些电子邮件存在的计时侧信道。 - **速率限制**:SlowAPI 全局限制器(默认 120次/分钟)。`/auth/login` 限制为每个 IP 5次/分钟;`/predict` 和 `/ingest` 为 60次/分钟;`/reports/{id}` 为 30次/分钟。 - **WebSocket**:`wss:///ws/feed?token=` —— 需要 token;服务器还会针对 `CORS_ORIGINS` 验证 `Origin`(CSWSH 防御)。token 无效 → 关闭代码 4401;origin 无效 → 4403;服务器满载 → 4408。 - **Dashboard token 存储**:内存中(Zustand)。不使用 `localStorage` —— 否则,应用上的 XSS 会窃取长效 token。代价是刷新标签页时需要进行一次登录往返。 ## 安全态势 目前已实施的控制措施概览: - **传输**:nginx 终止 TLS 1.2 / 1.3;HTTP → HTTPS 重定向;HSTS `max-age=63072000`。 - **头部**:严格的 CSP,`X-Frame-Options: DENY`,`X-Content-Type-Options: nosniff`, `Referrer-Policy: strict-origin-when-cross-origin`,`Permissions-Policy` 拒绝摄像头 / 麦克风 / 地理位置。 - **认证**:在每个 HTTP + WS 路由上使用 JWT bearer;角色层级;仅限管理员的注册。 - **CORS**:明确的 origin 允许列表;明确的方法 + 头部允许列表(无 `*`)。 - **速率限制**:SlowAPI,基于路由。 - **输入验证**:Pydantic v2 字段验证器限制 features 字典大小(256 个条目),IP 地址通过 `IPvAnyAddress` 解析,值必须有限且有界(`|x| ≤ 1e12`)。 - **模型完整性**:在每次执行 `joblib.load` / `xgb.Booster.load_model` 之前进行 SHA-256 清单验证。生产环境中若无清单则拒绝加载。 - **PDF 安全**:每个受用户影响的字符串均通过 `xml.sax.saxutils.escape` 进行转义;IP 通过 `ipaddress` 验证;MITRE URL 进行协议检查。移除了通配的 `except` 捕获 —— 渲染失败将抛出 `ReportRenderError`。 - **Dashboard**:zod schema 验证每个 REST + WS payload;`safeHttpUrl` 会在渲染为 `href` 之前拒绝 `javascript:` / `data:` 协议;所有路由均围绕 `ErrorBoundary`。 - **容器**:API 以 `read_only: true`、`cap_drop: ALL`、`no-new-privileges` 运行。 - **错误**:全局异常处理程序仅发出通用的 `detail` + 请求 ID;traceback 保留在服务器日志中。 - **数据集**:CICIDS 下载器流式传输至 `.partial` 附属文件,针对 `data/cicids_sha256.txt` 进行 SHA-256 验证,使用指数退避重试,规范化文件名以防范 zip-slip 攻击。 完整披露政策:[SECURITY.md](SECURITY.md)。 ## 测试 ``` # Python — 跨 API、models、ingestion 的 44 个测试 pytest api/tests models/tests ingestion/tests -q # Dashboard — 针对 zod schemas + URL guard 的 vitest suites npm --prefix dashboard run test ``` CI(`.github/workflows/ci.yml`)在每次推送和 pull request 时运行: - 针对需求执行 `ruff check`、`mypy`(建议性)、`bandit -r`、`pip-audit --strict` - 针对 Python 表面执行 `pytest -q --cov` - 针对 dashboard 执行 `npm run test` + `npm run build` 仓库根目录下的 `conftest.py` 设置了 `random.seed(0)` 和 `np.random.seed(0)` autouse,因此无论运行顺序如何,每个测试都是确定性的。 ## 关键文件 - `docker-compose.yml` —— 整个服务图表;ELK TLS 证书引导必须首先成功 - `docker/nginx/nginx.conf` —— TLS 终止、CSP、HSTS、安全头部;单一外部 ingress - `api/main.py` —— FastAPI 生命周期仅加载一次 ML 模型;全局异常处理程序;SlowAPI middleware - `api/auth/security.py` —— JWT 创建 / 解码 + argon2id 密码辅助工具 - `api/services/prediction_service.py` —— 反序列化前的 SHA-256 清单验证 - `ingestion/normalizer.py` —— CICIDS-2017 前导空格表头、Infinity 值、精细与粗糙标签映射 - `models/threat_classifier.py` —— 未见标签过滤器、确定性编码器路径、清单附属文件 - `explainability/report_generator.py` —— 带有 `xml.sax.saxutils.escape` 的 Platypus PDF,用于每个用户字段 - `dashboard/src/schemas/incident.ts` —— zod schema + `safeHttpUrl` 守卫 ## 已知陷阱 - **CICIDS-2017 标头**:所有列名都有导空格(` Label`、` Flow Duration`)。 `normalizer.py` 使用 `df.columns.str.strip()` 去除它们。 - **CICIDS-2017 Infinity 值**:`Flow Bytes/s` 和 `Flow Packets/s` 包含 `Infinity`。 替换为 `np.nan`,然后使用列中位数进行插补。 - **numpy 固定版本**:SHAP 0.45.x 需要 `numpy<2.0`。固定为 `numpy==1.26.4`。 - **XGBoost class_weight**:XGBoost 不接受 `class_weight='balanced'`。使用 `compute_class_weight('balanced', ...)` 并将结果作为 `sample_weight` 传递给 `.fit()`。 - **IsolationForest 训练数据**:仅在 BENIGN 行上进行训练。在所有类上进行训练会破坏正态分布基线。 - **ELK 8.x TLS**:ELK 8 默认启用了安全性。`setup` 服务会在 ES 启动之前将 TLS 证书引导至 `certs` Docker 卷中。证书目录权限必须为 `755`(而不是 `750`),以便 Logstash 能够读取它们。 - **SHAP 多分类形状**:`TreeExplainer.shap_values(X)` 在不同 SHAP 版本中返回的形状不同。 `shap_explainer.py` 会直接向模型询问获胜类,而不是根据 SHAP 总和进行猜测。 - **MLflow 预处理器**:`mlflow.xgboost.autolog()` 会记录 XGBoost 模型,但不会记录 sklearn 预处理器。需手动记录:`mlflow.log_artifact("models/preprocessor.joblib")`。 - **sklearn 版本锁定**:sklearn 1.6+ 添加了 XGBoost 2.0.x 未实现的 `__sklearn_tags__` 协议。固定为 `scikit-learn==1.5.2`。 - **setuptools 固定版本**:setuptools 82+ 移除了 MLflow 2.13.0 所需的 `pkg_resources`。 固定为 `setuptools<82`。 - **模型所有权**:模型由 root(训练)写入,但 API 以 `appuser` 身份运行。 训练后,在容器内运行 `chown -R appuser:appuser /models`。 - **需要 openssl**:`scripts/gen_dev_certs.sh` 需要 PATH 中包含 `openssl`。 - **生产环境中需要模型清单**:在 `APP_ENV=production` 时未设置 `MODEL_MANIFEST_PATH` 是致命的 —— API 不会反序列化未经验证的模型文件。 - **CICIDS 下载器默认严格要求**:首次下载需要 `--skip-hash-check`,之后应填充并提交 `data/cicids_sha256.txt`,以便每次后续运行时进行验证。 ## 技术栈版本 **运行时** - Python 3.12 (Docker) - Node 24 (Docker) - ELK 8.17.0 - XGBoost 2.0.3 + scikit-learn 1.5.2 - FastAPI 0.111.0 - React 18、Vite 5、TypeScript 5 - PostgreSQL 16 - MLflow 2.13.0 - MinIO (最新版) **安全技术栈** - pyjwt 2.9.0(HS256 签名) - argon2-cffi 23.1.0(密码哈希) - slowapi 0.1.9(速率限制) - zod 3.23.8(dashboard 运行时验证) - aiosqlite 0.20.0(仅限开发测试)
标签:AMSI绕过, Apex, ATT&CK框架, AV绕过, FastAPI, React, SOC分析师, Syscalls, 内容过滤, 威胁检测, 安全运营, 扫描框架, 机器学习, 测试用例, 请求拦截, 越狱测试, 逆向工具