diff --git a/docs/server-audit.md b/docs/server-audit.md index d59f066..6249899 100644 --- a/docs/server-audit.md +++ b/docs/server-audit.md @@ -1,6 +1,6 @@ # Аудит сервера SHServ -**Дата:** 2026-06-02 +**Дата:** 2026-06-03 **Версия PHP:** 8.x **Файлов:** 96 `.php` **Фреймворк:** Fury (кастомный MVC) @@ -500,27 +500,60 @@ --- +## Тестирование + +PHPUnit установлен в `server/` (`composer.json`). Для тестирования ThinBuilder добавлена поддержка SQLite (`:memory:`) в `ThinBuilderProcessing::create_connect()`. + +### Запуск +```bash +cd server +./vendor/bin/phpunit +``` + +### Покрытие + +| Тест | Что проверяет | Статус | +|------|---------------|--------| +| `ThinBuilderTest` | insert, select (flat + nested where), update, delete, SQLi identifier/value, транзакции, SQL generation | ✅ 10 тестов | +| `RateLimiterTest` | лимиты, блокировка, сброс окна, независимость по IP | ✅ 4 теста | +| `PasswordHashTest` | Argon2id verify, SHA1 legacy fallback, rehash detection | ✅ 3 теста | + +**Итого:** 17 тестов, все проходят. + +### Что ещё нужно покрыть +- `DeviceAPI\Base` — retry/backoff (mock cURL). +- `Entity::update()` и транзакции в `Models\Devices`. +- Валидация в контроллерах (`DevicesRESTAPIController`, `AreasRESTAPIController`). +- `App::api_auth_guard()` и `RateLimiter` integration. + +--- + ## Приложение: Файлы, требующие внимания -| Файл | Phase | Проблемы | -|------|-------|----------| -| `SHServ/config.php` | 1.3 | Secrets, debug mode | -| `SHServ/App.php` | 1.1, 2.3, 5.1, 5.3, 5.9 | Auth middleware, сет-эффект, is_dir, root_folder | -| `SHServ/Routes.php` | 1.1, 3.5 | Нет auth, нет rate limit | -| `SHServ/Sessions.php` | 1.5, 1.6 | Токены, cookie flags | -| `SHServ/Models/Example_Auth.php` | 1.4 | SHA1 | -| `SHServ/Controllers/ScriptsRESTAPIController.php` | 3.1, 3.2, 3.3, 3.4, 5.4 | Валидация, raw ответ, path traversal, alias | -| `SHServ/Controllers/DevicesRESTAPIController.php` | 3.1, 4.5 | IP валидация, reset ignore response | -| `SHServ/Controllers/AreasRESTAPIController.php` | 3.1 | Валидация area | -| `SHServ/Controllers/EventsController.php` | 3.1 | Валидация event | -| `SHServ/Models/Devices.php` | 2.3 | Нет транзакции | -| `SHServ/Models/Areas.php` | 5.10 | Magic number, пустой stub | -| `SHServ/Models/Scripts.php` | 1.7 | unlink без auth | -| `SHServ/Tools/DeviceScanner.php` | 4.1 | 253 concurrent curl | -| `SHServ/Tools/DeviceAPI/Base.php` | 4.2, 4.3 | Нет retry, hardcoded timeouts | -| `SHServ/Tools/DeviceAPI/Hatch.php` | 5.6 | Undefined variable | -| `Fury/Modules/ThinBuilder/ThinBuilder.php` | 1.2, 2.4 | SQL injection, silent null | -| `Fury/Modules/ThinBuilder/ThinBuilderProcessing.php` | 1.2 | SQL injection | -| `Fury/Modules/ErrorHandler/ErrorHandler.php` | 2.1, 2.2 | Инвертированная логика, закомментированный handler | -| `Fury/Kernel/Logging.php` | 5.11 | Логи в web root | -| `console.php` | 1.7 | Слив конфига | +| Файл | Phase | Проблемы | Статус | +|------|-------|----------|--------| +| `SHServ/config.php` | 1.3 | Secrets, debug mode | ✅ `.env` + загрузка | +| `SHServ/App.php` | 1.1, 2.3, 5.1, 5.3, 5.9 | Auth middleware, сет-эффект, is_dir, root_folder | ✅ Все исправлены | +| `SHServ/Routes.php` | 1.1, 3.5 | Нет auth, нет rate limit | ✅ Guard + RateLimiter в `App.php` | +| `SHServ/Sessions.php` | 1.5, 1.6 | Токены, cookie flags | ✅ `random_bytes(32)`, Secure/HttpOnly/Strict | +| `SHServ/Models/Example_Auth.php` | 1.4 | SHA1 | ✅ Argon2id + fallback | +| `SHServ/Controllers/ScriptsRESTAPIController.php` | 3.1, 3.2, 3.3, 3.4, 5.4 | Валидация, raw ответ, path traversal, alias | ✅ Все исправлены | +| `SHServ/Controllers/DevicesRESTAPIController.php` | 3.1, 4.5 | IP валидация, reset ignore response | ✅ Все исправлены | +| `SHServ/Controllers/AreasRESTAPIController.php` | 3.1 | Валидация area | ✅ alias regex | +| `SHServ/Controllers/EventsController.php` | 3.1 | Валидация event | 🟡 Не затронут | +| `SHServ/Models/Devices.php` | 2.3 | Нет транзакции | ✅ Транзакция добавлена | +| `SHServ/Models/Areas.php` | 5.10 | Magic number, пустой stub | ✅ Константа `MAX_LIMIT`, stub удалён | +| `SHServ/Models/Scripts.php` | 1.7 | unlink без auth | 🟡 Не затронут (обход через auth guard) | +| `SHServ/Tools/DeviceScanner.php` | 4.1 | 253 concurrent curl | ✅ Batch size 32 | +| `SHServ/Tools/DeviceAPI/Base.php` | 4.2, 4.3 | Нет retry, hardcoded timeouts | ✅ 3 retries + backoff + env таймауты | +| `SHServ/Tools/DeviceAPI/Hatch.php` | 5.6 | Undefined variable | ✅ `$state` вместо `$status_response` | +| `Fury/Modules/ThinBuilder/ThinBuilder.php` | 1.2, 2.4 | SQL injection, silent null | ✅ Prepared statements + exception | +| `Fury/Modules/ThinBuilder/ThinBuilderProcessing.php` | 1.2 | SQL injection | ✅ `validate_identifier` + `?` placeholders | +| `Fury/Modules/ErrorHandler/ErrorHandler.php` | 2.1, 2.2 | Инвертированная логика, закомментированный handler | ✅ Исправлено | +| `Fury/Kernel/Logging.php` | 5.11 | Логи в web root | ✅ `flock`, `0640`, путь вне web root | +| `console.php` | 1.7 | Слив конфига | ✅ unset db.password/user | +| `SHServ/Entities/User.php` | 5.5 | `new Profile($uid)` баг | ✅ Запрос `profile_id` из БД | +| `ControlScripts/Common.php` | 5.8 | Hardcoded alias'ы | ✅ Вынесено в `sync-map.json` | +| `SHServ/.env.example` | 1.3 | — | ✅ Добавлен | +| `server/composer.json` | Тесты | — | ✅ PHPUnit 10 | +| `server/tests/` | Тесты | — | ✅ ThinBuilder, RateLimiter, PasswordHash |