WordPress и CSRF защита: практическое руководство с nonce и проверкой referer

person in black and white t-shirt using computer

Введение

Cross‑Site Request Forgery (CSRF) – одна из самых распространённых уязвимостей в веб‑приложениях. В WordPress атаки часто используют отсутствие проверок токенов, позволяя злоумышленнику выполнить действия от имени авторизованного пользователя. В этой статье мы разберём, как правильно внедрять csrf защиту wordpress с помощью nonce, проверки Referer и функции wp_verify_nonce. Вы получите готовые примеры для обычных форм и AJAX‑запросов, а также ссылки на полезные материалы по общей безопасности WordPress.

Что такое CSRF и как он работает

CSRF‑атака заставляет браузер жертвы отправить запрос к вашему сайту, используя её куки‑авторизацию. При этом пользователь может даже не подозревать о происходящем. Пример:

<img src="https://example.com/wp-admin/admin-ajax.php?action=delete_user&user_id=1" style="display:none">

Если в запросе не проверяется, что действие инициировано из доверенного источника, WordPress выполнит удаление пользователя.

  • Атака происходит без доступа к коду сайта.
  • Ключевая защита – проверка уникального токена (nonce) и/или заголовка Referer.

Защита с помощью nonce

WordPress предоставляет встроенный механизм nonce – одноразовый номер, привязанный к текущему пользователю и действию. Его проверка гарантирует, что запрос пришёл из вашего интерфейса.

Генерация nonce в форме

<form method="post" action=""> <input type="hidden" name="action" value="my_custom_action"> <?php wp_nonce_field( 'my_custom_action_nonce', 'my_nonce' );?> <input type="text" name="example"> <input type="submit" value="Отправить"> </form>

Функция wp_nonce_field() выводит скрытое поле _wpnonce (или имя, которое вы указали) со сгенерированным токеном.

Проверка nonce в обработчике

add_action( 'admin_post_my_custom_action', 'my_custom_action_handler' ); function my_custom_action_handler() { if (! isset( $_POST['my_nonce'] ) ||! wp_verify_nonce( $_POST['my_nonce'], 'my_custom_action_nonce' ) ) { wp_die( 'Недопустимый запрос – проверка CSRF не пройдена.' ); } // Основная логика обработки формы //... wp_redirect( home_url() ); exit; }

Если токен не совпадает, запрос будет отклонён, и злоумышленник не сможет выполнить действие.

Проверка Referer и дополнительные меры

Помимо nonce, стоит проверять заголовок Referer. WordPress уже делает это в некоторых функциях, но в пользовательском коде вы можете добавить дополнительный слой.

Пример проверки Referer

function my_verify_referer() { $referer = wp_get_referer(); $site_url = get_site_url(); if ( strpos( $referer, $site_url )!== 0 ) { wp_die( 'Неверный Referer – запрос отклонён.' ); } } add_action( 'admin_post_my_custom_action', 'my_verify_referer', 5 );

Эта проверка гарантирует, что запрос пришёл со страницы вашего сайта, а не с внешнего ресурса.

Для более глубокой защиты можно использовать плагины, которые внедряют AI‑анализ поведения и Bot Score, но базовый набор nonce + referer уже покрывает большую часть сценариев.

Защита AJAX‑запросов в WordPress

AJAX‑запросы часто используют метод POST без визуального формы, поэтому nonce передаётся в заголовке или в теле запроса.

Генерация nonce для JavaScript

function my_enqueue_scripts() { wp_enqueue_script( 'my-ajax-script', get_template_directory_uri(). '/js/my-ajax.js', array('jquery'), null, true ); wp_localize_script( 'my-ajax-script', 'myAjax', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'my_ajax_nonce' ), ) ); } add_action( 'wp_enqueue_scripts', 'my_enqueue_scripts' );

JavaScript‑часть

jQuery.post( myAjax.ajax_url, { action: 'my_ajax_action', security: myAjax.nonce, data: { /* ваши данные */ } }, function( response ) { console.log( response ); });

Обработчик AJAX с проверкой nonce

add_action( 'wp_ajax_my_ajax_action', 'my_ajax_handler' ); function my_ajax_handler() { check_ajax_referer( 'my_ajax_nonce', 'security' ); // бросит 403 при ошибке // Обрабатываем данные wp_send_json_success( array( 'msg' => 'Данные приняты' ) ); }

Функция check_ajax_referer() – сокращённый вариант wp_verify_nonce() специально для AJAX.

Для ускорения работы и снижения нагрузки рекомендуется кэшировать часто запрашиваемые результаты. Подробнее о кэшировании в WordPress читайте в статье MySQL кэширование WordPress.

Лучшие практики и выводы

Подводя итог, перечислим проверенные шаги, которые помогут обезопасить ваш сайт от CSRF:

  1. Всегда генерируйте nonce через wp_create_nonce() и проверяйте его функциями wp_verify_nonce() или check_ajax_referer().
  2. Добавляйте проверку Referer в критические обработчики, особенно если они вызываются без формы.
  3. Для публичных форм (комментарии, регистрация) используйте встроенные функции WordPress, они уже включают nonce.
  4. Не храните nonce в URL‑параметрах GET – они могут быть записаны в логах.
  5. Регулярно обновляйте ядро, темы и плагины: многие уязвимости CSRF фиксируются в новых версиях.

Если вы уже используете комплексные решения, такие как GRE‑туннель Cloudflare, дополните их базовой nonce‑защитой – это создаст многоуровневый барьер.

Следуя этим рекомендациям, вы значительно снизите риск успешных CSRF‑атак и сделаете ваш WordPress‑проект надёжнее.

❓ Часто задаваемые вопросы

Что такое CSRF и почему он опасен для WordPress?

CSRF – подделка запросов от имени авторизованного пользователя. Если запрос не проверяется, злоумышленник может изменить настройки, удалить контент или выполнить любые действия, доступные пользователю.

Как правильно генерировать и проверять nonce в WordPress?

Для генерации используйте wp_create_nonce() или wp_nonce_field(). Проверку выполняйте через wp_verify_nonce() в обработчике или check_ajax_referer() для AJAX.

Нужна ли проверка Referer, если уже используется nonce?

Да, дополнительная проверка Referer повышает уровень защиты, особенно в кастомных обработчиках, где nonce может быть пропущен или скомпрометирован.

Можно ли хранить nonce в GET‑параметрах URL?

Не рекомендуется, потому что такие токены могут попасть в серверные логи, рефереры и кэш браузера, что упрощает их кражу.