Skip to content

Безопасность Laravel — лучшие практики (OWASP)

Дополняет правила безопасности в корневом ../../CLAUDE.md и ../blade.md. Проверять при любых изменениях на периметре (формы, API, публичные роуты).

SQL-инъекции

php
// ОПАСНО — конкатенация
DB::select("SELECT * FROM users WHERE email = '$email'");
User::whereRaw("name = '$name'");

// БЕЗОПАСНО — bindings / Eloquent
User::where('email', $email)->first();
DB::select('SELECT * FROM users WHERE email = ?', [$email]);
User::whereRaw('lower(name) = ?', [mb_strtolower($name)]);   // bindings даже в raw

Eloquent/Query Builder экранируют значения. DB::raw() — только для выражений (не данных), данные — через bindings.

XSS

СинтаксисПоведениеКогда
экранирует HTMLВСЕГДА по умолчанию
{!! $html !!}НЕ экранируеттолько доверенный HTML из админки
@js($var)безопасная передача в JSBlade → JS-переменная

{!! !!} с пользовательским вводом = XSS. Если нужен HTML от пользователя — санитизация (mews/purifier / HTMLPurifier) перед выводом.

CSRF

  • Web-формы: @csrf в форме (middleware проверяет автоматически).
  • Исключения (вебхуки): $middleware->validateCsrfTokens(except: ['stripe/*']) в bootstrap/app.php.
  • API на Sanctum (SPA) — CSRF через cookie; токен-API — CSRF не нужен (stateless).

Массовое присвоение

php
protected $fillable = ['name', 'email'];           // whitelist
// НИКОГДА: $guarded = []  на модели с пользовательским вводом
// НИКОГДА: User::create($request->all());  → используй validated()
User::create($request->validated());

Авторизация

  • Policies для моделей: php artisan make:policy PostPolicy --model=Post.
  • Gate::authorize() / $this->authorize() / @can в Blade.
  • Не проверять права в middleware «вручную» — Policy/Gate централизованно.
  • Route model binding по slug (публичные) / id (admin) + scopeBindings() для вложенных (проверка принадлежности child к parent).
php
public function update(UpdatePostRequest $request, Post $post)
{
    $this->authorize('update', $post);             // или в FormRequest::authorize()
    ...
}

Валидация

  • Только в FormRequest, не в контроллере.
  • max:255 на все string-поля (защита от переполнения).
  • email:rfc,dns, exists:table,col для FK, unique:...->ignore($id) при update.
  • Файлы: file, mimes:, max: (КБ) — проверять тип и размер. Хранить вне webroot или через Storage.

Секреты и конфигурация

php
// НИКОГДА env() вне config-файлов (ломается при config:cache)
$key = env('STRIPE_KEY');           // ПЛОХО в коде
$key = config('services.stripe.key'); // ХОРОШО
  • .env — в .gitignore, .env.example — в git с пустыми значениями.
  • APP_DEBUG=false в production — без исключений (stack traces видны юзерам).
  • APP_KEY сгенерирован; ротация через APP_PREVIOUS_KEYS (L11+).
  • Секреты — только в .envconfig(), не в коде/коммитах.

Аутентификация

  • Пароли: bcrypt/argon2 (дефолт), BCRYPT_ROUNDS растить со временем (авто-rehash в L11+).
  • Rate limiting на login/API: throttle: middleware, Limit::perMinute() / perSecond().
  • 2FA для админки (Fortify/Filament).
  • Sanctum для SPA/мобильных API, Passport — только для полноценного OAuth-сервера.

HTTP-периметр

  • HTTPS обязателен (Caddy/Let's Encrypt — см. корневой E:\Clients\CLAUDE.md).
  • За reverse proxy: TrustProxies middleware + URL::forceScheme('https') по request()->isSecure().
  • Security headers: HSTS, X-Content-Type-Options, CSP (на nginx/Caddy или middleware).
  • Не раскрывать stack traces, версии, внутренние ошибки в production-ответах (500 → generic).

API

КодКогда
401не аутентифицирован
403аутентифицирован, но нет прав (Policy)
422ошибка валидации
429rate limit
500серверная — БЕЗ деталей в prod
  • Rate limiting на каждый POST/PUT/DELETE.
  • API Resources для трансформации (не отдавать модель напрямую — утечка полей).
  • Не класть PII/секреты в URL (query string логируется).

Зависимости

  • composer audit в CI — known CVE в пакетах.
  • Обновлять зависимости регулярно (minor/patch не ломают по SemVer).
  • Минимум сторонних пакетов на периметре — каждый = surface attack.

Чеклист security-review

  1. Все SQL через Eloquent/bindings, нет конкатенации
  2. везде, {!! !!} только доверенный HTML
  3. @csrf в формах, вебхуки в except
  4. validated(), не all(); FormRequest на каждую форму
  5. Policy/Gate на защищённых действиях
  6. config(), не env() в коде; .env не в git; APP_DEBUG=false в prod
  7. Rate limiting на API/login
  8. composer audit зелёный

Внутренняя база знаний студии