hubertwojcik/ssh-log-anomaly-detector
GitHub: hubertwojcik/ssh-log-anomaly-detector
一款结合启发式规则与 Isolation Forest 模型的 Python 工具,用于分析 Linux auth.log 并检测 SSH 暴力破解、异常登录时间、新 IP 和提权等可疑活动。
Stars: 0 | Forks: 0
# ssh-log-anomaly-detector
一个 Python 工具,它通过结合启发式规则和 Isolation Forest ML 模型,分析 Linux `auth.log` 文件并检测可疑的 SSH 活动。
检测四类异常:暴力破解攻击、非用户历史时间段的登录、来自新 IP 地址的登录,以及提权尝试。每项发现都包含严重程度、人类可读的描述以及原始日志证据。
```
$ ssh-anomaly detect auth.log
SSH Log Anomaly Detector
File: auth.log | Events: 14,823 | Time range: 2024-06-01 → 2024-06-08
┌──────────────────────┬────────────────┬───────────────┬──────────┬────────────────────────────────────────────────┐
│ Timestamp │ Source IP │ Type │ Severity │ Description │
├──────────────────────┼────────────────┼───────────────┼──────────┼────────────────────────────────────────────────┤
│ 2024-06-03 03:12:44 │ 198.51.100.42 │ brute-force │ HIGH │ 538 failed attempts in 60s (threshold: 10) │
│ 2024-06-04 03:47:21 │ 203.0.113.17 │ unusual-time │ MEDIUM │ alice logged in at 03:47 — baseline: 08–18 │
│ 2024-06-05 11:23:05 │ 192.0.2.88 │ new-ip │ MEDIUM │ bob logged in from unseen IP (30-day baseline) │
│ 2024-06-06 14:55:33 │ — │ priv-esc │ HIGH │ 7 sudo failures then success for user charlie │
│ 2024-06-07 09:10:12 │ 198.51.100.99 │ ml-anomaly │ LOW │ Isolation Forest score: -0.41 (threshold -0.3) │
└──────────────────────┴────────────────┴───────────────┴──────────┴────────────────────────────────────────────────┘
Summary: 5 anomalies (HIGH: 2 MEDIUM: 2 LOW: 1)
```
## 工作原理
```
/var/log/auth.log
│
▼
┌─────────┐ regex + pandas ┌──────────────────┐
│ Parser │ ──────────────────► │ Structured │
│ │ │ DataFrame │
└─────────┘ └────────┬─────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Feature │ │ Heuristic │ │ ML │
│ Engineering │ │ Detectors │ │ Detector │
│ │ │ │ │ (Iso Forest) │
│ failure_rate │ │ brute-force │ │ │
│ inter_arrival│ │ unusual-time │ │ per-IP │
│ login_hour │ │ new-ip │ │ feature │
│ distinct_users │ priv-esc │ │ matrix │
└──────────────┘ └──────┬───────┘ └──────┬───────┘
│ │
└─────────┬─────────┘
▼
┌──────────────┐
│ Reporter │
│ table / json │
└──────────────┘
```
**启发式规则** 快速、可解释,且在已知模式下零误报。**Isolation Forest** 能够捕获不匹配任何特定规则的异常——即在统计上偏离基线的异常特征组合。
## 异常类型
| 类型 | 检测方法 | 捕获内容 |
|---|---|---|
| **暴力破解** | 启发式 —— 滑动窗口 | 同一 IP 在 T 秒内出现 N 次失败登录 |
| **异常登录时间** | 启发式 —— 单用户基线 | 成功登录发生在用户的历史时间段之外 |
| **新 IP** | 启发式 —— 单用户 IP 历史 | 成功登录来自基线期间从未见过的新 IP |
| **提权** | 启发式 —— 事件序列 | Sudo 失败、root SSH 尝试、失败后紧接成功 |
| **ML 异常** | Isolation Forest | 规则未涵盖的统计学异常 IP 行为 |
请参阅 [`docs/anomaly-types.md`](docs/anomaly-types.md) 以了解检测逻辑、调优指南以及每种类型的示例日志行。
## 数据来源
两个互补的来源为该项目提供数据:用于确定性测试的合成数据,以及用于生成真实训练/评估数据的真实一次性蜜罐:
| 来源 | 位置 | 用途 |
|---|---|---|
| **合成样本** | `data/samples/` | 带有已知位置已知异常的确定性测试夹具——用于解析器/检测器的单元测试。由 `data/generate_samples.py` 生成。 |
| **真实蜜罐日志** | `data/real/` | 从暴露在 22 端口上的一次性云 VM 收集的真实 `auth.log` 流量——用于训练/评估 Isolation Forest,并针对真实攻击者行为验证启发式规则。 |
**为什么要使用真实蜜罐?** 一个可公开访问的 SSH 端口会在几小时内被真实的僵尸网络扫描和暴力破解——这是目前最难令人信服地伪造的一类(攻击者 IP 的多样性、撞库的时间点、工具指纹)。编写脚本生成合成数据往往过于干净和规律,这使得模型可以通过学习生成器的特征来“作弊”,而不是学习真实的异常行为。
**哪些仍然需要编写脚本。** 没人会合法地登录到蜜罐,因此“正常”基线是刻意生成的:少数专用账户、仅密钥认证、通过 cron 在不同时间段驱动登录,以构建不同的单用户行为画像(参见 `infra/ansible/baseline_traffic.yml`)。提权示例也是合成的——一个隔离得当的蜜罐绝不应该真的被攻破。
**安全性。** 该蜜罐是一个一次性、隔离的实例:专用的安全组(仅开放 22 端口),不重复使用其他基础设施的密钥或凭证,没有敏感数据,真实访问仅限密钥认证。来自互联网的密码失败尝试会自然地填充到 `auth.log` 中,而无需冒任何账户被破解的风险。
## 安装说明
```
git clone https://github.com/hubertwojcik/ssh-log-anomaly-detector
cd ssh-log-anomaly-detector
pip install -e .
```
要求 Python 3.11+。
## 使用方法
**基础扫描:**
```
ssh-anomaly detect /var/log/auth.log
```
**输出 JSON 用于下游处理:**
```
ssh-anomaly detect auth.log --format json | jq '.[] | select(.severity == "HIGH")'
```
**仅输出 HIGH 严重级别,并写入文件:**
```
ssh-anomaly detect auth.log --quiet --output findings.txt
```
**调整阈值并仅运行启发式检测器:**
```
ssh-anomaly detect auth.log \
--detectors heuristic \
--threshold 5 \
--window 2m \
--baseline-days 14
```
**完整选项:**
```
Usage: ssh-anomaly detect [OPTIONS] LOGFILE
Options:
--format [table|json|csv] Output format [default: table]
--threshold INTEGER Brute-force failure threshold [default: 10]
--window TEXT Aggregation time window [default: 1m]
--baseline-days INTEGER Days of history for per-user baselines [default: 7]
--detectors [all|heuristic|ml] Which detectors to run [default: all]
--output FILE Write results to file instead of stdout
--quiet Only report HIGH severity findings
--help Show this message and exit.
```
## 项目结构
```
ssh-log-anomaly-detector/
├── src/
│ └── ssh_anomaly/
│ ├── parser.py # auth.log → pd.DataFrame
│ ├── features.py # per-event and per-IP feature engineering
│ ├── detectors/
│ │ ├── heuristic.py # BruteForceDetector, UnusualTimeDetector, NewIPDetector, PrivEscDetector
│ │ └── ml.py # IsolationForestDetector
│ ├── reporter.py # rich table, JSON, CSV output
│ └── cli.py # Click entrypoint
│
├── tests/
│ ├── test_parser.py
│ ├── test_features.py
│ └── test_detectors.py
│
├── infra/
│ ├── terraform/ # provisions the disposable honeypot VM (cheap cloud instance)
│ └── ansible/
│ ├── honeypot.yml # sshd config, log rotation, syncs auth.log → data/real/
│ └── baseline_traffic.yml # cron-driven scripted logins simulating legitimate users
│
├── data/
│ ├── generate_samples.py # generates synthetic auth.log files with known anomalies
│ ├── samples/ # synthetic, deterministic — unit test fixtures
│ │ ├── normal.log # 7 days of clean traffic — no anomalies
│ │ ├── bruteforce.log # 538 failed attempts from single IP
│ │ ├── after_hours.log # 3am login for a 9–17 user
│ │ ├── new_ip.log # login from unseen IP
│ │ ├── privesc.log # sudo failures then success
│ │ └── mixed.log # all of the above with realistic noise
│ └── real/ # auth.log pulled from the honeypot — ML training/eval
│
├── docs/
│ ├── anomaly-types.md # detection logic and tuning guidance
│ └── detector-comparison.md # heuristics vs ML: what each catches
│
└── pyproject.toml
```
## 技术栈
| 库 | 作用 |
|---|---|
| `pandas` | 日志解析,DataFrame 操作,滚动窗口聚合 |
| `scikit-learn` | Isolation Forest,StandardScaler |
| `click` | CLI 接口 |
| `rich` | 带有严重程度颜色编码的终端表格输出 |
| `pytest` | 测试套件 —— 基于合成日志文件的集成测试 |
## 运行测试
```
pytest -v
```
测试使用合成的 `data/samples/` 文件作为夹具 —— 无需对内部函数进行 mock。每个检测器都会进行端到端测试:解析器 → 特征 → 检测器 → 发现结果。
## 设计说明
**为什么选择 Isolation Forest?** 它是无监督的,不需要带标签的攻击数据。考虑到真实的 `auth.log` 数据绝大多数是正常流量,这非常契合——异常在定义上就是特征空间中的稀有数据点。
**为什么优先使用启发式?** 启发式规则透明且可调。一条在“60 秒内失败 10 次”触发的暴力破解规则,在报告中一目了然。ML 层增加了对边缘情况的覆盖,而不是替代显式规则。
**作为关键特征的 `inter_arrival_std`:** 诸如 Hydra 之类的自动化工具会以近乎恒定的速率发送尝试。而手动进行暴力破解的人类会表现出极高的到达时间间隔方差。这一单一特征能够可靠地将工具生成的攻击与手动攻击区分开来。
**合成样本对比真实蜜罐数据:** 合成日志精确且非常适合单元测试——你能确切知道异常发生在哪里。但规律性对于 ML 来说恰恰是个问题:仅在脚本生成的“正常”和“攻击”流量上训练的模型,可能会学会识别生成器,而不是识别异常。取而代之的是,使用来自一次性蜜罐的真实攻击者流量(参见[数据来源](#data-sources))来训练和评估 Isolation Forest。
作为一个 Python 作品集项目开发 —— 涵盖了解析、特征工程、ML pipeline、CLI 设计,以及基于真实安全数据的端到端测试。
标签:Apex, CSV导出, Python, SSH, 安全, 安全规则引擎, 异常检测, 无后门, 机器学习, 系统提示词, 红队行动, 聊天机器人, 超时处理, 逆向工具