CSRF Захист
2.5.x ✅ 4.0.x ✅
Атаки Cross-Site Request Forgery (CSRF) змушують користувачів виконувати небажані дії на сайті, де вони пройшли автентифікацію. XOOPS забезпечує вбудований захист CSRF через клас XoopsSecurity.
Пов’язана документація
Section titled “Пов’язана документація”- Security-Best-Practices - Вичерпний посібник із безпеки
- Очистка введення - MyTextSanitizer і перевірка
- SQL-Injection-Prevention - Методи безпеки бази даних
Розуміння атак CSRF
Section titled “Розуміння атак CSRF”Атака CSRF виникає, коли:
- Користувач аутентифікований на вашому сайті XOOPS
- Користувач відвідує шкідливий веб-сайт
- Шкідливий сайт надсилає запит на ваш сайт XOOPS, використовуючи сеанс користувача
- Ваш сайт обробляє запит так, ніби він надійшов від законного користувача
Клас безпеки Xoops
Section titled “Клас безпеки Xoops”XOOPS надає клас XoopsSecurity для захисту від атак CSRF. Цей клас керує маркерами безпеки, які мають бути включені у форми та перевірені під час обробки запитів.
Генерація маркерів
Section titled “Генерація маркерів”Клас безпеки генерує унікальні токени, які зберігаються в сеансі користувача та мають бути включені у форми:
$security = new XoopsSecurity();
// Get token HTML input field$tokenHTML = $security->getTokenHTML();
// Get just the token value$tokenValue = $security->createToken();Перевірка маркера
Section titled “Перевірка маркера”Під час обробки надсилання форми переконайтеся, що маркер дійсний:
$security = new XoopsSecurity();
if (!$security->check()) { redirect_header('index.php', 3, _MD_TOKENEXPIRED); exit();}Використання XOOPS Token System
Section titled “Використання XOOPS Token System”З класами XoopsForm
Section titled “З класами XoopsForm”При використанні класів форм XOOPS захист токенів є простим:
// Create a form$form = new XoopsThemeForm('Add Item', 'form_name', 'submit.php');
// Add form elements$form->addElement(new XoopsFormText('Title', 'title', 50, 255, ''));$form->addElement(new XoopsFormTextArea('Content', 'content', ''));
// Add hidden token field - ALWAYS include this$form->addElement(new XoopsFormHiddenToken());
// Add submit button$form->addElement(new XoopsFormButton('', 'submit', _SUBMIT, 'submit'));За допомогою спеціальних форм
Section titled “За допомогою спеціальних форм”Для спеціальних форм HTML, які не використовують XoopsForm:
// In your form template or PHP file$security = new XoopsSecurity();?><form method="post" action="submit.php"> <input type="text" name="title" /> <textarea name="content"></textarea>
<!-- Include the token --> <?php echo $security->getTokenHTML(); ?>
<button type="submit">Submit</button></form>У шаблонах Smarty
Section titled “У шаблонах Smarty”Під час створення форм у шаблонах Smarty:
// In your PHP file$security = new XoopsSecurity();$GLOBALS['xoopsTpl']->assign('token', $security->getTokenHTML());{* In your template *}<form method="post" action="submit.php"> <input type="text" name="title" /> <textarea name="content"></textarea>
{* Include the token *} <{$token}>
<button type="submit">Submit</button></form>Обробка подання форми
Section titled “Обробка подання форми”Базова перевірка маркерів
Section titled “Базова перевірка маркерів”// In your form processing script$security = new XoopsSecurity();
// Verify the tokenif (!$security->check()) { redirect_header('index.php', 3, _MD_TOKENEXPIRED); exit();}
// Token is valid, process the form$title = $_POST['title'];// ... continue processingЗ індивідуальною обробкою помилок
Section titled “З індивідуальною обробкою помилок”$security = new XoopsSecurity();
if (!$security->check()) { // Get detailed error information $errors = $security->getErrors();
// Log the error error_log('CSRF token validation failed: ' . implode(', ', $errors));
// Redirect with error message redirect_header('form.php', 3, 'Security token expired. Please try again.'); exit();}Для запитів AJAX
Section titled “Для запитів AJAX”Працюючи із запитами AJAX, додайте в запит маркер:
// JavaScript - get token from hidden fieldvar token = document.querySelector('input[name="XOOPS_TOKEN_REQUEST"]').value;
// Include in AJAX requestfetch('ajax_handler.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: 'action=save&XOOPS_TOKEN_REQUEST=' + encodeURIComponent(token)});// PHP AJAX handler$security = new XoopsSecurity();
if (!$security->check()) { echo json_encode(['error' => 'Invalid security token']); exit();}
// Process AJAX requestПеревірка посилання HTTP
Section titled “Перевірка посилання HTTP”Для додаткового захисту, особливо для запитів AJAX, ви також можете перевірити реферер HTTP:
$security = new XoopsSecurity();
// Check referer headerif (!$security->checkReferer()) { echo json_encode(['error' => 'Invalid request']); exit();}
// Also verify the tokenif (!$security->check()) { echo json_encode(['error' => 'Invalid token']); exit();}Комбінована перевірка безпеки
Section titled “Комбінована перевірка безпеки”$security = new XoopsSecurity();
// Perform both checksif (!$security->checkReferer() || !$security->check()) { redirect_header('index.php', 3, 'Security validation failed'); exit();}Конфігурація маркера
Section titled “Конфігурація маркера”Термін служби маркера
Section titled “Термін служби маркера”Жетони мають обмежений термін служби, щоб запобігти повторним атакам. Ви можете налаштувати це в налаштуваннях XOOPS або акуратно обробляти прострочені токени:
$security = new XoopsSecurity();
if (!$security->check()) { // Token may have expired // Regenerate form with new token redirect_header('form.php', 3, 'Your session has expired. Please submit the form again.'); exit();}Кілька форм на одній сторінці
Section titled “Кілька форм на одній сторінці”Якщо у вас є кілька форм на одній сторінці, кожна має мати власний маркер:
// Form 1$form1 = new XoopsThemeForm('Form 1', 'form1', 'submit1.php');$form1->addElement(new XoopsFormHiddenToken('token1'));
// Form 2$form2 = new XoopsThemeForm('Form 2', 'form2', 'submit2.php');$form2->addElement(new XoopsFormHiddenToken('token2'));Найкращі практики
Section titled “Найкращі практики”Завжди використовуйте маркери для операцій зміни стану
Section titled “Завжди використовуйте маркери для операцій зміни стану”Включайте маркери в будь-якій формі, яка:
- Створює дані
- Оновлення даних
- Видалення даних
- Змінює налаштування користувача
- Виконує будь-які адміністративні дії
Не покладайтеся виключно на перевірку за рекомендаціями
Section titled “Не покладайтеся виключно на перевірку за рекомендаціями”Заголовок посилання HTTP може бути:
- Позбавлені інструментів конфіденційності
- Відсутній у деяких браузерах
- У деяких випадках підроблено
Завжди використовуйте перевірку маркерів як основний захист.
Регенеруйте токени належним чином
Section titled “Регенеруйте токени належним чином”Розглянемо регенерацію токенів:
- Після успішної подачі форми
- Після login/logout
- Через рівні проміжки часу для тривалих сеансів
Витончено обробляйте термін дії маркера
Section titled “Витончено обробляйте термін дії маркера”$security = new XoopsSecurity();
if (!$security->check()) { // Store form data temporarily $_SESSION['form_backup'] = $_POST;
// Redirect back to form with message redirect_header('form.php?restore=1', 3, 'Please resubmit the form.'); exit();}Поширені проблеми та рішення
Section titled “Поширені проблеми та рішення”Помилка маркера не знайдено
Section titled “Помилка маркера не знайдено”Проблема: помилка перевірки безпеки з повідомленням «токен не знайдено»
Рішення: переконайтеся, що поле маркера включено у вашу форму:
$form->addElement(new XoopsFormHiddenToken());Помилка терміну дії маркера
Section titled “Помилка терміну дії маркера”Проблема: після тривалого заповнення форми користувачі бачать «термін дії маркера минув».
Рішення: спробуйте використовувати JavaScript для періодичного оновлення маркера:
// Refresh token every 10 minutessetInterval(function() { fetch('refresh_token.php') .then(response => response.json()) .then(data => { document.querySelector('input[name="XOOPS_TOKEN_REQUEST"]').value = data.token; });}, 600000);Проблеми з маркером AJAX
Section titled “Проблеми з маркером AJAX”Проблема: запити AJAX не проходять перевірку маркера
Рішення: переконайтеся, що маркер передається з кожним запитом AJAX і перевірте його на стороні сервера:
// AJAX handlerheader('Content-Type: application/json');
$security = new XoopsSecurity();if (!$security->check(true, false)) { // Don't clear token for AJAX http_response_code(403); echo json_encode(['error' => 'Invalid token']); exit();}Приклад: повна реалізація форми
Section titled “Приклад: повна реалізація форми”<?phprequire_once dirname(__DIR__) . '/mainfile.php';
$security = new XoopsSecurity();
// Handle form submissionif ($_SERVER['REQUEST_METHOD'] === 'POST') { if (!$security->check()) { redirect_header('form.php', 3, 'Security token expired. Please try again.'); exit(); }
// Process valid submission $title = $myts->htmlSpecialChars($_POST['title']); // ... save to database
redirect_header('success.php', 3, 'Item saved successfully!'); exit();}
// Display form$GLOBALS['xoopsOption']['template_main'] = 'mymodule_form.tpl';include XOOPS_ROOT_PATH . '/header.php';
$form = new XoopsThemeForm('Add Item', 'add_item', 'form.php');$form->addElement(new XoopsFormText('Title', 'title', 50, 255, ''));$form->addElement(new XoopsFormTextArea('Content', 'content', ''));$form->addElement(new XoopsFormHiddenToken());$form->addElement(new XoopsFormButton('', 'submit', _SUBMIT, 'submit'));
$GLOBALS['xoopsTpl']->assign('form', $form->render());
include XOOPS_ROOT_PATH . '/footer.php';#безпека #csrf #xoops #форми #токени #XoopsSecurity