An open API service indexing awesome lists of open source software.

https://github.com/zavetsec/zavetsec-mailinspector

Phishing & malware triage for .eml and .msg e‑mail files.
https://github.com/zavetsec/zavetsec-mailinspector

Last synced: 18 days ago
JSON representation

Phishing & malware triage for .eml and .msg e‑mail files.

Awesome Lists containing this project

README

          

![ZavetSec MailInspector](assets/banner.svg)

# ZavetSec‑MailInspector

**Разбирает письма `.eml` и `.msg` на фишинг и вредоносные вложения.**
Один файл, почти без зависимостей. На выходе — вердикт, готовый к блокировке список IOC и автономный HTML‑отчёт.

![Python](https://img.shields.io/badge/python-3.8%2B-00ff88?style=flat-square&logo=python&logoColor=0a0d10&labelColor=0d1117)
![License](https://img.shields.io/badge/license-MIT-00ff88?style=flat-square&labelColor=0d1117)
![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-00ff88?style=flat-square&labelColor=0d1117)
![Report](https://img.shields.io/badge/report-offline%20%2F%20zero%20external%20refs-00ff88?style=flat-square&labelColor=0d1117)
![Use](https://img.shields.io/badge/use-defensive%20DFIR%20%2F%20SOC-00ff88?style=flat-square&labelColor=0d1117)

---

## Зачем

В abuse‑ящик валятся пересланные `.eml` и `.msg`, и аналитику L1 нужно быстро понять: письмо безобидное, подозрительное или это уже атака. MailInspector берёт на себя первый проход и отдаёт вердикт, с которым можно сразу работать, и список IOC, который остаётся только закинуть в блокировку.

- **Два формата, один инструмент.** `.eml` (RFC822) и `.msg` (Outlook).
- **Запускается где угодно.** Для `.eml` хватает одной стандартной библиотеки Python.
- **По умолчанию офлайн.** Без флага `--online` с машины не уходит ничего.
- **Отчёт не звонит наружу.** В HTML нет ни одной внешней ссылки — ни CDN, ни шрифтов, ни трекеров. Его спокойно можно открыть на изолированной станции, разбирая содержимое из письма злоумышленника.
- **Встраивается в автоматизацию.** На выходе JSON и осмысленные коды возврата для пайплайнов.

---

## Превью отчёта

![HTML-отчёт MailInspector](assets/report-preview.png)

*Автономный HTML‑отчёт: вердикт, индикаторы с весами, блок IOC и маршрут письма. Открывается без интернета.*

---

## Как это работает

```text
┌─────────────┐
│ .eml / .msg │
└──────┬──────┘

┌──────────┐ stdlib email · extract-msg
│ Parser │ заголовки · тело · вложения
└────┬─────┘

┌──────────────────────┐ AUTH · HEADER · URL
│ Detectors │ BODY · ATTACH · (TI)
└──────────┬───────────┘

┌───────────┐ взвешенные severity
│ Scoring │ → CLEAN / SUSPICIOUS / MALICIOUS
└─────┬─────┘

┌────────────────────────────────┐
│ HTML-отчёт · JSON · список IOC │ + код возврата
└────────────────────────────────┘
```

---

## Что детектируется

| Слой | Проверки |
|------|----------|
| **Аутентификация** | результаты SPF / DKIM / DMARC · цепочка `Received` и originating IP |
| **Спуфинг отправителя** | расхождение From ↔ Return‑Path ↔ Reply‑To · чужой адрес в display‑name · имитация бренда в display‑name · **имитация госоргана** (министерства, комитеты, ведомства РФ/РК) с негосударственного домена · домен Message‑ID не из того же домена |
| **URL** | текст ссылки не ведёт туда, куда href (link spoofing) · ссылка на голый IP · обфускация хоста через `user:pass@` · punycode / IDN homograph · **смешение алфавитов (Latin + Cyrillic/Greek) — homoglyph** · сокращатели ссылок · дешёвые и абузные TLD · бренд в поддомене · схемы `data:` / `javascript:` |
| **Тело** | двуязычный (RU + EN) скоринг приёмов социальной инженерии · tracking‑пиксели · скрытый текст · HTML‑формы прямо в письме |
| **Вложения** | MD5 / SHA‑1 / SHA‑256 · **настоящий тип по magic bytes против заявленного расширения** · опасные и двойные расширения · **детект VBA‑макросов** (auto‑exec / suspicious, через `oletools`) · **контекстная энтропия Shannon** (packed / obfuscated пейлоады) · **архивы под паролем** (ZIP / RAR / 7z) с **сопоставлением пароля из тела письма** |
| **Рекурсивные архивы** | **распаковывает и пересканирует вложенное** (ZIP / TAR / GZIP в памяти; 7z / RAR через опциональные библиотеки) до 3 уровней вглубь · **защита от zip‑bomb** (глубина, число файлов, бюджет размера, compression‑ratio) · каждый вложенный файл проходит весь набор детекторов, а его хэш уходит в IOC |
| **QR-коды (quishing)** | декодирует QR‑коды в **картинках и PDF**‑вложениях (OpenCV / PyMuPDF) и прогоняет извлечённые ссылки через все URL‑детекторы — ловит фишинговые URL, спрятанные в QR от текстовых фильтров |
| **Threat intel** | *по желанию* проверка SHA‑256 по MalwareBazaar и ThreatFox (`--online`) |
| **Вывод** | риск‑скор → вердикт · IOC без дублей (домены / IP / URL / e‑mail / хэши) · маршрут доставки |

### Рекурсивный анализ архивов

Вредонос почти никогда не приходит голым `.exe` — его прячут в архив. MailInspector распаковывает контейнеры в памяти и заново прогоняет все детекторы по каждому вложенному файлу, так что `.exe`, зарытый в zip внутри zip, всё равно вылезет, да ещё и с полным путём:

![Рекурсивная распаковка архивов](assets/report-recursive.png)

Глубина, число файлов, размер каждого файла и суммарный бюджет ограничены, плюс есть контроль compression‑ratio: zip‑bomb не разворачивается, а ловится и отмечается в отчёте. Распаковка в памяти заодно убирает zip‑slip как класс.

### Quishing — фишинг через QR‑коды

Чтобы спрятать ссылку от текстовых фильтров, фишеры всё чаще кладут её в QR‑код картинкой. MailInspector декодирует QR в графических вложениях и в PDF, а вытащенную ссылку прогоняет через те же URL‑детекторы — находки помечаются `[из QR]`:

![Детект quishing](assets/report-quishing.png)

QR со ссылкой на домен, не совпадающий с доменом отправителя, повышается до MEDIUM; легитимные QR (билеты, 2FA на свой домен) остаются низкошумными.

---

## Установка

```bash
git clone https://github.com/zavetsec/ZavetSec-MailInspector.git
cd ZavetSec-MailInspector

# Для .eml зависимости не нужны вообще.
# Для разбора .msg, детекта макросов и онлайн-TI:
pip install -r requirements.txt
```

| Зависимость | Что даёт | Обязательна? |
|-------------|----------|--------------|
| `extract-msg` | разбор Outlook `.msg` | нет |
| `oletools` | анализ VBA‑макросов в Office‑вложениях | нет |
| `requests` | онлайн threat‑intel (`--online`) | нет |
| `py7zr` | рекурсия в 7‑Zip | нет |
| `rarfile` | рекурсия в RAR (и лучший детект шифрования RAR) | нет |
| `opencv-python-headless` | декодирование QR‑кодов (quishing) | нет |
| `pymupdf` | поиск QR‑кодов в PDF‑вложениях | нет |

Если какой‑то библиотеки нет, инструмент не падает — просто сообщает, что именно пропустил.

---

## Быстрый старт

```bash
# Одно письмо → HTML + JSON
python ZavetSec-MailInspector.py suspicious.eml -o report.html -j result.json

# Рекурсивно по всей папке карантина / abuse
python ZavetSec-MailInspector.py ./abuse-inbox/ -o ./reports/

# Письмо Outlook, вытащить вложения для песочницы
python ZavetSec-MailInspector.py message.msg --dump ./attachments/

# Включить проверку репутации по хэшам (хэши вложений уходят в MB/ThreatFox)
python ZavetSec-MailInspector.py invoice.eml --online -o report.html
```

Проверить на примере из репозитория:

```bash
python ZavetSec-MailInspector.py examples/sample_phish.eml -o demo.html
```

---

## Как выглядит вывод

```text
┌──────────────────────────────────────────────────────────────────────
│ ZavetSec-MailInspector v1.3
│ sample_phish.eml [EML]
└──────────────────────────────────────────────────────────────────────
From : СберБанк Безопасность
Subject : Подозрительный вход в ваш аккаунт
Auth : SPF=fail DKIM=fail DMARC=fail
URLs : 4 Attachments: 1

VERDICT: MALICIOUS (score 100/100)

[HIGH] URL: Текст ссылки не совпадает с реальным адресом (link spoofing)
[HIGH] URL: Ссылка ведёт на IP-адрес, а не на домен
[HIGH] ATTACH: Двойное расширение файла (Уведомление_СберБанк.pdf.exe)
[MEDIUM] HEADER: Имя отправителя имитирует бренд «сбербанк»
[MEDIUM] URL: Бренд «сбербанк» в поддомене, но не в основном домене
[MEDIUM] URL: Сокращатель ссылок (реальная цель скрыта)
[MEDIUM] BODY: Триггеры социальной инженерии (13)
...
```

В HTML‑отчёте — все индикаторы, полные таблицы ссылок и вложений, маршрут письма и блок IOC под копипаст. Всё в тёмной терминальной стилистике ZavetSec и целиком автономно (см. [превью](#превью-отчёта) выше).

---

## Опции CLI

| Опция | Что делает |
|-------|------------|
| `target` | файл `.eml` / `.msg` либо каталог для рекурсивного обхода |
| `-o, --html PATH` | сохранить HTML‑отчёт (для каталога — папка с отчётами) |
| `-j, --json PATH` | сохранить результат в JSON |
| `--dump DIR` | вытащить вложения в `DIR` (имена вида `sha256_имя`) |
| `--online` | проверка по MalwareBazaar и ThreatFox (**хэши уходят вовне**) |
| `--no-color` | без ANSI‑цвета в консоли |
| `--quiet` | не печатать каждый индикатор |

### Коды возврата

| Код | Что значит | Куда |
|-----|------------|------|
| `0` | clean | делать нечего |
| `1` | suspicious / likely malicious | аналитику на разбор |
| `2` | malicious | эскалация / авто‑карантин |

Для каталога возвращается код худшего письма в пачке — удобно вешать на hook почтового шлюза или на cron‑разбор abuse‑ящика.

---

## Как считается скор

У каждого индикатора своя severity (`INFO` → `CRITICAL`) и вес. Веса складываются с убывающей отдачей внутри категории — десяток мелких URL сам по себе вердикт не накрутит — и упираются в потолок 100.

| Скор | Вердикт |
|------|---------|
| `0 – 17` | **CLEAN** |
| `18 – 39` | **SUSPICIOUS** |
| `40 – 69` | **LIKELY MALICIOUS** |
| `70 – 100` | **MALICIOUS** |

Пороги и списки ключевых слов, брендов и TLD вынесены в начало скрипта — правьте под своё окружение, логику при этом трогать не нужно.

---

## Встраивание в SOC

**Авто‑разбор abuse‑ящика**: складываем отчёты, JSON для SIEM, а по коду возврата раскидываем письма:

```bash
for f in /var/spool/abuse/*.eml; do
python ZavetSec-MailInspector.py "$f" \
-o "/var/www/reports/$(basename "$f").html" \
-j "/var/log/mailinspect/$(basename "$f").json" --quiet
rc=$?
[ "$rc" -eq 2 ] && mv "$f" /var/spool/abuse/malicious/
done
```

В JSON лежат все индикаторы, IOC, хэши вложений и маршрут письма — заливайте в корреляцию, на блокировку по хэшам или в watchlist.

---

## Дизайн и OPSEC

- **В отчёте нет внешних ссылок.** URL из письма выводятся обычным текстом, а не кликабельными ``/``. Открывать отчёт на изолированном хосте можно спокойно.
- **Сначала офлайн.** Threat‑intel включается руками (`--online`); без него с машины ничего не уходит.
- **Только системные шрифты.** Ничего не подгружается извне — отчёт одинаково выглядит офлайн и остаётся автономным.

---

## Сборка автономного бинаря

Для аналитиков без Python собирается портативный артефакт (скрипты в [`build/`](build/)):

```bash
# Кроссплатформенный однофайловый zipapp (AV не флагает, компактный)
make pyz # или: build/build.sh pyz

# Windows .exe (PyInstaller) — держим внутри, allowlist по SHA-256 в EDR
build\build.ps1
```

> `.exe` удобен на эндпоинтах, но его регулярно ловят эвристики AV/EDR. Поэтому раздавать лучше `.py` (его видно глазами) или `.pyz` (портативный и к AV дружелюбный). Подробности — в [`build/`](build/).

---

## Roadmap

- [ ] валидация цепочки **ARC** (доживают ли `Authentication-Results` между хопами)
- [ ] детект **S/MIME и PGP** — есть ли подпись, валидна ли, совпадает ли signer с отправителем
- [ ] YARA‑сканирование вложений (по файлу правил)
- [ ] экспорт IOC в **STIX 2.1** и сводный dashboard для пакетных прогонов

**Сделано в v1.1:** контекстная энтропия вложений · архивы под паролем с сопоставлением пароля из тела.
**Сделано в v1.2:** рекурсивная распаковка архивов (ZIP / TAR / GZIP / 7z / RAR) с защитой от zip‑bomb и полным пересканированием вложенного.
**Сделано в v1.3:** детект quishing — декодирование QR‑кодов в картинках и PDF с анализом извлечённых ссылок.

---

## Контрибьют

Issues и PR — welcome, особенно новые правила детекта, magic‑сигнатуры, бренды и ключевые слова, репорты ложных срабатываний. Изменения держите самодостаточными и лёгкими по зависимостям: смысл в том, чтобы код оставался читаемым, переносимым и работал офлайн.

---

## Дисклеймер

MailInspector — **оборонительный** инструмент для аналитиков, у которых есть право разбирать обрабатываемые письма. Это статический анализ, и он не заменяет детонацию в песочнице или полноценный реверс. Поставляется как есть, без гарантий — см. [LICENSE](LICENSE).

---

**ZavetSec** · часть DFIR‑тулкита ZavetSec
Распространяется под [лицензией MIT](LICENSE)