Как правильно валидировать данные из $_GET или $_REQUEST с помощью функций WordPress?

12 сент. 2012 г., 19:17:16
Просмотры: 18.7K
Голосов: 8

Я работаю над плагином, который требует динамического управления выводом контента. Это полностью зависит от текущей переменной $_GET или $_REQUEST.

В зависимости от значения переменной будет вызываться определенный метод класса для обработки запроса пользователя и вывода соответствующего контента.

Я полностью ознакомлен со страницей Валидации данных в WordPress Codex, однако не уверен, какой подход будет лучшим для моего сценария или любого другого случая санитизации переменных $_GET или $_REQUEST.

Как я могу санитизировать строку из переменной $_GET или $_REQUEST с помощью функций WordPress, если эта строка будет использоваться для вызова определенного метода класса?

Может ли этот код быть уязвимым для атак или вызвать ошибки?:

public function display_admin_page(){
    if(is_admin() && isset($_GET['page'])){
        global $content;
        $page = sanitize_title($_GET['page']);
        $method_name = 'page_'.str_replace('-', '_', $page);
        if(method_exists('content', $method_name)){
            // Отображаем запрошенную страницу из класса content
            $thePage = $content->$method_name();
        } else{
            $thePage = $content->error(404);    
        }
        echo $thePage;
    }
}
0
Все ответы на вопрос 4
1

WordPress не предоставляет специфических функций для валидации данных в SUPERGLOBALS.

Я использую PHP функцию filter_input, а затем экранирую её, как и любую другую ненадёжную переменную.

$url = filter_input( INPUT_GET, 'some_query_string', FILTER_VALIDATE_URL );

echo '<a href="'. esc_url( $url ). '">Нажми на меня</a>';

PHP функция filter_input принимает:

12 сент. 2012 г. 19:33:57
Комментарии

@Chris_0, как насчёт запросов $_GET? Например, filter_var( $_GET[ $item['name'] ], FILTER_SANITIZE_FULL_SPECIAL_CHARS ). Нужно ли это реализовывать как-то по-другому?

Motivated Motivated
30 окт. 2022 г. 10:12:17
2

Для вашего конкретного примера:

Вы правильно санировали данные $_GET (хотя я бы использовал sanitize_key вместо sanitize_title — нельзя сказать, что разница существенная, но sanitize_title предназначен для использования в URL).

Функция method_exists вернет true для private и protected методов, поэтому если пользователь попытается вызвать private или protected метод, это приведет к ошибке без перехода на 404 страницу. (Если только метод display_admin_page не находится в том же классе.)

Это подводит нас к главной потенциальной уязвимости: абсолютно любой может заставить выполнить любой public метод в вашем классе. По возможности всегда лучше явно указывать белый список допустимых методов. Таким образом, валидацию можно выполнить примерно так:

if ( !in_array( $_GET['page'], array( 'accepted_method', 'another_accepted_method' ) ) )
     $content->error(404);
12 сент. 2012 г. 22:22:47
Комментарии

Не могли бы вы подробнее рассказать о теории потенциальной уязвимости?

Michael Ecklund Michael Ecklund
13 сент. 2012 г. 17:15:11

Конечно, это то, о чем нужно подумать. Каждый публичный метод в вашем классе может быть вызван кем угодно в любое время. Это не автоматически делает его уязвимостью, но это важный момент для рассмотрения. Есть ли в вашем классе метод, который удаляет данные из базы? Есть ли метод, который выводит пароли пользователей? Будете ли вы добавлять другие методы, о которых нужно беспокоиться? И так далее.

SeventhSteel SeventhSteel
14 сент. 2012 г. 16:23:01
2

Я рекомендую использовать mysql_real_escape_string($_GET) для любых GET-запросов. Это очень мощная функция PHP.

Затем вы можете использовать str_replace() для замены нежелательных символов.

ОБНОВЛЕНИЕ 2023:

esc_sql() - это идеальное решение.

12 сент. 2012 г. 19:26:06
Комментарии

Разве функция WordPress esc_sql() не является лучшим выбором?

gillespieza gillespieza
10 февр. 2023 г. 12:55:04

@gillespieza конечно, это так, но в 2012 году эта функция была лучше. Это ответ 11-летней давности :)

Ciprian Ciprian
10 февр. 2023 г. 15:17:58
0

Санізація $_GET дуже залежить від контексту. Залежно від того, яке значення ви очікуєте і як воно має бути перевірене.

Немає універсальної відповіді на це питання. Все дуже залежить від контексту. Наприклад, ви можете написати функцію, яка видаляє всі теги та слеші з вхідних даних – це дуже безпечно, але що, якщо ви хочете зберегти тег <p>? У цьому немає нічого поганого. Сімейство функцій wp_kses() є цікавим прикладом, але це не найкраще рішення, оскільки воно враховує контекст, рівень користувача та інше. Наприклад, адміністратор може зберігати JavaScript у заголовках та вмісті записів, а користувачі з нижчим рівнем доступу – ні.

Якщо значення відоме заздалегідь, ви також можете перевірити, чи in_array( $array_valid_strings ), щоб бути впевненим ще більше.

Тобто, існують різні ступені санізації, тому важливо тримати кінцеву мету на увазі. Я б радив звернутися до цього списку і знайти функцію або комбінацію функцій, які відповідають вашим потребам. Саме функції sanitize_ слід використовувати в цьому випадку, а не esc_. Плутанина між санізацією та екрануванням продовжується...

У моєму випадку я використовуватиму sanitize_text_field(), оскільки вона санізує рядок, отриманий від користувача або з бази даних.

  • Перевіряє на наявність недійсного UTF-8,
  • Перетворює одиничні символи < на сутності
  • Видаляє всі теги
  • Видаляє розриви рядків, табуляції та зайві пробіли
  • Видаляє октети

Удачі :).

P.S. Ця відповідь цитує погляди трьох різних розробників (Джош, Міхал, Кевін).

11 окт. 2016 г. 21:19:29