montana/Android/Внешний-аудит/02-Угрозы-и-модель.md
2026-05-18 22:11:45 +03:00

167 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 02. Threat model — Montana Android v6.5.0
## Атакующие — классификация
### A. Пассивный сетевой наблюдатель (DPI на ISP)
**Капабилитности:**
- Виден весь трафик клиента до публичного интернета
- Может выполнять traffic analysis (timing, size patterns)
- Не может выполнить активное соединение к клиенту извне (NAT)
**Защита:**
- Reality protocol — handshake выглядит как обычный TLS-1.3 к `www.googletagmanager.com`. SNI Echo маскирует destination.
- Pinned fingerprint Chrome 120+. JA3/JA4 хэши совпадают с реальным Chrome.
**Открыто:**
- Timing-based traffic analysis (всплески запросов соответствуют WebRTC, видео, и т.п.)
- Если DPI имеет ML-классификатор Reality (известно научное исследование GFW 2024) — обнаружение возможно
### B. Активный сетевой наблюдатель (active probing)
**Капабилитности:**
- Может выполнять TCP-зондирование `91.132.142.42:443` (Helsinki публичный IP)
- Может сравнивать ответы с эталонными `www.googletagmanager.com:443`
**Защита:**
- Reality terminate на правильный destination через **SNI Echo** — если клиент шлёт неправильный сертификат, xray прозрачно проксирует к real `googletagmanager.com:443`.
- На случай proxy-fallback: nginx `:80` decoy → отдаёт `"It works!"` HTML.
**Открыто:**
- Атакующий с full state inspection (видит timing handshake и сравнивает с эталонным DNS+TLS к googletagmanager) может различить.
### C. Malicious Android app на том же устройстве
**Капабилитности:**
- Своё data dir (изолировано Android sandbox)
- Возможно `MANAGE_EXTERNAL_STORAGE` (Android 11+) — доступ к `/sdcard/`, не к нашим private data
- На rooted устройстве — полный доступ к `/data/data/quest.montana.vpn/`
**Защита (если не root):**
- Android sandbox 0700 на data dir
- localStorage WebView хранится в `/data/data/quest.montana.vpn/app_webview/Default/Local Storage/` — недоступен другим приложениям
**Открыто (если root):**
- Seed 24 слов читается прямо из localStorage — **plain text**, не шифрован
- Atomic recovery — атакующий получает все деньги, владельцу остаётся ничего
**Severity:** **средний** (зависит от того, root ли у пользователя; на стоковом Android защищено sandbox).
### D. Forensic / физический доступ к устройству
**Капабилитности:**
- Полная image копия `/data/data/quest.montana.vpn/`
- Анализ offline
**Защита сейчас:**
- Никакой кроме Android FBE (File-Based Encryption) которое работает только при выключенном устройстве и неизвестном пароле user.
**Открыто:**
- На разблокированном устройстве или с известным паролем — seed читается тривиально.
**Severity:** **высокий** для пользователей хранящих значительный баланс. Closure: шифрование seed через user passcode + PBKDF2 (см. `07` F-6).
### E. Атака на VPN-сеть Montana через публичный endpoint
**Капабилитности:**
- Может поднять Montana VPN клиент (открытый VLESS URL)
- Может слать heartbeat-ы с любого 40-hex адреса
**Защита сейчас:**
- Только проверка `request.remote_addr ∈ MONTANA_NODES` (helsinki/frankfurt/newyork). Атакующий должен сначала подключиться через VPN — это сделает любой.
- Никакой подписи heartbeat **нет**.
**Открыто (блокер):**
- Атакующий с одним VPN-подключением шлёт 10⁶ heartbeat от 10⁶ fake-адресов → 10³ Ɉ/сек на fake-баланс
- Экономика начисления рушится
**Severity:** **блокер mainnet**. Closure: подпись Falcon-512 (см. `07` F-2, требует TimeChain integration M-VPN-2/3).
### F. Compromise CI/build pipeline
**Капабилитности:**
- Подмена `bip39-en.txt` в APK при сборке
- Подмена UUID/Reality keys в Kotlin
**Защита сейчас:**
- BIP39 wordlist: **hardcoded SHA-256** в `MainActivity.kt` — если подменили, `bip39()` возвращает пустую строку, app не работает
- APK signature: Genesis-keystore, fingerprint известен и публичен
- Reproducible builds — частично (см. `08-Воспроизводимая-сборка.md`)
**Открыто:**
- Reality keys и UUID **захардкожены** в коде, не имеют integrity check — атакующий может подменить в скомпрометированной сборке без обнаружения
- Closure: `[C-1]` SSOT — keys должны загружаться из одного authoritative источника с подписью (см. `07` CF-4).
### G. Mass surveillance government adversary
**Капабилитности:**
- Может координировать DPI с ML-классификатором
- Может выпустить subpoena/court order на hosting provider узла Helsinki (Финляндия — нейтральная юрисдикция, но не безопасна абсолютно)
- Может физически захватить узел (закон или операция)
**Защита:**
- Юрисдикция Finland — нейтральная, без mass surveillance законов аналогичных Five Eyes
- Каскад через два exit-узла (Frankfurt DE / NewYork US) — добавляет дополнительный hop
- Reality маскировка — повышает порог obfuscation
**Открыто:**
- Frankfurt (Germany) и NewYork (USA) — оба под юрисдикциями с MLAT-соглашениями
- Если атакующий контролирует Helsinki + один из exit — может deanonymize пользователя
- Compromise двух узлов из трёх → каскад теряет силу
**Severity:** государственный actor — out of MVP scope. Дополнительные меры (Tor onion routing, additional jurisdictions) — future work.
### H. Sybil-атаки
**Капабилитности:**
- Создание миллиона BIP39-кошельков (бесплатно)
- Отправка heartbeat с каждого через VPN
**Защита:**
- См. атакующий **E** выше. Сейчас не защищено никак.
**Severity:** **блокер mainnet**. Closure: TimeChain validator state + Falcon signature per heartbeat (M-VPN-2/3).
---
## Что приложение защищает
| Свойство | Защищено? | Механизм | Ограничения |
|----------|-----------|----------|--------------|
| Identity (seed) от других apps | **да** (если не root) | Android sandbox 0700 | Не защищено от root, forensic |
| Identity от network adversary | **да** | Seed никогда не покидает устройство | n/a |
| Identity от подмены в APK | **частично** | BIP39 wordlist SHA-256 check | Reality keys не verified |
| Traffic content от пассивного DPI | **да** | Reality TLS-1.3 inside | Timing analysis возможен |
| Traffic content от active probing | **да** | SNI Echo decoy | Full state inspection — открыто |
| Целостность баланса | **нет** | n/a | Sybil-атака открыта (E,H блокеры) |
| Authentication heartbeat | **нет** | n/a | Любой может слать heartbeat (E блокер) |
| Persistence баланса при отказе сервера | **нет** | Single Moscow file | TimeChain integration отложена |
---
## Предположения (assumptions)
1. **Android FBE работает корректно** — данные приложения зашифрованы при выключенном устройстве.
2. **WebView SubtleCrypto детерминирован**`crypto.subtle.digest('SHA-256', ...)` и `deriveBits('PBKDF2', ...)` дают идентичный результат на разных Chromium-версиях Android. (См. `06-Восстановление.md` — для верификации требуются tests on multiple Android versions.)
3. **xray-core реализует Reality корректно** — внешний аудит xray не входит в наш scope. Версия v26.2.6 актуальна на 2026-05.
4. **haproxy stick-table персистентна 24h** — verified empirically (см. `04-Сетевой-слой.md`).
5. **Genesis keystore хранится у автора в безопасном месте** — компрометация = возможность подписать malicious APK.
---
## Запреты в коде (что архитектурно невозможно)
1. **Heartbeat не идёт мимо VPN**`MontanaVpnService.sendHeartbeat()` всегда через `socksConnect(127.0.0.1:10808)` (SOCKS5 локального xray).
2. **App не использует свой VPN для своего трафика**`addDisallowedApplication(packageName)` исключает quest.montana.vpn из своего же TUN.
3. **Версия не дублируется**`versionCode` и `versionName` только в `build.gradle.kts`, нигде в коде явно.
4. **xray access logs отключены**`"access": "none"` в конфиге → logcat не спамит.
---
## Outside scope этого аудита
- Уязвимости в Android OS (CVE на WebView, kernel etc.) — обязанность пользователя обновляться
- Уязвимости в Linux kernel exit-нод — обязанность hosting provider
- DDoS на публичный Helsinki:443 — на уровне hosting provider (THE.Hosting) + cloudflare если включено
- Юридический аудит соответствия GDPR / законам о связи — отдельная экспертиза