====== Правила безопасности для авторов плагинов ====== Создание [[wiki:plugins|плагинов]] для DokuWiki очень просто даже для начинающих [[wiki:devel:plugins|программистов]] PHP. Чтобы убедиться, что ваш плагин не ставит под угрозу безопасность всей вики, на которой он установлен, вам следует следовать рекомендациям, изложенным на этой странице. :!: Улучшение этой страницы всегда приветствуется. Она находится в очень сыром состоянии и должна быть расширена более подробной информацией, ссылками и примерами. ===Краткое содержание=== Список наиболее распространенных проблем безопасности и способы их избежания можно найти на этой странице. Краткое резюме: * Межсайтовый скриптинг (XSS) — вставляет вредоносный код на веб-сайт для манипулирования сайтом в браузере пользователя. * Подделка межсайтовых запросов (CSRF) — уловки, позволяющие вам совершать неосознанные вредоносные действия на вашем сайте. * Удаленное включение кода – включает код на сервере, который там выполняется. * Утечка информации – отображается слишком много информации * SQL-инъекция – можно выполнить нежелательные запросы к вашим данным Также добавлено примечание о [[#reporting Security Issues|необходимости сообщать о проблемах безопасности ]]. ===== Межсайтовый скриптинг (XSS) ===== Это, вероятно, самая распространенная уязвимость, встречающаяся в плагинах DokuWiki. Cross Site Scripting относится к атаке, при которой вредоносный код JavaScript внедряется на веб-сайт. Это может использоваться для перенаправления невинных пользователей на вредоносные веб-сайты или для кражи аутентификационных cookie-файлов. Механизм плагинов DokuWiki дает разработчикам плагинов большую гибкость. В случае с плагинами синтаксиса, в частности, фреймворк дает плагинам возможность работать с сырым необработанным выводом. Это означает, что данные страницы вики, которые достигают вашего плагина, вообще не были обработаны. И не будет никакой дальнейшей обработки вывода после того, как он покинет ваш плагин. ===Выход из режима экранирования=== Как минимум, плагин должен гарантировать, что все выходные необработанные данные будут содержать все специальные символы HTML , преобразованные в сущности HTML с помощью функции [[phpfn>htmlspecialchars()]]. DokuWiki предоставляет удобный ярлык [[xref>hsc()]] для этой функции. Значения URL-адресов следует экранировать с помощью [[phpfn>rawurlencode()]]. Кроме того, следует с подозрением относиться к любым данным вики, извлеченным и используемым внутри компании (например, именам пользователей). ===Проверка входных данных=== Всегда проверяйте все ваши входные данные. Используйте белые списки, фильтры, преобразования в точный тип данных, который вы имеете в виду, например, из числа, введенного как смешанное значение php, в целое число и т. д., чтобы убедиться, что у вас есть __только__ разрешенные вами данные. Также ознакомьтесь с нашей главой об обработке [[wiki:devel:request_vars|переменных запросов]], таких как ''_GET'', ''_POST'' или ''_SERVER''. ==Смотрите также:== * [[wp>Cross-site scripting|Межсайтовый скриптинг]] * FIXME[[http://ha.ckers.org/xss.html|Шпаргалка по XSS]] ==== Типичные примеры уязвимостей ==== Ниже показаны некоторые очень распространенные проблемы. Примеры очень просты, чтобы сделать общую проблему понятной. Ваш плагин, вероятно, сложнее, но вам нужно отслеживать те же уязвимости. === Синтаксис Тела === Многие простые плагины синтаксиса принимают часть введенных пользователем данных и форматируют их в виде пользовательского HTML . Пример: Вот плагин сокращенного синтаксиса, позволяющий выделить заданный ввод жирным шрифтом. class syntax_plugin_bold extends DokuWiki_Syntax_Plugin { // общие функции плагина опущены public function connectTo($mode) { $this->Lexer->addSpecialPattern('!!!.*?!!!', $mode, 'plugin_bold'); } public function handle($match, $state, $pos, Doku_Handler $handler){ return [substring($match, 3, -3)]; } public function render($format, Doku_Renderer $renderer, $data) { if($format != 'xhtml') return false; $renderer->doc .= '' . $data[0] . ''; // без экранирования } } Как вы можете видеть, необработанные входные данные, захваченные в шаблоне лексера, просто передаются в метод рендеринга, где экранирование вообще не выполняется. Злонамеренные пользователи могут вводить любой код JavaScript и HTML , который они хотят. Решение простое: правильный побег. class syntax_plugin_bold extends DokuWiki_Syntax_Plugin { // общие функции плагина опущены public function connectTo($mode) { $this->Lexer->addSpecialPattern('!!!.*?!!!', $mode, 'plugin_bold'); } public function handle($match, $state, $pos, Doku_Handler $handler){ return [substring($match, 3, -3)]; } public function render($format, Doku_Renderer $renderer, $data) { if($format != 'xhtml') return false; $renderer->doc .= '' . htmlspecialchars($data[0]) . ''; //экранирование } } === Формы === Когда ваш плагин предоставляет форму, очень часто требуется проверить вводимые данные и повторно отобразить форму с полученными данными пользователя в случае возникновения ошибки проверки. Пример: ниже показана форма, уязвимая для атаки XSS, поскольку она не экранирует правильно введенные пользователем данные:
//без экранирования
Предоставление данных ''%%">%%'' в качестве входных данных пользователя приведет к эксплуатации уязвимости. Для исправления формы используйте функцию [[phpfn>htmlspecialchars|htmlspecialchars()]] или функцию DokuWiki shortcut [[wiki:xref:hsc|hsc()]]:
//экранирование
В целом рекомендуется не создавать формы вручную, а использовать [[wiki:devel:form|библиотеку форм]] DokuWiki . === Классы и другие атрибуты === Часто плагины принимают несколько параметров и опций, которые используются для изменения выходных данных плагина. Представьте себе плагин, принимающий следующие входные данные для отображения окна сообщения: Do not believe anything! В методе рендеринга этого синтаксиса может быть такой код: $renderer->doc .= '
' //$class может быть чем угодно . htmlspecialchars($message) . '
';
Как вы видите, само сообщение правильно экранировано, но класс — нет. Вместо экранирования может быть разумнее использовать белый список разрешенных классов с резервным вариантом по умолчанию:: $allowed = ['notice', 'info', 'warning', 'error']; // белый список if(!in_array($class, $allowed){ $class = 'notice'; // неизвестный ввод, вернуться к разумному значению по умолчанию } $renderer->doc .= '
' . htmlspecialchars($message) . '
';
===входные URL-адреса === Когда плагин принимает URL-адреса в качестве входных данных, необходимо убедиться, что пользователи не смогут передать ''%%javascript://%%'' псевдо-протокол. Вот пример того, как может выглядеть очень простая проверка, позволяющая убедиться, что используются только URL-адреса http и https. // пустой URL при несоответствии протокола if(!preg_match('/^https?:\/\//i', $url)) { $url = ''; } ===== Подделка межсайтовых запросов (CSRF) ===== Эта уязвимость часто появляется в плагинах из-за отсутствия понимания этой проблемы, ее часто путают с XSS. Подделка межсайтовых запросов относится к атаке, при которой вредоносный сайт обманывает браузер жертвы, запрашивая страницу на уязвимом сайте для выполнения нежелательного действия. Атака предполагает, что браузер жертвы имеет учетные данные для изменения чего-либо на уязвимом сайте. ===Добавление токена безопасности=== DokuWiki предлагает функции, которые помогут вам бороться с атаками CSRF. [[https://codesearch.dokuwiki.org/xref/dokuwiki/inc/common.php?r=&mo=3231&fi=116#116|getSecurityToken()]] создаст токен, который следует использовать для защиты любого аутентифицированного действия. Он должен быть включен в ссылки или формы, запускающие это действие. Все формы, созданные с помощью [[wiki:devel:form|библиотеки форм]] будут иметь автоматически добавленные токены безопасности, для форм, созданных вручную, можно использовать функцию [[https://codesearch.dokuwiki.org/xref/dokuwiki/inc/common.php?r=&mo=4438&fi=157#157|formSecurityToken()]]. Вы как автор плагина несете ответственность за фактическую проверку токена перед выполнением авторизованных действий с использованием функции [[https://codesearch.dokuwiki.org/xref/dokuwiki/inc/common.php?r=&mo=3783&fi=133#133|checkSecurityToken()]]. ==See also== * [[wp>Cross Site Request Forgery|Подделка межсайтовых запросов]] * [[https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29|Объяснение OWASP]] ==== Типичный пример уязвимости ==== Ниже приведен простейший пример для начала. У вас может быть более сложный плагин для защиты, вот простой пример на основе формы. Представьте, что вы хотите узнать что-то, на что можно ответить «Да» или «Нет», у вас получится форма такого типа:
Затем вы обрабатываете эту форму следующим образом: global $INPUT; if($INPUT->get->has('yn')){ do_something_with_yn($INPUT->get->str('yn')); } Итак, пользователь подключен, чтобы ответить на этот вопрос, но он пока не знает ответа. Давайте уделим время размышлениям и просмотрим веб-страницы… Теперь пользователь посещает вредоносный веб-сайт, который знает или нет, что пользователь может быть подключен к вашему DokuWiki. На этом веб-сайте разработчик включил этот HTML- тег изображения: Что тогда будет делать браузер пользователя? Браузер обработает это изображение как любое другое и отправит запрос на этот URL . Ваш плагин увидит, что ''$_GET['yn']'' установлено, и вызовет ''do_something_with_yn()'' функцию. Это один из примеров CSRF. Теперь, как исправить эту дыру в безопасности? ==== Предотвращение CSRF-атак ==== Помните вашу форму выше? Давайте добавим в нее ввод:
Видите первый ввод? Да? Хорошо. Теперь вам нужно проверить токен безопасности при получении формы, перед ее обработкой: global $INPUT; if($INPUT->get->has('yn') && checkSecurityToken()) { do_something_with_yn($INPUT->get->str('yn')); } Поскольку вредоносный веб-сайт никогда не найдет значение скрытого ввода «sectok», ваша форма больше не уязвима для CSRF. **Примечание**: Если токен безопасности недействителен, ''checkSecurityToken()'' функция отображает сообщение, информирующее пользователя. ===== Удаленное включение кода ===== Эта атака позволяет злоумышленнику внедрить код (PHP) в ваше приложение. Это может произойти при включении файлов или использовании небезопасных функций операций, таких как [[phpfn>eval()]] или [[phpfn>system()]]. **Всегда фильтруйте любые входные данные**, которые будут использоваться для загрузки файлов или которые передаются в качестве аргумента внешним командам. ===== Утечка информации ===== Эта атака может привести к раскрытию файлов, которые обычно должны быть защищены ACL DokuWiki , или может раскрыть файлы на сервере (например, ''/etc/passwd''). **Всегда фильтруйте любые входные данные,** которые будут использоваться для загрузки файлов или которые передаются в качестве аргумента внешним командам. **Всегда используйте функции проверки ACL DokuWiki при доступе к данным страницы.** ===== SQL-инъекция ===== Эта атака редко актуальна в DokuWiki, поскольку база данных не используется. Однако, если ваш плагин обращается к базе данных, всегда экранируйте все значения перед их использованием в операторах SQL. Дополнительная информация: * [[wp>SQL injection|SQL-инъекция]] ===== Сообщение о проблемах безопасности ===== Если у вас возникли проблемы с плагином, сообщите об этом автору плагина по электронной почте, при желании указав [[andi@splitbrain.org|Andi]] or the [[wiki:mailinglist|список рассылки]] on CC. Дополнительно к [[wiki:lugin:repository|данным]] на странице плагина ''securityissue'' следует добавить поле с кратким описанием проблемы . Это создаст красное предупреждающее поле и исключит плагин из основного списка плагинов. После устранения проблемы и выпуска новой версии это поле следует снова удалить.