Одноразові числа (nonce)
У вступі згадувалося, що для перевірки прав є два підходи: це «Перевірка прав користувача» і «Одноразові числа», що доповнюють цю перевірку.
«Одноразові числа» – це якийсь токен у WordPress – випадково створений рядок з 10 знаків, наприклад bec698e7ea
, який можна повторити протягом короткого проміжку часу (24 години). Тобто. створити і перевірити це число можна тільки протягом 24 години, після цього, та сама операція поверне вже інше «число».
Такі числа називаються в WordPress “Nonce” – “Number used ONCE” (число, що використовується 1 раз) і використовуються для додаткового захисту GET та POST запитів. Їх можна сприймайте як секретні прикмети, щоби переконатися, що дія санкціонована.
Докладніше див. опис функції wp_create_nonce()
Приклад роботи Nonce
Ми зайшли в адмінку, в налаштування, при заході згенерувалась форма, де одне з полів – це таке «nonce значення». Ми змінили дані та натиснули кнопку «зберегти». При обробці даних, крім перевірки прав доступу ( current_user_can() ) WordPress перевіряє чи сходиться nonce число. Якщо nonce не сходиться, запит на збереження даних провалиться.
Ми не помічаємо цих nonce перевірок, тому що зазвичай все відбувається швидко. Але якщо, наприклад, зайти на сторінку налаштувань в адмінку, почекати 24 години і тільки потім спробувати зберегти дані, то внесені зміни не збережуться, тому що перевірку не буде пройдено.
Навіщо потрібна перевірка «одноразовими числами»?
Уявімо, що неавторизований користувач без прав, знайшов вразливе місце в плагіні. Наприклад, він знає, що є таке посилання, натиснувши на яке адміністратор, сам не знаючи того, змінить якесь налаштування (опцію) на сайті, тому що потрібно хакеру. Наприклад, в налаштування запишеться хакерський javascript (зазначений у посиланні), який потім виконатиметься при відвідуванні іншої сторінки сайту цим же адміністратором.
Змусити щоб браузер адміністратора пройшов за таким посиланням, можна у різний спосіб.
Наприклад, створити сторінку та в ній використовувати такий код:
<img src="http://example.com/wp-admin/post.php?post=123&action=trash" />
Або, наприклад, написати лист адміністратору сайту, в який підсунути зовні невинне посилання…
Авторизований користувач (адмін), клікне за посиланням, і в результаті виконатися JS код хакера, який, наприклад, надішле дані авторизації. І ось колись неавторизований хакер став адміністратором вашого сайту.
Щоб, неможливо було виконати таку хитрість, існують «одноразові числа» (nonce захист).
Так як nonce число застаріває, то якщо додати це число в URL або параметр форми і потім перевіряти його, URL або форма будуть робітниками тільки 24 години. А потім запити створювані URL або формою просто не проходитимуть перевірку. Таким чином, якщо хакер змусить вас клікнути за відомим посиланням, то посилання швидше за все вже буде неробочим, тому що не пройде перевірку «одноразового числа».
Nonce Функції
Для управління одноразовими числами WordPress є спеціальні функції . Основні з них:
- wp_nonce_field( $action, $name )
- Створює вполе поле з одноразовим числом для форми.
- wp_create_nonce( $action )
- Просто створює одноразове число у вигляді рядка.
- wp_nonce_url( $url, $action )
-
Додає nonce до надісланої URL-адреси у вигляді параметра запиту
?_wpnonce=9d6bd884a1
- wp_verify_nonce( $nonce, $action )
- Перевіряє одноразове число.
- check_ajax_referer()
- Перевіряє Ajax запит на відповідність nonce коду. Обриває роботу скрипта через die, якщо перевірку не пройдено.
Приклад використання Nonce захисту
Це приклад з розділу перевірка прав користувача , тільки до нього додається ще й перевірка nonce.
При створенні посилання використовуємо wp_create_nonce() , щоб додати одноразове число до посилання:
// функція виводить посилання з nonce числом видалення запису function frontend_delete_link() { // Перевірка прав if( ! current_user_can( 'edit_others_posts' ) ) return; $url = add_query_arg( array( 'action' => 'frontend_delete', 'post' => get_the_ID(); 'nonce' => wp_create_nonce( 'nonce_frontend_delete' ), ), home_url(), ); printf( '<a href="%s">Видалити</a>', esc_url( $url ) ); }
Аргумент, що передається функції гарантує, що одноразове число є унікальним для даної конкретної дії.
Потім при обробці запиту перевіряємо одноразове число:
if ( isset( $_REQUEST['action'] ) && 'frontend_delete' === $_REQUEST['action'] ) { add_action('init','frontend_delete_post'); } function frontend_delete_post(){ // Перевіримо право if( ! current_user_can( 'edit_others_posts' ) ) return; // Перевіримо nonce if( ! wp_verify_nonce( $_REQUEST['nonce'], 'nonce_frontend_delete' ) ) return; // ID запису $post_id = ( isset( $_REQUEST['post'] ) ? get_post( (int) $_REQUEST['post'] ) : false; // ні ID запису if( empty( $post_id ) ) return; // Видаляємо запис wp_trash_post($post_id); // редирект в адмінку $redirect = admin_url('edit.php'); wp_safe_redirect ($ redirect); exit; }
Перевірка referer
Крім Nonce є ще перевірка referer. Вона доповнює nonce захист. Це незалежна перевірка і вона працює так: з форми передається параметр, де вказано HTTP_REFERER , при обробці форми цей параметр перевіряється і якщо запит прийшов не з очікуваної сторінки, то перевірка провалюється.
Для referer перевірки WordPress є 3 функції:
- wp_referer_field() – створює поле referer
- check_admin_referer() – перевіряє поле referer
- wp_nonce_field() – за замовчуванням створює ще referer поле для форми, разом із nonce полем.
Висновок
При виконанні будь-якої операції перетворення даних, наприклад, збереження налаштувань плагіна або видалення даних плагіна, завжди слід переконатися, що користувач має право здійснювати операцію (перевірка прав) і що запит не застарів (nonce перевірка).