- Вопрос или проблема
- Ответ или решение
- Надежный способ добавления nonce в HTTP-заголовок в WordPress
- Проблема с существующим решением
- Решение проблемы
- Шаг 1: Генерация nonce
- Шаг 2: Добавление заголовка Content Security Policy
- Шаг 3: Добавление nonce в теги <script>
- Шаг 4: Использование nonce в инлайн-скриптах
- Заключение
Вопрос или проблема
Я пытаюсь реализовать CSP на своем сайте WordPress.
Вдохновленный этим вопросом, https://stackoverflow.com/questions/50002041/adding-nonce-to-script-tag, я попытался найти способ добавить nonce на мой сайт WordPress.
add_action( 'run_custom_nonce_value', 'custom_nonce_value' );
function custom_nonce_value () {
$created_nonce = wp_create_nonce();
define( 'NONCE_RANDVALUE', $created_nonce );
}
Эта функция была взята напрямую из ссылке на Stackoverflow, упомянутой выше.
Она создавала значения nonce, используя wp_create_nonce()
Главная проблема в том, что она создает nonce, но не обновляет его. Обновление моего сайта WordPress по-прежнему показывает одно и то же значение nonce.
Может ли global $variable
быть лучшим вариантом вместо define?
В любом случае, после этого ниже приведенный код немного изменен и добавляет nonce в заголовки с помощью WP действий и добавляет nonce ко всем зарегистрированным скриптам.
add_filter( 'script_loader_tag', 'add_nonce_to_script', 10, 3 );
function add_nonce_to_script( $tag, $handle, $source ) {
custom_nonce_value();
$val_nonce = NONCE_RANDVALUE;
$search = "type=\"text/javascript\"";
$replace = "type=\"text/javascript\" nonce=\"".$val_nonce."\" ";
$subject = $tag;
$output = str_replace($search, $replace, $subject);
return $output;
}
function pagely_security_headers($headers) {
custom_nonce_value();
$val_nonce = NONCE_RANDVALUE;
$headers['X-Content-Security-Policy'] = "default-src 'self'; script-src unsafe-hashes 'self' https://milyin.com 'nonce-" . $val_nonce . "' https:; object-src 'none';base-uri 'none';img-src https: data:;style-src 'self' 'unsafe-inline' https:;report-uri https://milyin.com/?csp=true";
return $headers;
}
add_filter( 'wp_headers', 'pagely_security_headers' );
Итак, нам нужно решить 2 вещи.
1.) Он не обновляет значение nonce, обновление страницы и открытие новой вкладки по-прежнему используют одно и то же значение nonce, что подрывает всю цель nonce.
2.) Лучший способ вывести nonce в другом месте, так как я хочу, чтобы инлайновые скрипты, не зарегистрированные в WordPress, также имели nonce.
Также я прочитал, что CSP требует base64 nonce, являются ли эти nonce base64?
Я обратил внимание на ваши вопросы по поводу добавления nonce csp в скрипты WordPress. Пожалуйста, проверьте мои выводы
Я создал функцию в functions.php моей темы
//создание случайного nonce для заголовка script-src CSP
function generate_custom_nonce(){
$created_nonce = bin2hex(openssl_random_pseudo_bytes(32));
return wp_create_nonce($created_nonce);
}
В моем header.php я добавил код для заголовков и вызываю nonce всякий раз, когда это необходимо
$nonce=generate_custom_nonce();
header("Content-Security-Policy: script-src 'nonce-".$nonce."';");
<script type="text/javascript" nonce="<?php echo $nonce; ?>">
dosomething....
</script>
Этот метод был единственным и самым простым, который сработал для меня. Для встроенных js-кодов WordPress с помощью генератора хешей CSP добавил хешированный код в директиву script-src.
Ответ или решение
Надежный способ добавления nonce в HTTP-заголовок в WordPress
В контексте реализации политики безопасности контента (Content Security Policy, CSP) на вашем сайте WordPress важно обеспечить надежное использование nonce. Это позволит избежать многих уязвимостей, связанных с выполнением вредоносного кода. В данной статье мы рассмотрим, как динамически генерировать nonce и правильно добавлять его в HTTP-заголовок и теги <script>
.
Проблема с существующим решением
Вы правильно заметили, что функция, генерирующая nonce с использованием wp_create_nonce()
, не обновляется при каждом обновлении страницы. Это делает nonce статичным и неэффективным. Кроме того, использование define()
для хранения значения nonce ограничивает его область видимости и не подходит для динамического обновления.
Решение проблемы
Для правильного подхода мы будем использовать session
для хранения nonce, который будет обновляться при каждой загрузке страницы. Мы создадим следующие функции:
- Генерация нового nonce.
- Добавление nonce в заголовки.
- Добавление nonce в скрипты.
Шаг 1: Генерация nonce
Создадим функцию, которая будет генерировать и хранить nonce в сессии:
function start_nonce_session() {
if (!session_id()) {
session_start();
}
}
function generate_custom_nonce() {
start_nonce_session();
$_SESSION['nonce'] = bin2hex(openssl_random_pseudo_bytes(16));
return $_SESSION['nonce'];
}
Шаг 2: Добавление заголовка Content Security Policy
Теперь добавьте nonce в HTTP-заголовок:
function pagely_security_headers($headers) {
$val_nonce = generate_custom_nonce();
$headers['Content-Security-Policy'] = "default-src 'self'; script-src 'nonce-".$val_nonce."';";
return $headers;
}
add_filter('wp_headers', 'pagely_security_headers');
Шаг 3: Добавление nonce в теги <script>
Теперь, чтобы добавить nonce ко всем скриптам, используйте фильтр script_loader_tag
:
add_filter('script_loader_tag', 'add_nonce_to_script', 10, 3);
function add_nonce_to_script($tag, $handle, $source) {
if (isset($_SESSION['nonce'])) {
$val_nonce = $_SESSION['nonce'];
return str_replace('src', 'nonce="'.esc_attr($val_nonce).'" src', $tag);
}
return $tag;
}
Шаг 4: Использование nonce в инлайн-скриптах
Для инициализации и использования nonce в инлайн-скриптах, можно просто вывести его в шаблоне:
<script type="text/javascript" nonce="<?php echo esc_attr($_SESSION['nonce']); ?>">
// Ваши скрипты здесь
</script>
Заключение
Следуя представленным шагам, вы сможете надежно генерировать и использовать nonce в вашем WordPress сайте. Такой подход не только улучшит безопасность вашего ресурса, но и повысит его надежность благодаря динамической генерации значений nonce. Не забудьте протестировать вашу реализацию после всех изменений, чтобы убедиться, что не возникло новых уязвимостей.
Если у вас возникнут дополнительные вопросы или вам требуется помощь с настройкой, обратитесь к сообществу WordPress или профессионалам в области веб-разработки.