WordPress и CSRF защита: практическое руководство с nonce и проверкой referer
Введение
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:
- Всегда генерируйте nonce через
wp_create_nonce()и проверяйте его функциямиwp_verify_nonce()илиcheck_ajax_referer(). - Добавляйте проверку
Refererв критические обработчики, особенно если они вызываются без формы. - Для публичных форм (комментарии, регистрация) используйте встроенные функции WordPress, они уже включают nonce.
- Не храните nonce в URL‑параметрах GET – они могут быть записаны в логах.
- Регулярно обновляйте ядро, темы и плагины: многие уязвимости 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?
Не рекомендуется, потому что такие токены могут попасть в серверные логи, рефереры и кэш браузера, что упрощает их кражу.