PopElite/esc
GitHub: PopElite/esc
ESC 是一个生产就绪的 SaaS 安全运营平台,通过规则引擎与多 LLM 协同分析实现日志异常检测、沙盒攻击模拟和人工审批缓解的完整闭环。
Stars: 0 | Forks: 0
# ESC — 精英安全 Copilot
## 架构概述
```
┌─────────────────────────────────────────────────────────────────────┐
│ INGESTION LAYER │
│ Nginx webhooks / CSV upload / Syslog / Cloud audit APIs │
└──────────────────────────────┬──────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ EVENT PIPELINE (Redis Bull) │
│ Dedup → Normalize → Fingerprint → Queue → Priority routing │
└──────────────────────────────┬──────────────────────────────────────┘
│
┌──────────┴──────────┐
▼ ▼
┌─────────────────┐ ┌─────────────────────┐
│ DETECTION │ │ LLM ANALYSIS │
│ ENGINE │ │ ORCHESTRATOR │
│ │ │ │
│ ► Rule-based │ │ 1. Claude Sonnet │
│ ► Statistical │ │ 2. GPT-4o Mini │
│ ► Signature │ │ 3. Ollama (local) │
│ ► Heuristic │ │ │
│ │ │ Auto-failover │
│ 6 built-in │ │ Strict JSON output │
│ rule classes │ │ Confidence score │
└────────┬────────┘ └──────────┬──────────┘
│ │
└──────────┬─────────────┘
▼
┌─────────────────────────┐
│ ALERT ENGINE │
│ Risk scoring · SLA │
│ Webhook · Email notify │
│ RBAC-scoped visibility │
└────────────┬────────────┘
│
┌────────────┴────────────┐
▼ ▼
┌───────────────────┐ ┌────────────────────────┐
│ MITIGATION │ │ SANDBOX ENGINE │
│ PLANNER (LLM) │ │ │
│ │ │ ⚠ SYNTHETIC ONLY │
│ Immediate steps │ │ No real network I/O │
│ Short-term plan │ │ Memory-isolated sim │
│ Long-term fixes │ │ 8 attack vectors │
│ │ │ Detection rate report │
│ requiresApproval │ │ │
│ = true ALWAYS │ │ │
└───────────────────┘ └────────────────────────┘
│
▼
┌────────────────────────────────────────────────┐
│ POSTGRESQL (Prisma ORM) │
│ Organizations · Users · LogEvents │
│ Detections · Alerts · AuditLogs │
│ DetectionRules · SandboxSimulations │
└────────────────────────────────────────────────┘
```
## 模块映射
```
esc/
├── backend/
│ ├── src/
│ │ ├── index.ts # API entry: Express + middleware, connects DB
│ │ ├── worker.ts # Bull worker process: full 7-step pipeline
│ │ ├── routes.ts # All API routes (real Prisma reads/writes)
│ │ ├── modules/
│ │ │ ├── auth/
│ │ │ │ └── auth.service.ts # JWT, RBAC, password hashing
│ │ │ ├── detection/
│ │ │ │ ├── detection.engine.ts # 6 rule classes, in-memory context
│ │ │ │ └── llm.orchestrator.ts # Claude→GPT→Ollama failover chain
│ │ │ ├── sandbox/
│ │ │ │ └── sandbox.engine.ts # Synthetic attack simulation (safe)
│ │ │ ├── queue/
│ │ │ │ └── log-ingest.queue.ts # Bull queue producer (Redis-backed)
│ │ │ └── db/
│ │ │ └── prisma.client.ts # PrismaClient singleton, connect w/ retry
│ │ ├── core/
│ │ │ └── middleware/
│ │ │ └── security.middleware.ts # Helmet, rate limit, CORS, audit
│ │ └── shared/
│ │ ├── types/index.ts # Shared TypeScript interfaces
│ │ └── utils/
│ │ ├── logger.ts # Winston structured logging
│ │ └── crypto.ts # AES-256-GCM, HMAC, fingerprint
│ ├── prisma/
│ │ ├── schema.prisma # Full DB schema (8 models, RBAC)
│ │ └── seed.ts # Seeds demo org/user/log source
│ ├── scripts/
│ │ └── test-ingestion.js # End-to-end pipeline smoke test
│ ├── Dockerfile # Multi-stage, non-root user, runs prisma generate
│ └── .env.example
├── frontend/
│ └── src/ # React dashboard (see below)
├── docker-compose.yml # Full stack: PG + Redis + API + FE + Nginx
└── scripts/db/init.sql # DB init + extensions
```
## 安全设计原则
### 身份验证
- JWT (HS256) 有效期 15 分钟 + refresh token (7d)
- 用于 token 吊销的 JWT ID (`jti`) 字段
- bcrypt cost factor 14(刻意放慢)
- 常数时间密码比较(防止 timing attacks)
- 登录失败时逐步增加延迟(防暴力破解)
- 指数退避的账户锁定机制
### RBAC(4 种角色)
| 角色 | 可执行操作 |
|------|--------|
| `SUPER_ADMIN` | 所有操作 |
| `SECURITY_ADMIN` | 所有安全操作,读取用户信息 |
| `ANALYST` | 读取警报,提出缓解措施,审查检测 |
| `READ_ONLY` | 对警报/检测/日志的只读访问权限 |
| `SERVICE_ACCOUNT` | 仅用于日志接入(API keys) |
### 数据保护
- 对静态敏感数据(MFA 密钥、webhook URLs)使用 AES-256-GCM 加密
- 使用 SHA-256 指纹进行日志去重
- HMAC-SHA256 webhook 签名验证
- 日志中隐藏所有敏感字段 (`[REDACTED]`)
- 生产环境下的 PostgreSQL `sslmode=require`
### 纵深防御(API)
- `helmet` 和严格的 CSP
- `cors` 白名单(非通配符)
- 分级速率限制(全局 100/15分钟,身份验证 10/15分钟,接入 10k/分钟)
- `express-validator` 通过 Zod 进行输入验证
- 拦截 Null byte injection
- 请求大小限制 (10MB)
- 非 root Docker 用户 + `cap_drop: ALL` + `no-new-privileges`
- 内部 Docker 网络(DB/Redis 绝不公开暴露)
### 沙盒安全
沙盒引擎是纯模拟的:
- 不执行 `child_process`
- 没有连接到外部主机的 `net.Socket` 或 `http.request`
- 没有文件系统写入操作
- 所有“攻击”事件均在内存中生成
- 需要作为显式开关的 `SANDBOX_MODE=true` 环境变量
- 每个结果都包含 `sandboxConfirmation` token
### 缓解措施安全
- 所有 `MitigationAction` 对象上硬编码了 `automated: false`
- 在 LLM prompt 和响应 schema 中强制执行 `requiresApproval: true`
- LLM 收到的指令是:“绝不建议自动化的破坏性操作”
- 所有计划在执行任何步骤之前都需要人工审查
## API Endpoints
```
GET /api/v1/health # Public health check
GET /api/v1/health/detailed # Auth required: SECURITY_ADMIN
POST /api/v1/auth/login # Login → JWT
POST /api/v1/auth/logout # Revoke session
POST /api/v1/logs/ingest # Bulk log ingestion (API key or JWT)
GET /api/v1/alerts # List alerts (org-scoped)
POST /api/v1/alerts/:id/acknowledge # Acknowledge alert
POST /api/v1/analysis/event # LLM analyze a log event
POST /api/v1/analysis/mitigation # Generate mitigation plan
POST /api/v1/sandbox/simulate # Run sandbox simulation
GET /api/v1/dashboard/stats # Dashboard KPIs
GET /api/v1/audit # Audit log (SECURITY_ADMIN)
```
## 检测规则
| ID | 名称 | 方法 | 风险 |
|----|------|--------|------|
| BF-001 | 暴力破解登录 | 阈值/时间窗口 | HIGH |
| INJ-001 | SQL Injection | Regex 特征码 | CRITICAL |
| PT-001 | Path Traversal | Regex 特征码 | HIGH |
| RA-001 | 速率滥用 / DDoS | 统计 | HIGH |
| PE-001 | Privilege Escalation | 基于规则 | CRITICAL |
| GEO-001 | 不可能旅行 | 统计 | HIGH |
## 快速开始(完整工作流水线)
```
# 1. 配置 secrets
cp backend/.env.example backend/.env
# 编辑 backend/.env — 至少设置 JWT_SECRET, JWT_REFRESH_SECRET, ENCRYPTION_KEY
# (ANTHROPIC_API_KEY / OPENAI_API_KEY 可选 — pipeline 没有它们也能运行,
# LLM 分析步骤将被跳过/使用 fallback)
# 2. 一次性启动 + 冒烟测试
./run.sh
# ── 或手动 ──
docker-compose up -d postgres redis
docker-compose up migrate # runs prisma migrate deploy + db seed
docker-compose up -d worker backend frontend nginx
# 3. 运行 end-to-end pipeline 测试
docker-compose exec backend node scripts/test-ingestion.js
```
测试脚本以初始化的 demo 管理员身份登录,将一批日志事件
(来自同一个 IP 的 15 次暴力破解登录失败,一个 SQL injection payload,一个
path traversal payload,以及一个正常事件)POST 到 `/api/v1/logs/ingest`,然后轮询
`/api/v1/alerts`,直到 worker 在 PostgreSQL 中生成真实的警报行,
并将它们打印出来。
观察流水线实时执行:
```
docker-compose logs -f worker
```
你将看到如下输出:
```
[PIPELINE] ─────────────────────────────────────────────
[PIPELINE] job=3 requestId=a1b2c3d4
[PIPELINE] STEP 1/7 -> normalizing event
[PIPELINE] STEP 2/7 -> persisting LogEvent (fingerprint=9f8e7d6c5b4a...)
[PIPELINE] STEP 3/7 -> running detection engine
[PIPELINE] STEP 4/7 -> detection fired: category=BRUTE_FORCE risk=HIGH confidence=0.85 method=RULE_BASED
[PIPELINE] STEP 5/7 -> calling LLM orchestrator (Claude -> GPT -> Ollama)
[PIPELINE] STEP 5/7 -> LLM analysis complete: provider=claude riskLevel=HIGH confidence=0.91
[PIPELINE] STEP 6/7 -> persisting Detection + Alert rows
[PIPELINE] STEP 7/7 -> alert persisted: id=7f3a... status=OPEN
[PIPELINE] DONE (alert created) in 842ms
[PIPELINE] ─────────────────────────────────────────────
```
### 手动 API 演练
```
# 登录(内置的 demo 管理员)
TOKEN=$(curl -s -X POST http://localhost:3001/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@esc.local","password":"Demo@SecurePass123!"}' \
| jq -r .data.accessToken)
# Ingest 一个恶意 event
curl -s -X POST http://localhost:3001/api/v1/logs/ingest \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{
"sourceId": "00000000-0000-0000-0000-000000000002",
"analyzeWithLLM": true,
"events": [{
"timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%S.000Z)"'",
"rawPayload": {"msg": "test"},
"ipAddress": "203.0.113.99",
"endpoint": "/api/users?id=1%27%20OR%20%271%27=%271",
"method": "GET",
"statusCode": 400,
"userAgent": "sqlmap/1.7"
}]
}'
# -> 202 Accepted,返回 jobIds。Worker 会异步处理它。
# 轮询 alerts(来自 PostgreSQL 的真实数据行)
curl -s http://localhost:3001/api/v1/alerts -H "Authorization: Bearer $TOKEN" | jq
```
### 实际连接的内容(无伪代码,无 mocks)
| 组件 | 实际情况 |
|---|---|
| `POST /logs/ingest` | 验证输入,其自身不进行任何持久化——将每个事件作为一个 Bull job 推送到 `esc-log-ingest` 队列(基于 Redis) |
| `worker.ts` | 独立的 Node 进程,`queue.process()` 消费者,在每个 job 上同步运行**完整的 7 步流水线** |
| `detection.engine.ts` | 真正的内存中有状态规则引擎(IP/用户/端点历史映射),针对每个事件运行 |
| `llm.orchestrator.ts` | 真实的 HTTP 调用,通过 try/catch 故障转移链连接到 Anthropic/OpenAI/Ollama;如果 3 个全部失败或未设置密钥,则优雅地降级为安全的 fallback 对象 |
| `prisma.client.ts` | 真正的 `PrismaClient` 单例,在后端和 worker 启动时通过重试/退避机制进行连接 |
| `LogEvent` / `Detection` / `Alert` / `AuditLog` 行 | 确实由 worker 按顺序写入 PostgreSQL,每个事件对应 |
| `GET /alerts` | 真正的 `prisma.alert.findMany()`,范围限制为调用者的 `organizationId`,并带有 `include: { detection: ... }` |
| `prisma/seed.ts` | 创建一个真实的 Organization,一个 SECURITY_ADMIN User(使用 bcrypt 哈希处理的密码),以及一个默认的 LogSource,以便 demo 可以立即使用 |
## 生产环境检查清单
- [ ] 更换 `.env` 中的所有密钥(JWT_SECRET、ENCRYPTION_KEY 等)
- [ ] 启用 PostgreSQL SSL (`sslmode=require`)
- [ ] 将 `CORS_ORIGINS` 设置为您的实际域名
- [ ] 配置用于警报通知的 SMTP
- [ ] 在 Nginx (`./nginx/ssl/`) 中设置 TLS
- [ ] 启用日志保留策略(默认:365 天)
- [ ] 配置 Redis 持久化和密码
- [ ] 根据您的流量基准审查和调整检测阈值
- [ ] 设置外部监控(正常运行时间、错误率警报)
- [ ] 为所有 `SECURITY_ADMIN` 和 `SUPER_ADMIN` 账户启用 MFA
*ESC 是一个分析和警报平台。它从不自动执行缓解措施。所有建议的操作都需要明确的人工批准。*
标签:SaaS, 威胁分析, 搜索引擎查询, 攻击仿真, 日志异常检测, 测试用例, 自动化侦查工具, 自动化攻击, 请求拦截