Безпека
Безпека
Безпека в Celena не опційна — це набір обовʼязкових практик. Нижче — що використовувати і чого не робити.
Валідація введення
Будь-яке введення користувача проходить через Celena\Core\Security\Filter:
use Celena\Core\Security\Filter;
$name = Filter::string((string) $request->input('name'));
$slug = Filter::urlSlug((string) $request->input('slug'));
$email = Filter::email((string) $request->input('email'));
$id = (int) $request->input('id');
Не довіряйте $_GET/$_POST напряму — беріть через $request->input()/query() і фільтруйте.
SQL-інʼєкції
Лише підготовлені вирази та QueryBuilder. Конкатенація значень у SQL заборонена.
// ПРАВИЛЬНО
$conn->builder('users')->where('email', '=', $email)->first();
$conn->run('SELECT * FROM ' . $conn->table('users') . ' WHERE id = ?', [$id]);
// НЕБЕЗПЕЧНО — так не можна
$conn->run("SELECT * FROM users WHERE email = '$email'");
XSS — виведення в HTML
У шаблонах змінні екрануються автоматично ({var}). Сире виведення ({var|raw}) — лише для довіреного HTML. У PHP використовуйте хелпер e():
echo e($userText); // безпечно
echo $userText; // НЕБЕЗПЕЧНО, якщо це введення користувача
Markdown-рендерер ядра екранує початковий HTML — користувацький markdown не може виконати <script>.
CSRF
Форми та AJAX-запити захищені токеном. У шаблоні:
<form method="post">{csrf} … </form> <!-- прихований інпут _csrf -->
{csrf format="meta"} <!-- мета-тег для fetch/AJAX -->
На сервері:
use Celena\Core\Security\Csrf;
if (!Csrf::validate((string) $request->input('_csrf'))) {
return Response::json(['error' => 'csrf'], 419);
}
Автентифікація та ролі
- Паролі зберігаються як Argon2id (
Celena\Core\Security\Password). У відкритому вигляді не зберігаються ніде. - Вхід —
/admin/login. Користувачі — у таблиціcl_celena_users. - Ролі:
admin(усе),editor,author,user,customer. Перевірка прав:
use Celena\Core\Security\Permission;
if (!Permission::can($user, 'news.update')) {
return Response::redirect('/admin/login');
}
Адмінські контролери перевіряють $this->auth->user() на початку дії.
Обмеження частоти
Celena\Core\Security\RateLimiter захищає чутливі ручки (логін, приймання заявок, публічний API) від перебору:
$limiter = $container->make(RateLimiter::class);
if (!$limiter->attempt('login_' . $request->ip(), 5, 60)) { // 5 спроб за хвилину
return Response::json(['error' => 'rate_limited'], 429);
}
Завантаження файлів і zip
- Перевіряйте MIME/розширення завантажуваних файлів; не віддавайте їх як виконувані.
- Встановлювач плагінів перевіряє архіви на ZIP-Slip (вихід за межі теки), блокує
.phar, валідуєmanifest.json. Ці самі перевірки повторюйте при будь-якому розпакуванні користувацьких архівів.
CSP і зовнішні ресурси
Політика безпеки контенту (CSP) пускає скрипти лише з 'self' і довірених доменів (Google-сервіси). Зовнішні CDN (jQuery, шрифти, віджети) заблоковані — зберігайте асети локально. На сайті немає jQuery.
.htaccess і сервер
Не використовуйте в .htaccess директиви <Directory> чи php_flag при роботі з PHP-FPM — це ламає Apache (помилка 500). Кеш-заголовки статики налаштовуються на рівні nginx, а не в .htaccess.