Aiyeesha/log-anomaly-detector
GitHub: Aiyeesha/log-anomaly-detector
一个基于规则的认证日志异常检测引擎,通过透明且经过单元测试的规则实时发现暴力破解、不可能旅行、撞库和非工作时间访问等安全威胁。
Stars: 0 | Forks: 0
# 🕵️ 日志异常 Detector
*[点击查看法语版本](#-log-anomaly-detector-1)*
一个用于认证日志的基于规则的检测引擎——用于发现暴力破解尝试、不可能旅行登录、撞库突发以及非工作时间访问,每一项都使用透明且经过单元测试的规则,而不是黑盒模型。
## 为什么做这个项目
大多数“SOC 仪表板”演示显示的都是在其他地方已经存在的警报。而这个项目会*生成*警报:它接收原始认证事件,并通过检测逻辑进行处理,该逻辑必须对事件的*序列*进行推理——比如在短时间内聚集的失败尝试、同一个账户太快出现在两个国家、单个 IP 尝试许多不同的用户名。这与过滤或显示预先标记好的数据有着本质上的(也是更困难的)区别。
## 功能
- **四个独立的检测规则**,每个都是一个无 I/O 的纯函数:
- **暴力破解** — 同一账户在 5 分钟内有 5 次或以上的失败登录
- **不可能旅行** — 同一账户在比合理旅行时间(2 小时窗口)更短的间隔内,成功从两个不同的国家登录
- **撞库** — 同一源 IP 在 10 分钟内有 8 个或以上的*不同*用户名登录失败(这是暴力破解垂直模式对应的横向模式)
- **非工作时间访问** — 在 UTC 时间 22:00 到 06:00 之间的成功登录
- **实时接收** — `POST /api/logs` 会在其实时窗口内,针对所有四个规则实时运行每个新事件
- **异常去重** — 如果源自某规则的未解决异常仍在其自身的时间窗口内,则该规则不会针对同一对象重新触发,因此持续的攻击不会产生重复的垃圾警报
- **“模拟攻击流量”按钮** — 重放一个特意触发所有四个规则各一次的合成场景,这对于演示引擎非常有用,免去手动构造大量请求的麻烦
- **持久化存储**(SQLite),用于原始事件和派生的异常
## 架构
```
┌─────────────┐ REST (fetch) ┌───────────────────────────┐
│ React UI │ ───────────────► │ FastAPI routers │
│ (Vite/TS) │ ◄─────────────── │ logs / anomalies / simulate │
└─────────────┘ └──────────────┬─────────────┘
│
┌───────▼───────┐
│ detection.py │ ← 4 pure rule functions,
└───────┬───────┘ unit-tested with plain dicts
┌───────▼───────┐
│ crud.py │ (windowing + dedup + persistence)
└───────┬───────┘
┌───────▼───────┐
│ SQLAlchemy │
│ (SQLite) │
└────────────────┘
```
`detection.py` 接收事件字典的普通列表,并返回普通的异常字典——没有数据库会话,也没有 FastAPI 请求上下文。`crud.py` 是唯一知道如何获取先前事件的正确时间窗口的地方(针对以账户为中心的规则按用户名获取,针对撞库规则按源 IP 获取),并将规则的输出转换为持久化、去重后的行。这种拆分使得 20 个规则边缘情况能在几毫秒内完成测试,且无需配置任何数据库。
## 技术栈
| 层级 | 技术 |
|-------|------------|
| 后端 | Python 3.11+, FastAPI, SQLAlchemy |
| 数据库 | SQLite (基于文件,零配置) |
| 认证 | 在接收、解决和模拟端点上使用 API 密钥 |
| 前端 | React 18, TypeScript, Vite |
| 测试 | Pytest — 纯检测规则测试 + 完整 API 测试 |
| 容器 | Docker Compose |
## 快速开始
### 使用 Docker Compose
```
docker-compose up
```
然后打开 [http://localhost:5176](http://localhost:5176)。后端在首次启动时会植入一个合成场景,以便立即显示所有四种规则类型。
### 手动设置
**后端**
```
cd backend
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
cp .env.example .env
pip install -r requirements.txt
uvicorn app.main:app --reload --port 8003
```
**前端**
```
cd frontend
npm install
npm run dev
```
### 运行测试
```
cd backend
pip install -r requirements-dev.txt
pytest -v
```
`test_detection.py` 通过手动构建的事件序列和固定的时间戳,覆盖了每条规则的触发和非触发条件——没有数据库,没有时钟依赖,不会出现不稳定性。`test_api.py` 对整个技术栈进行了测试,包括断言植入的场景会为每条规则精确生成一个异常(该场景锚定在一天中的固定时间点,而不是实际的挂钟时间,正是为了无论何时运行测试,该断言都是确定性的)。
## API 参考
| 方法 | 端点 | 认证 | 描述 |
|--------|----------|------|-------------|
| `GET` | `/api/logs` | — | 最近的原始日志事件 (可选 `?username=&source_ip=&limit=100`) |
| `POST` | `/api/logs` | `X-API-Key` | 接收一个事件;立即运行检测并返回任何新的异常 |
| `GET` | `/api/anomalies` | — | 列出异常 (可选 `?severity=&resolved=&limit=100`) |
| `PATCH` | `/api/anomalies/{id}/resolve` | `X-API-Key` | 将异常标记为已解决 |
| `POST` | `/api/simulate` | `X-API-Key` | 重放演示场景 (每条规则一个异常) |
| `GET` | `/api/stats` | — | 事件/异常总数、未解决的数量、每条规则的触发计数 |
后端启动后,可在 `/docs` 查看交互式 OpenAPI 文档。
## 项目结构
```
.
├── backend/
│ ├── app/
│ │ ├── main.py # App factory, lifespan (DB init + scenario seed)
│ │ ├── config.py # Settings
│ │ ├── database.py # SQLAlchemy engine/session
│ │ ├── models.py # LogEventORM, AnomalyORM
│ │ ├── schemas.py # Pydantic schemas
│ │ ├── detection.py # The 4 detection rules (pure, unit-tested)
│ │ ├── crud.py # Windowing, dedup, persistence, orchestration
│ │ ├── security.py # API-key dependency
│ │ ├── seed_data.py # Deterministic demo scenario builder
│ │ └── routers/
│ │ ├── logs.py
│ │ ├── anomalies.py
│ │ ├── simulate.py
│ │ └── stats.py
│ ├── tests/
│ │ ├── test_detection.py # Pure rule tests, no DB, no clock dependency
│ │ └── test_api.py
│ ├── requirements.txt
│ ├── requirements-dev.txt
│ ├── .env.example
│ └── Dockerfile
├── frontend/
│ └── src/
│ ├── api/client.ts
│ ├── hooks/useAnomalies.ts
│ └── components/
│ ├── StatsPanel.tsx
│ ├── AnomalyTable.tsx
│ ├── SimulateControls.tsx
│ └── LogFeed.tsx
└── docker-compose.yml
```
## 已知限制
- 检测规则使用固定的阈值(5 次失败、8 个不同用户等),而不是基于每个用户/组织生成自适应基线——真实系统会根据环境调整这些参数,或者使用统计基线
- 没有地理位置查找功能——“国家”是接收事件中的一个字段,而不是从源 IP 推导出来的,因此“不可能旅行”规则信任日志源报告的任何内容
- 24 小时的回溯窗口是一个固定常量;生产系统可能会按规则进行索引和窗口化,而不是在每次接收事件时重新查询主体的完整历史记录
## 许可证
MIT
# 🕵️ 日志异常 Detector
*[上方为英文版本](#-log-anomaly-detector)*
一个用于认证日志的基于规则的检测引擎——用于发现暴力破解尝试、不可能旅行登录、撞库突发以及非工作时间访问,每一项都使用透明且经过单元测试的规则,而不是黑盒模型。
## 为什么做这个项目
大多数“SOC 仪表板”演示显示的都是在其他地方已经存在的警报。而这个项目会*生成*警报:它接收原始认证事件,并通过检测逻辑进行处理,该逻辑必须对事件的*序列*进行推理——比如在短时间内聚集的失败尝试、同一个账户太快出现在两个国家、单个 IP 尝试许多不同的用户名。这与过滤或显示预先标记好的数据有着本质上的(也是更困难的)区别。
## 功能
- **四个独立的检测规则**,每个都是一个无 I/O 的纯函数:
- **暴力破解** — 同一账户在 5 分钟内有 5 次或以上的失败登录
- **不可能旅行** — 同一账户在比合理旅行时间(2 小时窗口)更短的间隔内,成功从两个不同的国家登录
- **撞库** — 同一源 IP 在 10 分钟内有 8 个或以上的*不同*用户名登录失败(这是暴力破解垂直模式对应的横向模式)
- **非工作时间访问** — 在 UTC 时间 22:00 到 06:00 之间的成功登录
- **实时接收** — `POST /api/logs` 会在其实时窗口内,针对所有四个规则实时运行每个新事件
- **异常去重** — 如果源自某规则的未解决异常仍在其自身的时间窗口内,则该规则不会针对同一对象重新触发,因此持续的攻击不会产生重复的垃圾警报
- **“模拟攻击流量”按钮** — 重放一个特意触发所有四个规则各一次的合成场景,这对于演示引擎非常有用,免去手动构造大量请求的麻烦
- **持久化存储**(SQLite),用于原始事件和派生的异常
## 架构
```
┌─────────────┐ REST (fetch) ┌───────────────────────────┐
│ UI React │ ───────────────► │ Routers FastAPI │
│ (Vite/TS) │ ◄─────────────── │ logs / anomalies / simulate │
└─────────────┘ └──────────────┬─────────────┘
│
┌───────▼───────┐
│ detection.py │ ← 4 fonctions de règles pures,
└───────┬───────┘ testées avec de simples dicts
┌───────▼───────┐
│ crud.py │ (fenêtrage + dédup + persistance)
└───────┬───────┘
┌───────▼───────┐
│ SQLAlchemy │
│ (SQLite) │
└────────────────┘
```
`detection.py` 接收事件字典的普通列表,并返回普通的异常字典——没有数据库会话,也没有 FastAPI 请求上下文。`crud.py` 是唯一知道如何获取先前事件的正确时间窗口的地方(针对以账户为中心的规则按用户名获取,针对撞库规则按源 IP 获取),并将规则的输出转换为持久化、去重后的行。这种拆分使得 20 个规则边缘情况能在几毫秒内完成测试,且无需配置任何数据库。
## 技术栈
| 层级 | 技术 |
|--------|-------------|
| 后端 | Python 3.11+, FastAPI, SQLAlchemy |
| 数据库 | SQLite (基于本地文件,零配置) |
| 认证 | 在接收、解决和模拟端点上使用 API 密钥 |
| 前端 | React 18, TypeScript, Vite |
| 测试 | Pytest — 纯检测规则测试 + 完整 API 测试 |
| 容器 | Docker Compose |
## 快速开始
### 使用 Docker Compose
```
docker-compose up
```
然后打开 [http://localhost:5176](http://localhost:5176)。后端在首次启动时会植入一个合成场景,以便立即显示所有四种规则类型。
### 手动安装
**后端**
```
cd backend
python -m venv .venv && source .venv/bin/activate # Windows : .venv\Scripts\activate
cp .env.example .env
pip install -r requirements.txt
uvicorn app.main:app --reload --port 8003
```
**前端**
```
cd frontend
npm install
npm run dev
```
### 运行测试
```
cd backend
pip install -r requirements-dev.txt
pytest -v
```
`test_detection.py` 通过手动构建的事件序列和固定的时间戳,覆盖了每条规则的触发和非触发条件——没有数据库,没有时钟依赖,不会出现不稳定性。`test_api.py` 对整个技术栈进行了测试,包括断言植入的场景会为每条规则精确生成一个异常(该场景锚定在一天中的固定时间点,而不是实际的挂钟时间,正是为了无论何时运行测试,该断言都是确定性的)。
## API 参考
| 方法 | 端点 | 认证 | 描述 |
|---------|----------|------|--------------|
| `GET` | `/api/logs` | — | 最近的原始日志事件 (可选 `?username=&source_ip=&limit=100`) |
| `POST` | `/api/logs` | `X-API-Key` | 接收一个事件;立即运行检测并返回任何新的异常 |
| `GET` | `/api/anomalies` | — | 列出异常 (可选 `?severity=&resolved=&limit=100`) |
| `PATCH` | `/api/anomalies/{id}/resolve` | `X-API-Key` | 将异常标记为已解决 |
| `POST` | `/api/simulate` | `X-API-Key` | 重放演示场景 (每条规则一个异常) |
| `GET` | `/api/stats` | — | 事件/异常总数、未解决的数量、每条规则的触发计数 |
后端启动后,可在 `/docs` 查看交互式 OpenAPI 文档。
## 项目结构
```
.
├── backend/
│ ├── app/
│ │ ├── main.py # Factory de l'app, lifespan (init DB + seed du scénario)
│ │ ├── config.py # Configuration
│ │ ├── database.py # Moteur/session SQLAlchemy
│ │ ├── models.py # LogEventORM, AnomalyORM
│ │ ├── schemas.py # Schémas Pydantic
│ │ ├── detection.py # Les 4 règles de détection (pures, testées)
│ │ ├── crud.py # Fenêtrage, dédup, persistance, orchestration
│ │ ├── security.py # Dépendance clé API
│ │ ├── seed_data.py # Générateur de scénario de démo déterministe
│ │ └── routers/
│ │ ├── logs.py
│ │ ├── anomalies.py
│ │ ├── simulate.py
│ │ └── stats.py
│ ├── tests/
│ │ ├── test_detection.py # Tests purs des règles, sans DB, sans dépendance horloge
│ │ └── test_api.py
│ ├── requirements.txt
│ ├── requirements-dev.txt
│ ├── .env.example
│ └── Dockerfile
├── frontend/
│ └── src/
│ ├── api/client.ts
│ ├── hooks/useAnomalies.ts
│ └── components/
│ ├── StatsPanel.tsx
│ ├── AnomalyTable.tsx
│ ├── SimulateControls.tsx
│ └── LogFeed.tsx
└── docker-compose.yml
```
## 已知限制
- 检测规则使用固定的阈值(5 次失败、8 个不同用户等),而不是基于每个用户/组织生成自适应基线——真实系统会根据环境调整这些参数,或者使用统计基线
- 没有地理位置查找功能——“国家”是接收事件中的一个字段,而不是从源 IP 推导出来的,因此“不可能旅行”规则信任日志源报告的任何内容
- 24 小时的回溯窗口是一个固定常量;生产系统可能会按规则进行索引和窗口化,而不是在每次接收事件时重新查询主体的完整历史记录
## 许可证
MIT
标签:AV绕过, FastAPI, React, Syscalls, 异常检测, 红队行动, 网络测绘, 请求拦截, 身份验证安全, 逆向工具