Безопасность

Руководство по безопасности при работе с Triangle Framework.

Основные принципы безопасности

1. Валидация входных данных

Всегда валидируйте и санитизируйте данные пользователя:

use Triangle\Engine\Request;

Router::post('/users', function (Request $request) {
    // ✅ Валидация типов через type hints
    $name = $request->post('name'); // string|null
    $age = $request->post('age');    // string|null
    
    // ✅ Дополнительная валидация
    if (empty($name) || strlen($name) < 2) {
        throw new InvalidInputException('Имя должно содержать минимум 2 символа');
    }
    
    if (!is_numeric($age) || $age < 18) {
        throw new InvalidInputException('Возраст должен быть числом >= 18');
    }
    
    // Обработка данных...
});

2. Защита от SQL Injection

Используйте Query Builder или Eloquent ORM:

use Triangle\Database\Facades\Db;

// ✅ Безопасно - параметризованные запросы
$users = Db::table('users')
    ->where('email', $email)
    ->where('status', 'active')
    ->get();

// ❌ НЕБЕЗОПАСНО - никогда не делайте так
$users = Db::select("SELECT * FROM users WHERE email = '$email'");

// ✅ Безопасно с Eloquent
$user = User::where('email', $email)->first();

3. Защита от XSS (Cross-Site Scripting)

Экранируйте выходные данные:

use Triangle\View\Facades\View;

// В шаблонах автоматически экранируется
return view('user', [
    'name' => $user->name, // Автоматически экранировано
]);

// Для JSON ответов
return responseJson([
    'message' => htmlspecialchars($message, ENT_QUOTES, 'UTF-8'),
]);

4. CSRF защита

Для state-changing операций используйте токены:

// В форме
<form method="POST" action="/posts">
    <input type="hidden" name="_token" value="<?= csrf_token() ?>">
    <!-- ... -->
</form>

// В middleware или контроллере
if ($request->post('_token') !== session('_token')) {
    throw new InvalidInputException('Invalid CSRF token');
}

5. Конфигурация для Production

Настройте config/app.php:

<?php

return [
    'debug' => false, // ✅ ВСЕГДА false в production
    'http_always_200' => false,
    'support_php_files' => false, // ✅ Отключить выполнение PHP файлов
    
    'log' => [
        'level' => 'error', // Только ошибки в production
    ],
];

6. Работа с файлами

Проверяйте типы и размеры файлов:

use Triangle\Engine\Request;
use Triangle\Engine\File;

Router::post('/upload', function (Request $request) {
    $file = $request->file('avatar');
    
    if (!$file || !$file->isValid()) {
        throw new InvalidInputException('Файл не загружен');
    }
    
    // Проверка типа
    $allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
    if (!in_array($file->getType(), $allowedTypes)) {
        throw new InvalidInputException('Недопустимый тип файла');
    }
    
    // Проверка размера (например, 5MB)
    if ($file->getSize() > 5 * 1024 * 1024) {
        throw new InvalidInputException('Файл слишком большой');
    }
    
    // Сохранение файла
    $file->move(storage_path('uploads'), $file->getName());
});

7. Аутентификация и авторизация

Используйте middleware для защиты маршрутов:

use Triangle\Middleware\MiddlewareInterface;
use Triangle\Engine\Request;
use Triangle\Engine\Response;

class AuthMiddleware implements MiddlewareInterface
{
    public function process(Request $request, callable $next): Response
    {
        if (!session()->has('user_id')) {
            return response()->withStatus(401);
        }
        
        return $next($request);
    }
}

// Применение middleware
Router::middleware([AuthMiddleware::class])->group(function () {
    Router::get('/dashboard', [DashboardController::class, 'index']);
});

8. Работа с сессиями

Используйте безопасные настройки сессий:

// config/session.php
return [
    'driver' => 'file', // или 'redis' для production
    'lifetime' => 120, // 2 часа
    'secure' => true, // HTTPS only
    'http_only' => true, // Защита от XSS
    'same_site' => 'strict', // CSRF защита
];

9. Rate Limiting

Ограничивайте количество запросов:

use Triangle\Middleware\MiddlewareInterface;
use Triangle\Engine\Request;
use Triangle\Engine\Response;
use Triangle\Database\Facades\Db;

class RateLimitMiddleware implements MiddlewareInterface
{
    public function process(Request $request, callable $next): Response
    {
        $ip = $request->getRemoteIp();
        $key = "rate_limit:$ip";
        
        // Используйте Redis или кэш
        $attempts = cache()->get($key, 0);
        
        if ($attempts >= 60) { // 60 запросов в минуту
            return response('Too Many Requests', 429);
        }
        
        cache()->set($key, $attempts + 1, 60);
        
        return $next($request);
    }
}

10. Логирование и мониторинг

Логируйте подозрительную активность:

use Triangle\Engine\Logger;

try {
    // Обработка запроса
} catch (SuspiciousActivityException $e) {
    Logger::warning('Suspicious activity detected', [
        'ip' => $request->getRemoteIp(),
        'path' => $request->path(),
        'user_agent' => $request->header('user-agent'),
    ]);
    
    throw $e;
}

Best Practices

Конфигурация

  1. Никогда не коммитьте секреты в репозиторий
  2. Используйте переменные окружения для чувствительных данных
  3. Ротация ключей для production
  4. Регулярные обновления зависимостей

Разработка

  1. Валидация на стороне сервера - никогда не полагайтесь только на клиентскую валидацию
  2. Принцип наименьших привилегий - давайте минимальные необходимые права
  3. Регулярные аудиты безопасности кода
  4. Тестирование безопасности как часть CI/CD

Развертывание

  1. HTTPS везде в production
  2. Security headers (CSP, X-Frame-Options, etc.)
  3. Регулярные бэкапы базы данных
  4. Мониторинг логов на подозрительную активность

Отчетность об уязвимостях

Если вы обнаружили уязвимость в безопасности, пожалуйста, НЕ создавайте публичный issue.

Вместо этого отправьте email на security@localzet.com с:

  • Описанием уязвимости
  • Шагами для воспроизведения
  • Потенциальным воздействием
  • Предложенным исправлением (если есть)

Мы ответим в течение 24 часов и предоставим начальный ответ в течение 48 часов.

Дополнительные ресурсы