montana/Русский/Логистика/report_seafare_2026-02-28.md

260 lines
10 KiB
Markdown
Raw Permalink 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.

# ОТЧЁТ О БЕЗОПАСНОСТИ
## SeaFare Montana (seafare-montana.duckdns.org) — 28.02.2026
---
## Executive Summary
- **Находок: 8** (Критические: 0 | Высокие: 2 | Средние: 4 | Низкие: 2)
- **Общая оценка: Удовлетворительная**
- Критических уязвимостей не найдено. Основные проблемы: утечка внутренней информации через `/health`, dev-CORS конфиг в production, отсутствие email-верификации. Финансовые endpoints (wallet, subscription) защищены корректно.
---
## Scope
| Параметр | Значение |
|----------|----------|
| **Цель** | https://seafare-montana.duckdns.org |
| **IP** | 89.19.208.158 |
| **Приложение** | SeaFare Montana — Maritime Logistics AI |
| **Стек** | nginx/1.24.0 (Ubuntu) → Flask (Python) + PostgreSQL |
| **Интеграции** | Google OAuth, Telegram Bot, AISStream, Digitraffic, USDT TRC20 (Tron) |
| **Frontend** | Vanilla HTML/JS + Leaflet.js (карты) |
| **Авторизация** | Flask itsdangerous signed tokens (Bearer) |
| **Период** | 28.02.2026 |
| **Тип** | Black-box → Grey-box |
| **Авторизация на тест** | Подтверждена владельцем |
---
## Результаты сканирования портов
| Порт | Сервис | Статус |
|------|--------|--------|
| **80** | HTTP (nginx) | **OPEN** (→ redirect to HTTPS) |
| **443** | HTTPS (nginx) | **OPEN** |
| 22 | SSH | closed |
| 3306 | MySQL | closed |
| 5432 | PostgreSQL | closed |
| 6379 | Redis | closed |
| 27017 | MongoDB | closed |
| 5050 | Backend (Flask) | closed |
| 8080-9200 | Все прочие (21 порт) | closed |
**Вердикт**: минимальная поверхность атаки. Только HTTP/HTTPS наружу.
---
## API Attack Surface
**Открытые эндпоинты (без auth):**
| Эндпоинт | Данные |
|----------|--------|
| `GET /health` | Имя сервиса, версия, DB, users count, AIS status |
| `GET /api/v1/auth/config` | Google OAuth Client ID |
| `GET /api/v1/subscription/plans` | Планы подписки с ценами |
| `GET /api/v1/ports/search?q=` | Поиск портов (116K+) |
| `POST /api/v1/auth/register` | Открытая регистрация |
| `POST /api/v1/auth/login` | Логин |
**Авторизированные эндпоинты (21+):**
auth/me, profile, chat/stream, chat/history, map/vessels, wallet, wallet/check, wallet/withdraw, wallet/withdrawals, subscription/upgrade, purchased-contacts, telegram/status, telegram/link, telegram/unlink, admin/revenue, admin/costs
---
## Находки
---
### [HIGH-001] Health endpoint — массивная утечка внутренней информации
- **Severity**: High (CVSS 7.2)
- **Категория**: Information Disclosure (OWASP A01:2021)
- **CWE**: CWE-200
**Описание**: Публичный `/health` раскрывает:
- Имя сервиса: "SeaFare API" v3.30.0
- Тип БД: PostgreSQL
- Количество пользователей: 4 (до теста)
- AISStream: статус подключения, bounding boxes, reconnect count, thread status
- Digitraffic: статус конфигурации
**POC:**
```bash
curl -s https://seafare-montana.duckdns.org/health
# → {"db":"ok","db_mode":"postgres","users":4,"version":"3.30.0",
# "ais":{"aisstream":{"connected":true,"tracked_mmsis":0,...}}}
```
**Impact**: Атакующий узнаёт версию, стек, кол-во пользователей, состояние внутренних сервисов без авторизации. Упрощает целевую атаку.
**Remediation:**
1. Убрать users count, AIS details, version из публичного health
2. Оставить только `{"status":"ok"}` для мониторинга
3. Детальный health — за авторизацией (admin only)
---
### [HIGH-002] CORS dev-конфиг в production
- **Severity**: High (CVSS 6.8)
- **Категория**: Security Misconfiguration (OWASP A05:2021)
- **CWE**: CWE-942
**Описание**: Заголовок `Access-Control-Allow-Origin: http://127.0.0.1:5050` возвращается на все ответы. Раскрывает:
1. Внутренний backend на порту 5050
2. Протокол HTTP (не HTTPS) для внутренних запросов
3. Dev-конфигурация осталась в production
**POC:**
```bash
curl -sI https://seafare-montana.duckdns.org/
# → Access-Control-Allow-Origin: http://127.0.0.1:5050
```
**Remediation:**
1. Заменить на `Access-Control-Allow-Origin: https://seafare-montana.duckdns.org`
2. Или динамически проверять Origin по whitelist
---
### [MED-001] Открытая регистрация без email-верификации
- **Severity**: Medium (CVSS 5.3)
- **CWE**: CWE-287
**Описание**: Регистрация мгновенная, без подтверждения email. Аккаунт сразу активен. Можно создавать аккаунты на чужие email.
**POC:**
```bash
curl -s https://seafare-montana.duckdns.org/api/v1/auth/register \
-X POST -H "Content-Type: application/json" \
-d '{"email":"anyone@example.com","password":"123456"}'
# → {"success":true, "token":"...", "user":{"id":5,"is_active":true}}
```
**Remediation**: Email-верификация перед активацией аккаунта.
---
### [MED-002] nginx версия раскрыта в заголовках
- **Severity**: Medium (CVSS 4.3)
- **CWE**: CWE-200
**Описание**: `Server: nginx/1.24.0 (Ubuntu)` — точная версия и ОС.
**Remediation**: `server_tokens off;` в nginx.conf
---
### [MED-003] Flask itsdangerous token — payload в cleartext
- **Severity**: Medium (CVSS 4.5)
- **CWE**: CWE-311
**Описание**: Токен аутентификации содержит base64-encoded payload без шифрования. Любой может декодировать:
```
eyJlbWFpbCI6InBlbnRlc3QuLi4iLCJuYW1lIjoiIn0=
→ {"email":"pentest.seafare@protonmail.com","name":""}
```
Подпись (HMAC) защищает от модификации, но email виден.
**Remediation**: Рассмотреть шифрование payload или переход на JWT с минимальным payload (только user_id).
---
### [MED-004] Subscription upgrade — 500 Internal Server Error
- **Severity**: Medium (CVSS 4.0)
- **CWE**: CWE-209, CWE-755
**Описание**: `POST /api/v1/subscription/upgrade` возвращает 500 без обработки ошибки. Может раскрывать stack trace в debug-режиме.
**POC:**
```bash
curl -s https://seafare-montana.duckdns.org/api/v1/subscription/upgrade \
-X POST -H "Content-Type: application/json" \
-H "Authorization: Bearer <TOKEN>" \
-d '{"plan":"pro"}'
# → 500 Internal Server Error
```
**Remediation**: Обработать ошибку, вернуть корректный JSON с описанием (недостаточно средств / невалидный план).
---
### [LOW-001] Google OAuth Client ID публично доступен
- **Severity**: Low (CVSS 2.5)
- **CWE**: CWE-200
**Описание**: `/api/v1/auth/config` возвращает Google OAuth Client ID. Сам по себе не секрет (нужен для frontend), но позволяет идентифицировать Google Cloud проект.
```
{"google_client_id":"199727561298-...apps.googleusercontent.com"}
```
---
### [LOW-002] Wallet API раскрывает реальный blockchain-адрес
- **Severity**: Low (CVSS 3.0)
- **CWE**: CWE-200
**Описание**: `/api/v1/wallet` возвращает реальный USDT TRC20 адрес: `TRyQSvbE43RzZuuDaNSpbTvyxzaKqvTybR`. Адрес публично отслеживается на блокчейн-эксплорерах.
**Remediation**: Генерировать адрес только при запросе на депозит, не показывать постоянно.
---
## Что НЕ уязвимо (хорошие практики)
| Проверка | Результат |
|----------|-----------|
| Admin endpoints (revenue, costs) | **Заблокированы** — "Admin access required" |
| Privilege escalation (is_admin, plan, balance через profile) | **Заблокировано** — поля не меняют auth-модель |
| Wallet negative amount | **Заблокировано** — min $2 USDT |
| SQL Injection (ports/search) | **Не обнаружена** — параметризация |
| CORS reflection (evil origin) | **Не отражается** |
| Network ports (DB, Redis, SSH) | **Все закрыты** |
| HSTS | **Включен** — max-age=31536000 |
| Security headers | **Все присутствуют** — XFO, XCT, XXP, RP |
| TLS | **Валидный** сертификат |
| Flask SECRET_KEY | **Не тривиальный** — 50 common secrets не подошли |
| Subscription bypass | **Не работает** — план остался free |
---
## Рекомендации по приоритету
### Немедленно (High)
1. Убрать детальную информацию из `/health` — оставить только `{"status":"ok"}`
2. Заменить CORS `127.0.0.1:5050` на production домен
### В течение недели (Medium)
3. Добавить email-верификацию при регистрации
4. `server_tokens off` в nginx
5. Обработать 500 ошибку на subscription/upgrade
6. Шифровать payload токена или перейти на JWT
### В течение месяца (Low)
7. Генерировать wallet-адрес on-demand
8. Ограничить /api/v1/auth/config авторизацией
---
## Методология
- **Инструменты**: curl, Python 3.14
- **Стандарты**: OWASP Top 10 (2021), OWASP API Security Top 10 (2023)
- **Просканировано**: 21 порт, 20+ API-эндпоинтов
- **Тестовый аккаунт**: `pentest.seafare@protonmail.com` (ID: 5) — **удалить**
- **Ущерб**: нулевой
---
*Отчёт подготовлен: 28.02.2026*
*Классификация: КОНФИДЕНЦИАЛЬНО*