montana/Android/Внешний-аудит/02-Угрозы-и-модель.md

167 lines
11 KiB
Markdown
Raw Normal View History

2026-05-18 22:11:45 +03:00
# 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 / законам о связи — отдельная экспертиза