Безопасность в WordPress: esc_html(), wp_nonce_field(), защита от XSS/CSRF
Основы безопасности в WordPress
WordPress предоставляет множество функций для защиты от распространенных уязвимостей, таких как межсайтовый скриптинг (XSS) и подделка межсайтовых запросов (CSRF).
Защита от XSS (межсайтового скриптинг)
Функции экранирования (escaping)
- esc_html() — экранирует HTML-сущности:
echo esc_html($unsafe_string);
Преобразует <script>alert('xss')</script>
в <script>alert('xss')</script>
- esc_attr() — для атрибутов HTML:
echo '<input value="' . esc_attr($unsafe_value) . '">';
- esc_url() — для URL:
echo '<a href="' . esc_url($unsafe_url) . '">Link</a>';
- esc_js() — для JavaScript:
echo '<script>var data = "' . esc_js($unsafe_data) . '";</script>';
- wp_kses() — фильтрация HTML с разрешенными тегами:
$allowed_html = array(
'a' => array('href' => array(), 'title' => array()),
'br' => array(),
'em' => array(),
);
echo wp_kses($unsafe_html, $allowed_html);
Когда использовать:
- esc_html() — когда выводите текст, который не должен содержать HTML
- wp_kses() — когда нужно разрешить некоторые HTML-теги
- esc_attr() — всегда в атрибутах HTML-элементов
- esc_url() — для всех URL
Защита от CSRF (подделки межсайтовых запросов)
Nonce (Number Used Once) в WordPress
- wp_nonce_field() — создает скрытое поле в форме:
wp_nonce_field('my_action', 'my_nonce_field');
Выведет: <input type="hidden" id="my_nonce_field" name="my_nonce_field" value="a1b2c3d4e5">
- wp_create_nonce() — создает nonce для кастомного использования:
$nonce = wp_create_nonce('my_action');
- check_admin_referer() — проверяет nonce в админке:
check_admin_referer('my_action', 'my_nonce_field');
- check_ajax_referer() — для AJAX-запросов:
check_ajax_referer('my_action', 'nonce');
- verify_nonce() — ручная проверка:
if (!wp_verify_nonce($_POST['nonce'], 'my_action')) {
die('Security check failed');
}
Полный пример защиты формы
// В форме
<form method="post">
<?php wp_nonce_field('my_form_action', 'my_form_nonce'); ?>
<input type="text" name="username">
<input type="submit" value="Submit">
</form>
// При обработке формы
if (isset($_POST['my_form_nonce'])) {
if (!wp_verify_nonce($_POST['my_form_nonce'], 'my_form_action')) {
wp_die('Security check failed');
}
// Безопасная обработка данных
$username = sanitize_text_field($_POST['username']);
// ...
}
Лучшие практики безопасности
- Всегда проверяйте nonce для форм и AJAX-запросов
- Экранируйте все выходные данные перед выводом в браузер
- Санитайзите все входные данные перед использованием
- Используйте подготовленные SQL-запросы с $wpdb
- Ограничивайте права пользователей с current_user_can()
Пример защиты AJAX-запроса
// JavaScript
jQuery.post(ajaxurl, {
action: 'my_ajax_action',
data: 'some_data',
_ajax_nonce: my_script_vars.nonce // Передаем nonce
}, function(response) {
// Обработка ответа
});
// PHP
add_action('wp_ajax_my_ajax_action', 'handle_my_ajax');
function handle_my_ajax() {
check_ajax_referer('my_ajax_action', '_ajax_nonce');
$data = sanitize_text_field($_POST['data']);
// ...
wp_send_json_success($data);
}
Разница между санитайзингом и экранированием
- Санитайзинг (sanitization) — очистка входных данных перед сохранением в БД
$clean_input = sanitize_text_field($_POST['input']);
- Экранирование (escaping) — защита при выводе данных
echo esc_html($data_from_db);
Важные функции санитайзинга
- sanitize_text_field() — для текстовых полей
- sanitize_email() — для email-адресов
- sanitize_url() — для URL
- sanitize_key() — для ключей/слаг
- sanitize_html_class() — для HTML-классов
Соблюдение этих практик безопасности поможет защитить ваш WordPress-сайт от наиболее распространенных атак.