Безопасность WordPress (или любой) веб-сайт является многогранной проблемой. Самый важный шаг, который каждый может предпринять, чтобы убедиться, что сайт является безопасным, чтобы иметь в виду, что ни один процесс или метод не является достаточным, чтобы обеспечить ничего плохого не происходит. Но есть вещи, которые вы можете сделать, чтобы помочь. Один из них должен быть на вахте, в коде, который вы пишете, и коде других, который вы развертываете, для функций, которые могут иметь негативные последствия. В этой статье мы рассмотрим именно те функции, которые разработчик WordPress должен ясно продумать перед использованием.
WordPress сам обеспечивает значительную библиотеку функций, некоторые из которых могут быть опасны. Помимо этого, Есть много функций PHP, что WordPress (PHP) разработчик будет использовать с некоторой частотой, которые могут быть опасны при использовании.
Все эти функции имеют законное и безопасное использование, но они также являются функциями, которые могут облегчить использование кода в плохих целях. Мы рассмотрим вещи, которые, скорее всего, являются причиной уязвимости безопасности, и почему вы должны следить за ними. Мы сначала запустить вниз ФУНКЦИи PHP в вашем коде, что плохие актеры могут использовать для зла, а затем говорить о WordPress конкретных функций PHP, которые также могут вызвать головную боль.
ФУНКЦИи PHP, чтобы остерегайться
Как мы уже говорили, PHP содержит много простых в использовании функций. Некоторые из этих функций печально известны легкостью, с которой люди могут делать плохие вещи с ними. Все эти функции имеют надлежащее использование, но будьте осторожны, как вы используете их и как другой код, который вы тянете в проект делает.
Мы собираемся предположить, что у вас уже есть магические котировки и регистрировать глобальные выключены, если ваша версия PHP поддерживает их. Они были выключены по умолчанию в PHP 5 и вверх, но могут быть включены для версий ниже 5.4. Немногие хосты разрешили это, но я не думаю, что статья безопасности PHP действительно полна без их включения.
Или упоминание о том, что PHP 5.6 является последней версией 5.x все еще с постоянной поддержкой безопасности. Вы должны быть на нем, по крайней мере. И вы должны иметь план, чтобы перейти на PHP 7 до 5,6 поддержка заканчивается в конце 2018 года.
После этого, вы просто некоторые рискованные функции для решения. Начиная с…
extract
Плохая новость, особенно на $_POST
или аналогичные
К счастью, использование extract
функции PHP в значительной степени упал в немилость. Суть его использования заключалась в том, что вы могли запускать его на массиве данных, и его пары ключей-ценности стали бы живыми переменными в коде. Сооо
$arr = array(
'red' => 5
);
extract($arr);
echo $red; // 5
будет работать. Это здорово, но это также очень опасно, если вы извлечения $_GET
$_POST
, и т.д. В этих случаях вы по существу воссоздаете register_globals
проблему самостоятельно: внешний злоумышленник может легко изменить переменные значения, добавив строку запроса или поле формы. Лучшее решение простое: не используйте extract
.
Если вы создаете массив, который вы извлекаете сами, это не проблема безопасности в extract
использовании, а в некоторых случаях, это может быть полезно. Но все виды его использования имеют проблему запутанной будущих читателей. Создание массива и вызова extract
является более запутанным, чем просто объявление переменных. Поэтому я призываю вас делать ручные декларации вместо этого, если это совершенно неосуществимо.
Если вы должны использовать extract
на входе пользователя, вы всегда должны использовать EXTR_SKIP
флаг. Это все еще имеет проблему запутанности, но оно получает освобожданным от возможности что ваши preset значения могут быть изменены злонамеренным аутсайдером через просто строку запроса или изменение формы паутины. (Потому что он «пропускает» уже установленные значения.)
«Это eval
зло», потому что произвольный код страшно
eval
в PHP и почти любой другой язык, который несет его всегда высоко в списках, как это. И не зря. Официальная документация PHP о PHP.net говорит, что это довольно откровенно:
ВНИМАНИЕ: Конструкция языка eval() очень опасна, потому что позволяет выполнять произвольный код PHP. Таким образом, его использование не рекомендуется. Если вы тщательно проверили, что нет другого выбора, кроме как использовать эту конструкцию, обратите особое внимание, чтобы не передавать в нее данные, предоставленные пользователем, без надлежащей проверки их заранее.
eval
позволяет запускать любую произвольную строку в вашей программе, как будто это код PHP. Это означает, что это полезно для «мета-программирования», где вы строите программу, которая может сама построить программу. Это также очень опасно, потому что если вы когда-нибудь позволить произвольных источников (например, текстовый ящик на веб-странице), которые будут переданы сразу же eval
строки оценщика, вы вдруг сделал это тривиально легко для злоумышленника, чтобы сделать почти все, что PHP может сделать на вашем сервере. Это включает в себя, очевидно, подключение к базе данных, удалять файлы, и почти все, что кто-то может сделать, когда SSHed в машину. Это плохо.
Если вы должны использовать eval
в программе, вы должны изо ставить перед собой дорогу, чтобы убедиться, что вы не позволяете произвольного пользовательского ввода, которые будут переданы в нее. И если вы должны разрешить произвольный доступ пользователей к входным eval
данным, ограничить то, что они могут сделать через черный список команд вы не позволяете им работать, или (лучше, но гораздо труднее реализовать) белый список, который только команды вы считаете безопасными. Более того, допускаются только небольшое количество конкретных изменений параметров, например, только проверенные целые числа.
Но всегда имейте в виду эту строку от Расмуса Лердорфа, основателя PHP:
«Если «eval()» является ответом, вы почти наверняка задаете неправильный вопрос».
Вариации наeval
Есть, в дополнение к хорошо известным eval
, целый ряд других способов, что PHP исторически поддерживает строки-оценки, как код. Два, которые являются наиболее актуальными для разработчиков WordPress preg_replace
с /e
модификатором, и create_function
. Каждый работает немного по-разному, и preg_replace
после PHP 5.5.0 не работает вообще. (PHP 5.5 и ниже больше не получают официальных обновлений безопасности, и, таким образом, лучше не использовать.)
/e
Модификаторы в Regex также «зло»
Если вы работаете PHP 5.4.x или ниже, вы хотите, чтобы следить за PHP preg_replace
звонки, которые заканчиваются с e. Это может выглядеть следующим:
$html = preg_replace(
'((.*?)>)e',
'"" . strtoupper("") . ">"',
$html
);)
// or
$html = preg_replace(
'~(.*?)>~e',
'"" . strtoupper("") . ">"',
$html
);)
PHP предлагает различные способы «забор» в вашем регулярном выражении, но основное, что вы хотите быть начеку является «е», как последний символ первого аргумента preg_replace
. Если он есть, вы на самом деле прохождения весь найденный сегмент в качестве аргумента в ваш рядный PHP, а затем eval
ING его. Это имеет точно такие же вопросы, как eval
если бы вы позволяете пользователь-вход идти в вашу функцию. Пример кода можно заменить вместо этого с помощью preg_replace_callback
. Преимущество этого заключается в том, что вы выписали свою функцию, так что злоумышленнику труднее изменить то, что получает оценку. Таким образом, вы бы написать выше, как:
// uppercase headings
$html = preg_replace_callback(
'((.*?)>)',
function ($m) {
return "" . strtoupper($m[2]) . "$m[1]>";
},
$html
);
Сдача пользователя ввода create_function
s также плохо …
PHP также имеет create_function
функцию. Это в настоящее время амортизированы в PHP 7.2, но это было очень похоже eval
и имел те же основные недостатки: он позволяет строку (второй аргумент), который будет превращен в исполняемый PHP. И это было те же риски: это слишком легко для вас, чтобы случайно дать умный взломщик возможность делать что-либо на вашем сервере, если вы не были осторожны.
Это одно, если вы на PHP над 5.3, то даже легке для того чтобы зафиксировать чем preg_replace
однако. Вы можете просто создать свою собственную функцию анонимного без использования строк в качестве посредников. Это и более безопасным и более читаемым, по крайней мере на моих глазах.
assert
Является также eval
-как
assert
это не функция, я вижу, многие разработчики PHP использовать, в WordPress или за ее пределами. Его цель заключается в очень легком утвержденияо о предварительных условиях для вашего кода. Но он также поддерживает eval
операцию типа -типа. По этой причине, вы должны быть осторожны с ним, как вы eval
. Строка основе утверждений (сердце, почему это плохо) также deprecated в PHP 7.2, что означает, что она должна быть меньше беспокойства в будущем.
Включение переменных файлов является способом возможного разрешения неконтролируемого исполнения PHP
Мы очень хорошо изучили, почему eval
это плохо, но что-то вроде include
или require($filename'.php')
может, особенно там, где $filename
устанавливается из пользовательского контролируемого значения, быть так же плохие новости. Причина тонко отличается от eval
. Переменные имена файлов часто используются для таких вещей, как простой URL-файл для разгрома в приложениях, не входящих в WordPress PHP. Но вы можете увидеть их, используемых в WordPress, а также.
Суть проблемы, что, когда вы include
require
include_once
(или) вы делаете ваш require_once
скрипт выполнить включен файл. Это, более или менее, концептуально eval
ING, что файл, хотя мы редко думаем об этом таким образом.
Если вы написали все файлы, которые include
может вытащить переменная, и рассмотрели, что произойдет, когда это произойдет, вы в порядке. Но это плохая новость, если вы не рассмотрели то, что include
ING password.php
или будет wp-config.php
делать. Это также плохая новость, если кто-то может добавить вредоносный файл, а затем выполнить ваш include
(хотя в этот момент вы, вероятно, имеют большие проблемы).
Решение этого не слишком трудно, хотя: жесткий код включает в себя, когда вы можете. Если вы не можете, иметь либо белый список (лучше) или черный список файлов, которые могут быть включены. Если файлы в белом списке (то есть: вы проверили, что он делает при добавлении), вы будете знать, что вы в безопасности. Если его нет в вашем белом списке, ваш скрипт не будет включать его. С этой простой настройки, вы довольно безопасно. Белый список будет выглядеть примерно так:
$white_list = [‘db.php’, filter.php’, ‘condense.php’]
If (in_array($white_list, $file_to_include)) {
include($file_to_include);
}
Никогда не передавайте пользовательский вход shell_exec
и варианты
Это большой. shell_exec
, system
exec
, и backticks в PHP все позволяют код, который вы работаете, чтобы поговорить с основной (обычно Unix) оболочки. Это похоже на то, что делает eval
опасным, но в два раза. Удвоено, потому что если вы позволяете пользователю ввода через здесь небрежно, злоумышленник даже не связан ограничениями PHP.
Возможность запуска команд оболочки phP может быть очень полезной в качестве разработчика. Но если вы когда-нибудь позволить пользователь вход там, они имеют возможность тайно получить много опасных полномочий. Так что я бы пойти так далеко, чтобы сказать, что пользовательский вход никогда не должны быть переданы shell_exec
функции типа.
Лучший способ, который я мог бы думать, чтобы справиться с такого рода ситуации, если у вас было искушение реализовать его, было бы предоставить пользователям доступ к небольшой набор известных-безопасных предопределенных команд оболочки. Это можно было бы обеспечить. Но даже тогда я предупреждаю вас быть очень осторожными.
Смотреть для unserialize
; Он запускает код автоматически
Основное действие вызова serialize
на живой объект PHP, хранение этих данных где-то, а затем с помощью этого сохраненного значения позже, unserialize
чтобы этот объект обратно к жизни прохладно. Это также достаточно часто, но это может быть рискованно. Почему рискованно? Если вход в этот unserialize
вызов не является полностью безопасным (скажем, он хранится как файл cookie, а не в базе данных…), злоумышленник может изменить внутреннее состояние объекта таким образом, чтобы unserialize
заставить вызов сделать что-то плохое.
Этот подвиг является более эзотерическим и менее вероятно, будет замечен, чем eval
вопрос. Но если вы используете файл cookie в качестве механизма хранения серийных данных, не используйте serialize
эти данные. Используйте что-то вроде json_encode
и json_decode
. С этими двумя PHP никогда не будет автоматически выполнять любой код.
Основная уязвимость здесь заключается в том, что, когда PHP unserialize
s строку в класс, он называет магический __wakeup
метод на этом классе. Если допускается непроверенный пользовательский unserialized
вход, то что-то вроде вызова базы данных или удаления файлов в __wakeup
методе потенциально может быть направлено на опасное или нежелательное место.
unserialize
отличается от eval
уязвимостей, поскольку требует использования магических методов на объектах. Вместо того, чтобы создавать свой собственный код, злоумышленник вынужден злоупотреблять уже написанными методами на объекте. И __destruct
__toString
магические методы на объектах также являются рискованными, как это oWASP Вики страница объясняет.
В общем, вы в порядке, если вы не используете __wakeup
__destruct
, или __toString
методы в ваших классах. Но поскольку позже вы можете увидеть, что кто-то добавит их в класс, это хорошая идея, чтобы никогда не позволять пользователю рядом с вашими звонками serialize
и unserialize
передавать все общедоступные данные для такого использования, хотя что-то вроде JSON json_encode
json_decode
(и) где никогда не бывает автоматического выполнения кода.
Получение URL-адресов с file_get_contents
рискованным
Распространенная практика при быстром написании некоторых КОД PHP, который должен вызвать внешний URL, заключается в том, чтобы file_get_contents
достичь. Это быстро, это легко, но это не супер безопасно.
Проблема с file_get_contents
тонким, но это достаточно часто, что хосты иногда настроить PHP даже не позволяют получить доступ к внешним URL-адресам. Это должно защитить тебя.
Проблема здесь заключается в том, что file_get_contents
будет получать удаленные страницы для вас. Но когда он делает это, он не проверяет целостность соединения протокола HTTPS. Это означает, что ваш сценарий потенциально может стать жертвой атаки «человек в середине», которая позволит злоумышленнику вложить в результат вашей страницы практически все, что он file_get_contents
хочет.
Это более эзотерическая атака. Но для защиты от него, когда я пишу современный (композитор основе) PHP, я почти всегда использую Guzzle обернуть более безопасной CURL API. В WordPress, это еще проще: использовать wp_remote_get
. Он работает гораздо более последовательно, чем file_get_contents
, и это будет по умолчанию для проверки SSL соединений. (Вы можете переключить, что покинуть, но, гм, может быть, не …) А еще лучше, но немного больше wp_safe_remote_get
раздражает говорить о, есть и т.д. Они работают одинаково, чем функции без safe_
их имени, но они будут убедиться, что небезопасные перенаправления и препровождения не произойдет на этом пути.
Не доверяйте слеповали URL-адрес отfilter_var
Так что это один немного неясным, так реквизит Для Криса Вейгмана для объяснения его в этом WordCamp говорить. В целом, PHP filter_var
является отличным способом для проверки или дезинфекции данных. (Хотя, не путайте, о которых вы пытаетесь сделать …)
Проблема здесь довольно конкретна: если вы пытаетесь использовать ее для обеспечения безопасности URL-адреса, filter_var
не проверяется протокол. Это не часто проблема, но если вы проходите пользовательский вход в этот метод для проверки, и используют FILTER_VALIDATE_URL
, что-то вроде javascript://comment%0aalert(1)
будет пройти. То есть, это может быть очень хорошим вектором для основной атаки XSS в месте, которое вы не ожидаете.
Для проверки URL-адреса функция WordPress esc_url
будет иметь аналогичное воздействие, но пропускает только разрешенные протоколы. javascript
Однако, в отличие filter_var
от, он вернет пустую строку (не ложную) для запрещенного протокола, который передается ей.
WordPress-специфические функции, чтобы держать глаз на
В дополнение к основной PHP потенциально уязвимых функций, Есть некоторые WordPress конкретных функций, которые могут быть немного gotcha. Некоторые из них очень похожи на различные опасные функции, перечисленные выше, некоторые немного отличаются.
WordPress Unserializes сmaybe_unserialize
Это одно вероятно очевидно если вы читаете выше. В WordPress есть функция называется maybe_unserialize
и, как вы догадались, он unserializes то, что прошло к нему, если это необходимо.
Там нет какой-либо новой уязвимости, что это вводит, проблема заключается в том, что так же, как основная unserialize
функция, это может привести к уязвимому объекту, который будет использоваться, когда он unserialized.
is_admin
Не отвечает, если пользователь является администратором!
Это один довольно простой, но функция неоднозначна по названию, и поэтому он склонен путать людей или быть пропущены, если вы в спешке. Вы всегда должны проверить, что пользователь, который пытается выполнить действие в WordPress имеет права и привилегии, необходимые для выполнения этого действия. Для этого следует использовать эту current_user_can
функцию.
Но вы можете, ошибочно, думаю, что is_admin
будет сказать, если вы текущий пользователь является администратором уровня учетной записи и, таким образом, должны быть в состоянии установить опцию плагин использует. Это ошибка. Что is_admin
делает в WordPress вместо говорю вам, если текущая загрузка страницы находится на административной стороне сайта (против передней стороны). Таким образом, каждый пользователь, который может получить доступ к странице администрирования (например, «Dashboard») сможет потенциально пройти эту проверку. До тех пор, как вы is_admin
помните, что о типе страницы, а не текущего пользователя, вы будете в порядке.
add_query_arg()
Не дезинфицировать URL-адреса
Это не так часто, но была большая волна обновлений в экосистеме WordPress несколько лет назад, потому что публичная документация по этим функциям не была правильной. Основная проблема заключается в том, что add_query_arg
функция (и ее обратная) remove_query_arg
не автоматически дезинфицировать URL-адрес сайта, если URL не был передан ему, и люди думали, что он сделал. Многие плагины были введены в заблуждение Кодексом, и в результате использовали это небезопасно.
Основное, что они должны были сделать по-другому: дезинфицировать результат вызова к этой функции, прежде чем использовать его. Если вы сделаете это, вы действительно в безопасности от XSS атак, что вы думали, что они были. Так что это выглядит примерно так:
echo esc_url( add_query_arg( 'foo', 'bar' ) );
$wpdb->query()
Открыт для атаки на инъекцию СЗЛ
Если вы знаете о инъекциях S’L,это может показаться глупым, даже лишним для списка. Потому что дело в том, что любой способ получить доступ к базе данных (скажем, с помощью драйверов базы данных PHP mysqli
или PDO) для создания запросов базы данных, которые позволяют для атак инъекций S’L.
Причина, по которой я специально призывая $wpdb->query
в том, что некоторые другие методы (например, insert
и delete
т.д.) на $wpdb
заботиться о инъекционных атак для вас. Кроме того, если вы привыкли к созданию основных запросов базы данных WordPress WP_Query
с или аналогичными, вам не нужно будет рассматривать инъекцию S’L. Вот почему я призываю его: чтобы убедиться, что вы понимаете, инъекционные атаки на базу данных возможно, когда вы впервые попытаетесь использовать, $wpdb
чтобы сделать свой собственный запрос.
Что делать? Используйте, $wpdb->prepare()
а затем $wpdb->query()
. Вы также хотите, чтобы убедиться, что вы готовите перед другими «получить» $wpdb
методы, get_row()
как, и get_var()
. В противном случае Бобби таблицы могут получить вас.
esc_sql
Не защищает вас от инъекций S’L либо
Для большинства разработчиков WordPress, я бы сказал, что esc_sql
не регистрируется с какой-либо смысл, но он должен. Ase мы только что упомянули, вы должны wpdb->prepare()
использовать, прежде чем сделать какой-либо запрос базы данных. Это будет держать вас в безопасности. Но это заманчиво и понятно, что разработчик может достичь esc_sql
вместо этого. И они могут ожидать, что это будет безопасно.
Проблема заключается esc_sql
в том, что не имеет как надежные средства защиты от инъекций S’L. Это действительно прославленная версия add_slashes
функции PHP,которую вы не рекомендуется использовать для защиты вашей базы данных в течение многих лет.
Там еще многое сделать, но это большой старт
Безопасность может быть намного больше, чем просто поиск функций в коде, которые злоумышленники могут неправильно использовать. Мы, например, не обсуждали, например, необходимость проверки и дезинфекции всех данных, которые вы получаете от пользователей и избежать его, прежде чем положить его на веб-страницу (хотя я недавно опубликовать статью на эту тему, «Защита Вашего WordPress сайта против Кросс-сайт Сценарий атаки«). Но вы можете и должны использовать это как часть более широкой стратегии безопасности.
Ведение этого списка простых в использовании функций на вашей стороне, как вы делаете окончательный осмотр перед развертыванием нового плагина в WordPress это отличная идея. Но вы также хотите, чтобы убедиться, что вы доверяете безопасности вашего хостинга, убедитесь, что ваши пользователи имеют хорошие пароли, и многое другое.
Основная вещь, чтобы помнить о безопасности является то, что ваше самое слабое звено является тот, который имеет значение. Надводная практика в одной области укрепляет возможные слабые места где-то в другом месте, но они никогда не смогут полностью исправить это. Но будьте бдительны этих функций, и вы будете иметь ногу на большинстве.
Источник: smashingmagazine.com