Что такое CSRF атака
CSRF (Cross-Site Request Forgery, также XSRF) – опаснейшая атака, которая приводит к тому, что хакер может выполнить на неподготовленном сайте массу различных действий от имени других, зарегистрированных посетителей.
Какие это действия – отправка ли сообщений, перевод денег со счёта на счёт или смена паролей – зависят от сайта, но в любом случае эта атака входит в образовательный минимум веб-разработчика.
Что такое CSRFHelper и как его установить
CSRFHelper — бесплатное MODX, которое поможет защитить ваши формы FormIt и AjaxForm от атак CSRF.
Установка CSRFHelper стандартная из основного репозитория.
Защита MODX форм от CSRF атак по шагам
1. Добавление токена в форму
В форме добавьте следующее скрытое поле:
<input type="hidden" name="csrf_token" value="[[!csrfhelper? &key=`simple-form`]]">
Примечание: у каждой формы должно быть уникальное значение
&key
.Для конфиденциальных форм вы также можете добавить свойство
&singleUse
со значением 1, которое гарантирует, что каждый запрос получит уникальный токен CSRF. Если вы не укажете этот параметр, токен для формы останется неизменным в течение 24 часов.
Чтобы показать ошибку, когда токен CSRF не совпадает, или если он не может быть безопасно сгенерирован на вашем сервере, добавьте следующее в подходящее место в вашей форме:
[[!+fi.error.csrf_token:notempty=`<div class="error">[[!+fi.error.csrf_token]]</div>`]]
2. Проверка токена с помощью хука
Теперь, когда мы отправляем токен, мы также должны его проверить. Делаем это хук csrfhelper_formit
.
В вызове FormIt или AjaxForm добавьте csrfhelper_formit
к своему &hooks
.
Также добавьте свойство &csrfKey
с хуком для токена CSRF; это должно быть уникальным для каждой уникальной формы и соответствовать &key
в csrfhelper
вызове сниппета. В приведенном выше примере это было установлено на simple-form
.
Примеры форм с защитой от CSRF атак
Вот пример из официальной документации по плагину:
[[!FormIt?
&hooks=`spam,csrfhelper_formit,email,redirect`
&redirectTo=`71`
&validate=`nospam:blank,
name:required,
email:email:required,
subject:required,
text:required:stripTags`
&csrfKey=`simple-form`
]]
<h2>Contact Form</h2>
[[!+fi.validation_error_message:notempty=`<p>[[!+fi.validation_error_message]]</p>`]]
<form action="[[~[[*id]]]]" method="post" class="form">
[[!+fi.error.csrf_token:notempty=`<div class="error">[[!+fi.error.csrf_token]]</div>`]]
<input type="hidden" name="csrf_token" value="[[!csrfhelper? &key=`simple-form`]]">
<input type="hidden" name="nospam" value="" />
<label for="name">
Name:
<span class="error">[[!+fi.error.name]]</span>
</label>
<input type="text" name="name" id="name" value="[[!+fi.name]]" />
<label for="email">
Email:
<span class="error">[[!+fi.error.email]]</span>
</label>
<input type="text" name="email" id="email" value="[[!+fi.email]]" />
<label for="subject">
Subject:
<span class="error">[[!+fi.error.subject]]</span>
</label>
<input type="text" name="subject" id="subject" value="[[!+fi.subject]]" />
<label for="text">
Message:
<span class="error">[[!+fi.error.text]]</span>
</label>
<textarea name="text" id="text" cols="55" rows="7" value="[[!+fi.text]]">[[!+fi.text]]</textarea>
<div class="form-buttons">
<input type="submit" value="Send Contact Inquiry" />
</div>
</form>
И дополнительно, в качестве примера возьму форму на AjaxForm и fenom со страницы контактов, которую делали в этом уроке. Сразу модифицирую ее вывод и чанк.
Вывод станет таким:
{'!AjaxForm' | snippet : [
'snippet' => 'FormIt',
'hooks' => 'csrfhelper_formit,email',
'validate' => 'name:required:maxLength=^21^,email:email:required,message:required:minLength=^30^',
'form' => 'contact_form',
'emailTpl' => 'tplForm',
'emailTo' => $_modx->config.emailsender,
'emailFrom' => 'noretly@modx-revolution.ru',
'emailSubject' => 'Сообщение со страницы контакты на сайте ' ~ $_modx->config.site_name,
'successMessage' => '<div class="contact-form-success alert alert-success mt-4"><strong>Успешно!</strong> Ваше сообщение отправлено нам.</div>',
'validationErrorMessage' => '<div class="contact-form-success alert alert-danger mt-4"><strong>Ошибка!</strong> Произошла ошибка при отправке вашего сообщения.</div>',
'csrfKey' => 'contact_form'
]}
А чанк, таким:
<form class="ajax_form af_example contact-form custom-form-style-1" action="{$_modx->makeUrl($_modx->resource.id, '', '', 'full')}" method="post">
{$fi.successMessage}
{$fi.validation_error_message}
{$fi.error.csrf_token}
<input type="hidden" name="csrf_token" value="{'!csrfhelper' | snippet : [ 'key' => 'contact_form' ]}">
<div class="row row-gutter-sm">
<div class="form-group col mb-3">
<input type="text" value="" class="form-control" name="name" placeholder="Ваше имя">
<span class="error_name">{$fi.error.name}</span>
</div>
</div>
<div class="row row-gutter-sm">
<div class="form-group col mb-3">
<input type="email" value="" class="form-control" name="email" placeholder="Ваш E-mail">
<span class="error_email">{$fi.error.email}</span>
</div>
</div>
<div class="row">
<div class="form-group col mb-3">
<textarea rows="4" class="form-control" name="message" placeholder="Сообщение"></textarea>
<span class="error_message">{$fi.error.message}</span>
</div>
</div>
<div class="row appear-animation" data-appear-animation="fadeInUpShorterPlus" data-appear-animation-delay="1500">
<div class="form-group col mb-0">
<button type="submit" class="btn btn-primary btn-modern font-weight-bold custom-btn-border-radius custom-btn-arrow-effect-1 text-3 px-5 py-3">
ОТПРАВИТЬ
<svg class="ms-2" version="1.1" viewBox="0 0 15.698 8.706" width="17" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<polygon stroke="#FFF" stroke-width="0.1" fill="#FFF" points="11.354,0 10.646,0.706 13.786,3.853 0,3.853 0,4.853 13.786,4.853 10.646,8 11.354,8.706 15.698,4.353 "/>
</svg>
</button>
</div>
</div>
</form>
Рекомендую во все формы на сайте внедрить защиту от CSRF атак + внедрить пару способов борьбы со спамом без капч, так вы отсекете огромный поток спама (защита будет не хуже чем гугл капча и не будет напрягать пользователей).
Ниже приведен полный пример, основанный на примере простой контактной формы для FormIt. В следующем уроке сделаем хлебные крошки.