Alpha-Beta-810/MailGlass_v3.1
GitHub: Alpha-Beta-810/MailGlass-v3.1
MailGlass 是一个混合式网络钓鱼邮件检测平台,结合黑名单查询、威胁情报、域名分析与机器学习分类器,提供可解释的风险评分及持久化扫描历史。
Stars: 0 | Forks: 0
# 🔍MailGlass_v3.1:混合式网络钓鱼邮件检测系统
MailGlass 是一个混合式网络钓鱼邮件检测器,它结合了**基于黑名单的检查**
(白名单、PhishTank、VirusTotal) 与一个 **ML 回退分类器**,
加上支持性的域名情报(WHOIS 域名年龄、IDN/同形异义字以及
域名抢注/仿冒检测)以及一个加权的、可解释的风险评分。可通过
命令行或 Flask Web 仪表板使用。
## 🚀 版本 3.1 的新特性
版本 **3.1** 在现有的混合式钓鱼检测平台基础上,引入了使用 SQLite 的**持久化扫描历史**。扫描结果现在可以在应用程序重启后保留,允许用户回顾之前的分析、导出历史报告,并直接从 Web 界面管理扫描历史。
| 功能 | 版本 3.0 | 版本 3.1 |
|:--------|:-----------:|:-----------:|
| Flask 仪表板 | ✅ | ✅ |
| 机器学习检测 | ✅ | ✅ |
| Typosquatting 检测 | ✅ | ✅ |
| 邮件头分析 | ✅ | ✅ |
| WHOIS / 域名情报 | ✅ | ✅ |
| 可解释风险引擎 | ✅ | ✅ |
| CSV 导出 | ✅ | ✅ |
| JSON 导出 | ✅ | ✅ |
| **持久化 SQLite 扫描历史** | ❌ | ✅ |
| **历史记录仪表板** | ❌ | ✅ |
| **服务器重启后的仪表板重建** | ❌ | ✅ |
| **导出以前的扫描结果** | ❌ | ✅ |
| **清除扫描历史** | ❌ | ✅ |
### ✨ v3.1 的新功能
- 🗄️ **持久化 SQLite 历史记录**
- 每次扫描都会自动存储在本地 SQLite 数据库(`scan_history.db`)中。
- 即使在关闭或重启应用程序后,扫描结果依然可用。
- 📜 **历史记录仪表板**
- 查看所有以前扫描过的邮件。
- 过滤并重新查看历史扫描结果。
- 🔄 **仪表板重建**
- 应用程序重启后,可以直接从数据库重建以前生成的仪表板。
- 📥 **历史报告导出**
- 无需重新扫描邮件,即可将任何以前的扫描导出为 **CSV** 或 **JSON**。
- 🧹 **清除历史记录**
- 只需单击一下,即可从应用程序中删除所有已存储的扫描历史。
## 架构
```
Read .eml
|
Parse HTML + Text
|
Extract href URLs + Plain URLs
|
Validate URLs
|
Whitelist
|
PhishTank
|
VirusTotal
|
Machine Learning (only if blacklist stage was inconclusive)
|
Risk Score
|
Final Verdict: SAFE / SUSPICIOUS / MALICIOUS
```
## 项目布局
| 文件 | 用途 |
|---|---|
| `phishing_detector.py` | **主入口。** CLI、编排、单封邮件报告。 |
| `config.py` | 分层设置:默认值 -> `config.json` -> 环境变量 -> CLI 标志。 |
| `email_utils.py` | `.eml` 解析:主题、发件人、正文、附件。 |
| `url_utils.py` | URL 提取(基于 href,而非锚文本)、验证、重定向解析。 |
| `whitelist_utils.py` | 域名标准化 + 基于根域名的白名单匹配。 |
| `threat_intel.py` | PhishTank + VirusTotal API 调用,带有单次运行缓存。 |
| `domain_intel.py` | WHOIS 域名年龄查询 + IDN/punycode 同形异义字检测。 |
| `typosquat_detection.py` | 仿冒品牌域名检测(字符替换、 combosquatting 、后缀交换)。 |
| `risk_engine.py` | 加权风险评分和 SAFE/SUSPICIOUS/MALICIOUS 分类。 |
| `ml_analysis.py` | ML 回退模型 + 对其推理过程的人类可读解释。 |
| `results_export.py` | 导出单封邮件结果的 CSV/JSON。 |
| `history_store.py` | 持久化 SQLite 扫描历史(在重启后保留),支持 Web 仪表板的历史记录页面。 |
| `app.py` | Flask Web 仪表板:上传 `.eml` 文件,在浏览器中浏览结果。 |
| `templates/`, `static/` | Web 仪表板的 HTML/CSS。 |
| `model_classes.py` | 训练好的 pipeline 使用的自定义 sklearn transformer。 |
| `ml_integration_fixed.py` | 从 `CEAS_08.csv` 训练 `phishing_email_model_fixed.pkl`。 |
| `model_evaluation.py` | 针对训练好模型的交叉验证、ROC 曲线、混淆矩阵。 |
| `whitelist.json` | 受信任的域名/URL 配置。 |
| `tests/` | 涵盖 URL/白名单/风险/域名情报逻辑的 Pytest 测试套件。 |
有关修复/添加的内容及其原因的详细历史记录,请参见 `CHANGES.md`。
## 设置
```
pip install -r requirements.txt # runtime
# 或者,同时运行 test suite:
pip install -r requirements-dev.txt
```
如果在加载内置模型时遇到 scikit-learn 版本不匹配的问题(请参阅
下方的**已知注意事项**),请锁定 `scikit-learn==1.6.1`,或者在您当前的 scikit-learn 版本下重新训练模型(请参阅**训练**)。
## Web 仪表板
```
python app.py
```
然后打开 `http://127.0.0.1:5000`。上传一个或多个 `.eml` 文件(
`emails/` 中的两个文件可用作演示),可选择勾选“解析跟踪链接
重定向” / “检查域名年龄”,您将获得:
- 一个仪表板,显示总扫描数 + SAFE/SUSPICIOUS/MALICIOUS 计数 +
平均 ML 置信度
- 一份单封邮件报告:风险评分仪表、可解释的逐个因素
分解、每个提取的 URL 旁边附有其*可见的锚文本*(以便您
能看到 href 与锚文本修复的实际效果)、附件扫描结果、
ML 回退的推理过程,以及任何 typosquat/同形异义字/域名年龄
发现
- 导出当前扫描的 CSV/JSON
每次单独的扫描也会写入一个小型 SQLite 数据库
(`scan_history.db`,自动在 `app.py` 旁边创建)。顶部导航栏中的 **历史记录**
链接列出了曾经扫描过的每一封邮件——跨越不同的
扫描批次,甚至在重启服务器后也是如此——并带有各自的
CSV/JSON 导出和“清除历史记录”操作。这就是使
`/dashboard/` 和 `/email//` 链接在重启后依然能继续工作
的原因:如果内存中的副本丢失,它们会回退到数据库。详情请参见 `history_store.py`。
这是一个本地单进程工具(无用户账户,无身份验证)——适合
于演示和评分,不适合作为共享的面向互联网的服务进行部署。
## 运行检测 (CLI)
```
mkdir -p emails # drop your .eml files here
python phishing_detector.py
```
`emails/` 中提供了两个示例 `.eml` 文件,演示了最初的
href 与锚文本 bug 修复以及 `mckinsey-login.com` 仿冒域名。
### CLI 标志
```
python phishing_detector.py --help
```
| 标志 | 效果 |
|---|---|
| `--emails-dir DIR` | `.eml` 文件的目录(默认:`emails`) |
| `--whitelist-file PATH` | 白名单 JSON 的路径(默认:`whitelist.json`) |
| `--model-path PATH` | 训练好的 `.pkl` 模型的路径 |
| `--resolve-redirects` | 在检查信誉之前,跟随跟踪链接重定向到达其最终目的地 |
| `--check-domain-age` | WHOIS 查询链接/发件人域名,并标记注册时间在 30 天内的域名(速度较慢,需要网络 + `python-whois`) |
| `--output-csv PATH` | 将结果摘要写入 CSV |
| `--output-json PATH` | 将结果摘要写入 JSON |
| `--config PATH` | JSON 配置文件的路径(默认:`config.json`) |
| `--log-level LEVEL` | `DEBUG` / `INFO` / `WARNING` / `ERROR` |
### 配置优先级
`config.py` 按以下顺序解析设置(后者优先):
**内置默认值 → `config.json`(如果存在)→ 环境变量 →
CLI 标志。** 复制 `config.example.json` 到 `config.json` 以进行自定义,
无需改动环境变量或标志:
```
cp config.example.json config.json
```
相关的环境变量:`PHISHTANK_API_KEY`, `VIRUSTOTAL_API_KEY`,
`EMAILS_DIR`, `WHITELIST_FILE`, `MODEL_PATH`, `RESOLVE_REDIRECTS`,
`CHECK_DOMAIN_AGE`, `OUTPUT_CSV`, `OUTPUT_JSON`, `LOG_LEVEL`。
### 示例:包含导出和域名年龄检查的完整运行
```
export VIRUSTOTAL_API_KEY=your_key_here
python phishing_detector.py --check-domain-age --resolve-redirects \
--output-csv results.csv --output-json results.json
```
## 运行测试
```
pip install -r requirements-dev.txt
pytest tests/ -v
```
该套件涵盖:href 与锚文本提取的修复、URL 验证
边缘情况、根域名白名单匹配(包括
`mckinsey-login.com` 仿冒案例)、跨所有
信号的加权风险评分、IDN/punycode 同形异义字检测,以及 typosquat/combosquat/
后缀交换品牌冒充检测。
## 训练 ML 模型
训练器需要在项目根目录下存在 `CEAS_08.csv`(此处未包含 - 大小约 65MB;请从您原始的数据集导出中获取)。
```
python ml_integration_fixed.py
```
这将训练一个 Random Forest pipeline(发件人模式特征 + 针对主题/正文的 TF-IDF + URL 计数),并写入 `phishing_email_model_fixed.pkl`。
请在与您运行 `phishing_detector.py` 相同的 scikit-learn 版本下进行训练,以避免下面提到的 pickle 兼容性问题。
要评估训练好的模型(混淆矩阵、ROC 曲线、交叉验证):
```
python model_evaluation.py
```
## 已知注意事项:scikit-learn 版本不匹配
内置的 `.pkl` 是使用 scikit-learn 1.6.1 训练的。在明显
更新的 scikit-learn 上,某些内部类(例如 `_RemainderColsList`)可能
无法被 unpickle。这是一个环境/版本问题,而不是检测
逻辑中的 bug - 系统已经实现了优雅降级,回退到
轻量级的发件人/主题启发式方法,而不是崩溃或静默地
报告 SAFE(请参阅 `risk_engine.py` 的 `ml_unavailable_heuristics` 路径)。
通过锁定 `scikit-learn==1.6.1` 或按上述方法重新训练来解决。
## 扩展
- **受信任的域名**:将根域名添加到 `whitelist.json` 中的 `domainsInSubdomains` 中。
- **Typosquat 品牌列表**:精选的候选列表位于 `typosquat_detection.CURATED_BRANDS` 中;通过 `whitelist.json` 中的 `"typosquatBrands"` 数组添加要监视的特定项目品牌,而不是直接修改代码。
- **风险权重**:所有分值都是位于 `risk_engine.py` 顶部的命名常量。
- **新信号**:向 `results_export.EmailResult` 添加一个字段,在 `phishing_detector.analyze_email()` 中计算它,并将其传递给 `risk_engine.score_email()`。
标签:Apex, SQLite, 威胁情报, 开发者工具, 机器学习, 逆向工具, 邮件安全, 钓鱼检测