{"id":51771824,"url":"https://github.com/zavetsec/zavetsec-mailinspector","last_synced_at":"2026-07-20T02:02:02.520Z","repository":{"id":364939392,"uuid":"1267291155","full_name":"zavetsec/ZavetSec-MailInspector","owner":"zavetsec","description":"Phishing \u0026 malware triage for .eml and .msg e‑mail files.","archived":false,"fork":false,"pushed_at":"2026-06-15T06:08:15.000Z","size":639,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-15T08:08:43.859Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zavetsec.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-12T12:01:43.000Z","updated_at":"2026-06-15T06:08:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/zavetsec/ZavetSec-MailInspector","commit_stats":null,"previous_names":["zavetsec/zavetsec-mailinspector"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/zavetsec/ZavetSec-MailInspector","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zavetsec%2FZavetSec-MailInspector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zavetsec%2FZavetSec-MailInspector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zavetsec%2FZavetSec-MailInspector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zavetsec%2FZavetSec-MailInspector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zavetsec","download_url":"https://codeload.github.com/zavetsec/ZavetSec-MailInspector/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zavetsec%2FZavetSec-MailInspector/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35670233,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-20T02:00:06.612Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-20T02:02:01.380Z","updated_at":"2026-07-20T02:02:02.514Z","avatar_url":"https://github.com/zavetsec.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n![ZavetSec MailInspector](assets/banner.svg)\n\n# ZavetSec‑MailInspector\n\n**Разбирает письма `.eml` и `.msg` на фишинг и вредоносные вложения.**\nОдин файл, почти без зависимостей. На выходе — вердикт, готовый к блокировке список IOC и автономный HTML‑отчёт.\n\n![Python](https://img.shields.io/badge/python-3.8%2B-00ff88?style=flat-square\u0026logo=python\u0026logoColor=0a0d10\u0026labelColor=0d1117)\n![License](https://img.shields.io/badge/license-MIT-00ff88?style=flat-square\u0026labelColor=0d1117)\n![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-00ff88?style=flat-square\u0026labelColor=0d1117)\n![Report](https://img.shields.io/badge/report-offline%20%2F%20zero%20external%20refs-00ff88?style=flat-square\u0026labelColor=0d1117)\n![Use](https://img.shields.io/badge/use-defensive%20DFIR%20%2F%20SOC-00ff88?style=flat-square\u0026labelColor=0d1117)\n\n\u003c/div\u003e\n\n---\n\n## Зачем\n\nВ abuse‑ящик валятся пересланные `.eml` и `.msg`, и аналитику L1 нужно быстро понять: письмо безобидное, подозрительное или это уже атака. MailInspector берёт на себя первый проход и отдаёт вердикт, с которым можно сразу работать, и список IOC, который остаётся только закинуть в блокировку.\n\n- **Два формата, один инструмент.** `.eml` (RFC822) и `.msg` (Outlook).\n- **Запускается где угодно.** Для `.eml` хватает одной стандартной библиотеки Python.\n- **По умолчанию офлайн.** Без флага `--online` с машины не уходит ничего.\n- **Отчёт не звонит наружу.** В HTML нет ни одной внешней ссылки — ни CDN, ни шрифтов, ни трекеров. Его спокойно можно открыть на изолированной станции, разбирая содержимое из письма злоумышленника.\n- **Встраивается в автоматизацию.** На выходе JSON и осмысленные коды возврата для пайплайнов.\n\n---\n\n## Превью отчёта\n\n\u003cdiv align=\"center\"\u003e\n\n![HTML-отчёт MailInspector](assets/report-preview.png)\n\n*Автономный HTML‑отчёт: вердикт, индикаторы с весами, блок IOC и маршрут письма. Открывается без интернета.*\n\n\u003c/div\u003e\n\n---\n\n## Как это работает\n\n```text\n        ┌─────────────┐\n        │ .eml / .msg │\n        └──────┬──────┘\n               ▼\n         ┌──────────┐     stdlib email  ·  extract-msg\n         │  Parser  │     заголовки · тело · вложения\n         └────┬─────┘\n              ▼\n   ┌──────────────────────┐   AUTH · HEADER · URL\n   │      Detectors       │   BODY · ATTACH · (TI)\n   └──────────┬───────────┘\n              ▼\n        ┌───────────┐    взвешенные severity\n        │  Scoring  │    → CLEAN / SUSPICIOUS / MALICIOUS\n        └─────┬─────┘\n              ▼\n   ┌────────────────────────────────┐\n   │ HTML-отчёт · JSON · список IOC │  + код возврата\n   └────────────────────────────────┘\n```\n\n---\n\n## Что детектируется\n\n| Слой | Проверки |\n|------|----------|\n| **Аутентификация** | результаты SPF / DKIM / DMARC · цепочка `Received` и originating IP |\n| **Спуфинг отправителя** | расхождение From ↔ Return‑Path ↔ Reply‑To · чужой адрес в display‑name · имитация бренда в display‑name · **имитация госоргана** (министерства, комитеты, ведомства РФ/РК) с негосударственного домена · домен Message‑ID не из того же домена |\n| **URL** | текст ссылки не ведёт туда, куда href (link spoofing) · ссылка на голый IP · обфускация хоста через `user:pass@` · punycode / IDN homograph · **смешение алфавитов (Latin + Cyrillic/Greek) — homoglyph** · сокращатели ссылок · дешёвые и абузные TLD · бренд в поддомене · схемы `data:` / `javascript:` |\n| **Тело** | двуязычный (RU + EN) скоринг приёмов социальной инженерии · tracking‑пиксели · скрытый текст · HTML‑формы прямо в письме |\n| **Вложения** | MD5 / SHA‑1 / SHA‑256 · **настоящий тип по magic bytes против заявленного расширения** · опасные и двойные расширения · **детект VBA‑макросов** (auto‑exec / suspicious, через `oletools`) · **контекстная энтропия Shannon** (packed / obfuscated пейлоады) · **архивы под паролем** (ZIP / RAR / 7z) с **сопоставлением пароля из тела письма** |\n| **Рекурсивные архивы** | **распаковывает и пересканирует вложенное** (ZIP / TAR / GZIP в памяти; 7z / RAR через опциональные библиотеки) до 3 уровней вглубь · **защита от zip‑bomb** (глубина, число файлов, бюджет размера, compression‑ratio) · каждый вложенный файл проходит весь набор детекторов, а его хэш уходит в IOC |\n| **QR-коды (quishing)** | декодирует QR‑коды в **картинках и PDF**‑вложениях (OpenCV / PyMuPDF) и прогоняет извлечённые ссылки через все URL‑детекторы — ловит фишинговые URL, спрятанные в QR от текстовых фильтров |\n| **Threat intel** | *по желанию* проверка SHA‑256 по MalwareBazaar и ThreatFox (`--online`) |\n| **Вывод** | риск‑скор → вердикт · IOC без дублей (домены / IP / URL / e‑mail / хэши) · маршрут доставки |\n\n### Рекурсивный анализ архивов\n\nВредонос почти никогда не приходит голым `.exe` — его прячут в архив. MailInspector распаковывает контейнеры в памяти и заново прогоняет все детекторы по каждому вложенному файлу, так что `.exe`, зарытый в zip внутри zip, всё равно вылезет, да ещё и с полным путём:\n\n\u003cdiv align=\"center\"\u003e\n\n![Рекурсивная распаковка архивов](assets/report-recursive.png)\n\n\u003c/div\u003e\n\nГлубина, число файлов, размер каждого файла и суммарный бюджет ограничены, плюс есть контроль compression‑ratio: zip‑bomb не разворачивается, а ловится и отмечается в отчёте. Распаковка в памяти заодно убирает zip‑slip как класс.\n\n### Quishing — фишинг через QR‑коды\n\nЧтобы спрятать ссылку от текстовых фильтров, фишеры всё чаще кладут её в QR‑код картинкой. MailInspector декодирует QR в графических вложениях и в PDF, а вытащенную ссылку прогоняет через те же URL‑детекторы — находки помечаются `[из QR]`:\n\n\u003cdiv align=\"center\"\u003e\n\n![Детект quishing](assets/report-quishing.png)\n\n\u003c/div\u003e\n\nQR со ссылкой на домен, не совпадающий с доменом отправителя, повышается до MEDIUM; легитимные QR (билеты, 2FA на свой домен) остаются низкошумными.\n\n---\n\n## Установка\n\n```bash\ngit clone https://github.com/zavetsec/ZavetSec-MailInspector.git\ncd ZavetSec-MailInspector\n\n# Для .eml зависимости не нужны вообще.\n# Для разбора .msg, детекта макросов и онлайн-TI:\npip install -r requirements.txt\n```\n\n| Зависимость | Что даёт | Обязательна? |\n|-------------|----------|--------------|\n| `extract-msg` | разбор Outlook `.msg` | нет |\n| `oletools` | анализ VBA‑макросов в Office‑вложениях | нет |\n| `requests` | онлайн threat‑intel (`--online`) | нет |\n| `py7zr` | рекурсия в 7‑Zip | нет |\n| `rarfile` | рекурсия в RAR (и лучший детект шифрования RAR) | нет |\n| `opencv-python-headless` | декодирование QR‑кодов (quishing) | нет |\n| `pymupdf` | поиск QR‑кодов в PDF‑вложениях | нет |\n\nЕсли какой‑то библиотеки нет, инструмент не падает — просто сообщает, что именно пропустил.\n\n---\n\n## Быстрый старт\n\n```bash\n# Одно письмо → HTML + JSON\npython ZavetSec-MailInspector.py suspicious.eml -o report.html -j result.json\n\n# Рекурсивно по всей папке карантина / abuse\npython ZavetSec-MailInspector.py ./abuse-inbox/ -o ./reports/\n\n# Письмо Outlook, вытащить вложения для песочницы\npython ZavetSec-MailInspector.py message.msg --dump ./attachments/\n\n# Включить проверку репутации по хэшам (хэши вложений уходят в MB/ThreatFox)\npython ZavetSec-MailInspector.py invoice.eml --online -o report.html\n```\n\nПроверить на примере из репозитория:\n\n```bash\npython ZavetSec-MailInspector.py examples/sample_phish.eml -o demo.html\n```\n\n---\n\n## Как выглядит вывод\n\n```text\n┌──────────────────────────────────────────────────────────────────────\n│ ZavetSec-MailInspector  v1.3\n│ sample_phish.eml  [EML]\n└──────────────────────────────────────────────────────────────────────\n  From      : СберБанк Безопасность  \u003cnoreply@online-secure-portal.top\u003e\n  Subject   : Подозрительный вход в ваш аккаунт\n  Auth      : SPF=fail  DKIM=fail  DMARC=fail\n  URLs      : 4   Attachments: 1\n\n  VERDICT: MALICIOUS  (score 100/100)\n\n  [HIGH]    URL:    Текст ссылки не совпадает с реальным адресом (link spoofing)\n  [HIGH]    URL:    Ссылка ведёт на IP-адрес, а не на домен\n  [HIGH]    ATTACH: Двойное расширение файла  (Уведомление_СберБанк.pdf.exe)\n  [MEDIUM]  HEADER: Имя отправителя имитирует бренд «сбербанк»\n  [MEDIUM]  URL:    Бренд «сбербанк» в поддомене, но не в основном домене\n  [MEDIUM]  URL:    Сокращатель ссылок (реальная цель скрыта)\n  [MEDIUM]  BODY:   Триггеры социальной инженерии (13)\n  ...\n```\n\nВ HTML‑отчёте — все индикаторы, полные таблицы ссылок и вложений, маршрут письма и блок IOC под копипаст. Всё в тёмной терминальной стилистике ZavetSec и целиком автономно (см. [превью](#превью-отчёта) выше).\n\n---\n\n## Опции CLI\n\n| Опция | Что делает |\n|-------|------------|\n| `target` | файл `.eml` / `.msg` либо каталог для рекурсивного обхода |\n| `-o, --html PATH` | сохранить HTML‑отчёт (для каталога — папка с отчётами) |\n| `-j, --json PATH` | сохранить результат в JSON |\n| `--dump DIR` | вытащить вложения в `DIR` (имена вида `sha256_имя`) |\n| `--online` | проверка по MalwareBazaar и ThreatFox (**хэши уходят вовне**) |\n| `--no-color` | без ANSI‑цвета в консоли |\n| `--quiet` | не печатать каждый индикатор |\n\n### Коды возврата\n\n| Код | Что значит | Куда |\n|-----|------------|------|\n| `0` | clean | делать нечего |\n| `1` | suspicious / likely malicious | аналитику на разбор |\n| `2` | malicious | эскалация / авто‑карантин |\n\nДля каталога возвращается код худшего письма в пачке — удобно вешать на hook почтового шлюза или на cron‑разбор abuse‑ящика.\n\n---\n\n## Как считается скор\n\nУ каждого индикатора своя severity (`INFO` → `CRITICAL`) и вес. Веса складываются с убывающей отдачей внутри категории — десяток мелких URL сам по себе вердикт не накрутит — и упираются в потолок 100.\n\n| Скор | Вердикт |\n|------|---------|\n| `0 – 17` | **CLEAN** |\n| `18 – 39` | **SUSPICIOUS** |\n| `40 – 69` | **LIKELY MALICIOUS** |\n| `70 – 100` | **MALICIOUS** |\n\nПороги и списки ключевых слов, брендов и TLD вынесены в начало скрипта — правьте под своё окружение, логику при этом трогать не нужно.\n\n---\n\n## Встраивание в SOC\n\n**Авто‑разбор abuse‑ящика**: складываем отчёты, JSON для SIEM, а по коду возврата раскидываем письма:\n\n```bash\nfor f in /var/spool/abuse/*.eml; do\n  python ZavetSec-MailInspector.py \"$f\" \\\n    -o \"/var/www/reports/$(basename \"$f\").html\" \\\n    -j \"/var/log/mailinspect/$(basename \"$f\").json\" --quiet\n  rc=$?\n  [ \"$rc\" -eq 2 ] \u0026\u0026 mv \"$f\" /var/spool/abuse/malicious/\ndone\n```\n\nВ JSON лежат все индикаторы, IOC, хэши вложений и маршрут письма — заливайте в корреляцию, на блокировку по хэшам или в watchlist.\n\n---\n\n## Дизайн и OPSEC\n\n- **В отчёте нет внешних ссылок.** URL из письма выводятся обычным текстом, а не кликабельными `\u003ca href\u003e`/`\u003cimg src\u003e`. Открывать отчёт на изолированном хосте можно спокойно.\n- **Сначала офлайн.** Threat‑intel включается руками (`--online`); без него с машины ничего не уходит.\n- **Только системные шрифты.** Ничего не подгружается извне — отчёт одинаково выглядит офлайн и остаётся автономным.\n\n---\n\n## Сборка автономного бинаря\n\nДля аналитиков без Python собирается портативный артефакт (скрипты в [`build/`](build/)):\n\n```bash\n# Кроссплатформенный однофайловый zipapp (AV не флагает, компактный)\nmake pyz        # или: build/build.sh pyz\n\n# Windows .exe (PyInstaller) — держим внутри, allowlist по SHA-256 в EDR\nbuild\\build.ps1\n```\n\n\u003e `.exe` удобен на эндпоинтах, но его регулярно ловят эвристики AV/EDR. Поэтому раздавать лучше `.py` (его видно глазами) или `.pyz` (портативный и к AV дружелюбный). Подробности — в [`build/`](build/).\n\n---\n\n## Roadmap\n\n- [ ] валидация цепочки **ARC** (доживают ли `Authentication-Results` между хопами)\n- [ ] детект **S/MIME и PGP** — есть ли подпись, валидна ли, совпадает ли signer с отправителем\n- [ ] YARA‑сканирование вложений (по файлу правил)\n- [ ] экспорт IOC в **STIX 2.1** и сводный dashboard для пакетных прогонов\n\n**Сделано в v1.1:** контекстная энтропия вложений · архивы под паролем с сопоставлением пароля из тела.\n**Сделано в v1.2:** рекурсивная распаковка архивов (ZIP / TAR / GZIP / 7z / RAR) с защитой от zip‑bomb и полным пересканированием вложенного.\n**Сделано в v1.3:** детект quishing — декодирование QR‑кодов в картинках и PDF с анализом извлечённых ссылок.\n\n---\n\n## Контрибьют\n\nIssues и PR — welcome, особенно новые правила детекта, magic‑сигнатуры, бренды и ключевые слова, репорты ложных срабатываний. Изменения держите самодостаточными и лёгкими по зависимостям: смысл в том, чтобы код оставался читаемым, переносимым и работал офлайн.\n\n---\n\n## Дисклеймер\n\nMailInspector — **оборонительный** инструмент для аналитиков, у которых есть право разбирать обрабатываемые письма. Это статический анализ, и он не заменяет детонацию в песочнице или полноценный реверс. Поставляется как есть, без гарантий — см. [LICENSE](LICENSE).\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\n**ZavetSec** · часть DFIR‑тулкита ZavetSec\nРаспространяется под [лицензией MIT](LICENSE)\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzavetsec%2Fzavetsec-mailinspector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzavetsec%2Fzavetsec-mailinspector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzavetsec%2Fzavetsec-mailinspector/lists"}