Немного теории
Одно из важных неявных нефункциональных требований при разработке сайтов на платформе «1С-Битрикс: Управление сайтом» — требование к безопасности разработки. Создавая публичный объект ИТ-инфраструктуры, надо помнить, что вместе с тем появляются риски недобросовестного его использования.
Главное правило безопасности — не доверять пользовательским данным. Под “пользовательскими данными” понимаются не только данные, введенные посетителем сайта в input-поля форм, но и все остальное: отправляемые им файлы, куки, заголовки http. Более того, даже понятие “пользователь” нужно трактовать максимально широко — если сайт интегрирован с учетной системой и забирает оттуда товары, а из веб-сервиса банка получает курс валют — их данные тоже нужно проверять по всей строгости.
Рассмотрим самые распространенные способы атаки на веб-сайт.
SQL code injection
Самой опасной считается атака на базу данных. Если злоумышленник сможет повлиять на SQL-запрос, он сможет получить, испортить или уничтожить данные. Чтобы обезопасить свои данные от этой атаки, необходимо тщательно фильтровать все, что поступает в SQL-запросы. Такая фильтрация производится в рекомендуемых для работы с БД API-методах, поэтому в документации и всех обучающих материалах об этом постоянно напоминают. Потому что в противном случае, при самостоятельных запросах в базу, вопрос безопасности полностью перекладывается на разработчика.
Поэтому добавление данных в Инфоблоки, HL-блоки и ORM-сущности нужно производить с помощью официальных методов Add, Update, Delete и GetList.
Но не любой API-метод можно считать абсолютно безопасным. Среди них есть и внутренние, которые разработчики оставили для себя и для широкого применения они не пригодны:
CDatabase::Add
CDatabase::PrepareInsert
CDatabase::PrepareUpdate
CDatabase::PrepareUpdateBind
Особенность таких методов в том, как в них передаются данные. Защита будет производиться, если данные передавать по реальным ключам, и будет отключена, если передавать данные в ключах с тильдой в начале названия колонки БД. Поэтому нельзя взять сырой массив $_POST и передать в качестве аргумента в такой метод.
Похожая ситуация с SqlExpression, который позволяет расширить условия фильтрации в ORM. Это API-метод с описанной документацией, но его нужно грамотно использовать. Практический пример мы разбираем в видео к данному уроку.
В то же время, особенно в контексте повышения производительности, собственные запросы к БД имеют право на существование. Если иного решения нет, то разработчик должен использовать следующие методы для каждой переменной, которую собирается передать в SQL-запрос.
CDatabase::ForSql
Bitrix\Main\DB\SqlHelper::forSql
Межсайтовый скриптинг/XSS
Представьте стандартную форму технической поддержки на сайте. Посетитель может оставить обращение, описав свою проблему. Сотрудник техподдержки получает письмо с уведомлением и может в специальном разделе сайта ответить на обращение. Реализовать такой раздел в минимальном жизнеспособном виде достаточно просто даже без использования платформы на чистом PHP.
Но в конце текста обращения злоумышленник может открыть тег <script>
и
написать произвольный javascript-код. Например, похитить куки сотрудника техподдержки или
подменить часть контента страницы, чтобы увести сотрудника на другой сайт. Это и есть
XSS-атака или межсайтовый скриптинг.
Ни в коем случае нельзя полагаться на клиентскую валидацию данных. Даже если в браузере
написано правило, например, запрещающее вводить латинские символы, это правило можно
отключить в панели разработчика почти в любом браузере или обойти, отправив сырой
HTTP-запрос, минуя браузер. Поэтому под угрозой не только поля <textarea>
,
но и <select>
и все типы <input>
, в том числе и hidden
.
Если сайт защищен от такой атаки, то js-код не будет выполнен, а о попытке обмана будет создана запись в журнале безопасности. Если защиты нет, то любой код злоумышленника будет выполнен.
Также вместо тега <script>
злоумышленник может вставить ссылку <a>
на свой сайт, в надежде, что по неосторожности или из любопытства кто-либо перейдет по этой
ссылке. Тег <a>
может быть дополнен атрибутами onclick, onfocus и
подобными, в которых, опять же, будет javascript.
Для защиты от таких атак используются специальные функции PHP и платформы при сохранении данных в БД или при их выводе:
- Для удаления тегов из строки:
strip_tags, HTMLToTxt
. - Для защиты параметров в url:
urlencode
. - Для вывода html как текста:
htmlspecialchars, htmlentities, htmlspecialcharsEx, HtmlFilter::encode
.
Если заранее известно, что в том или ином поле будет храниться число — вместо обработки текста можно применить intval или приведение к int.
Позже, при выводе данных из БД, стоит помнить про разницу методов GetNext
и
Fetch
. Fetch
работает быстрее и достает данные ровно в том виде, в котором они хранятся в таблице.
GetNext
подвергает данные обработке и защищает html-символы строк. Поэтому
во многих
системных компонентах вы могли видеть в $arResult
дубли ключей, например, ~NAME
и NAME
.
Разница в том, что по ключу NAME
лежат обработанные безопасные данные, а в
~NAME
— “сырые”, ровно в том виде, в каком хранятся в БД.
CSRF
Можно заставить браузер обратиться к произвольному сайту без ведома самого пользователя. Например, прислав ему картинку, src которой будет вести в административный раздел сайта, на котором у него активна сессия администратора. В таком случае, так как браузер авторизован, любой такой GET-запрос без дополнительных проверок будет интерпретирован как осознанное действие пользователя.
В случае с GET-запросами обычно вреда нет, но есть способ спровоцировать и POST-запрос, а это уже серьезная проблема.
Чтобы быть уверенным, что входящий HTTP-запрос действительно отправлен текущим пользователем по его инициативе, в платформе существует способ “подписать” каждый запрос. В качестве подписи используется значение, основанное на коде сессии пользователя.
Во всех POST-формах требуется разместить вызов функции bitrix_sessid_post
, а
перед
обработкой формы достаточно вызова check_bitrix_sessid
, чтобы убедиться,
что в POST
содержится та самая подпись.
Открытые редиректы
Злоумышленники могут атаковать сайт не только с целью кражи или порчи данных непосредственно из его БД. Используя атаку типа “открытый редирект”, они могут похитить самого пользователя и увести его на свой сайт.
Посетители сайтов редко следят за адресной строкой браузера, поэтому, если в какой-то момент работы с сайтом их перенаправит на другой сайт, с точно таким же внешним видом, но другим URL, они этого могут не заметить и продолжать работу на нем, спокойно вводя пароль и персональные данные.
Чтобы таких перенаправлений не было, нужно защищаться от XSS. Во-вторых, нужно грамотно
использовать существующий в платформе механизм “Защита редиректов”. Вместо
прямых ссылок на другие сайты потребуется выводить ссылку вида
/bitrix/redirect.php?goto=<url>
(или /bitrix/click.php
,
/bitrix/rk.php
). Механизм “Защита
редиректов” сам найдет на страницах гиперссылки и добавит к ним подпись,
GET-параметр af, который станет меткой, что редирект выполняется осознанно и с
разрешения платформы. В противном случае пользователь увидит предупреждение, что он
уходит на другой сайт.
Особые угрозы
Переходя от общих угроз к частным, хотим отметить важность внимательного обращения с
методом CAgent::AddAgent
. Данный метод создает в планировщике PHP-задание,
которое будет
выполнено, когда сработает таймер. Первый аргумент name данного
метода — полноценная строка кода, которая будет выполнена с помощью функции PHP
eval()
. Не существует универсальной функции, которая бы проверила значение
этого
аргумента и избавила его от кода злоумышленника, поэтому мы можем только дать
рекомендацию никогда не создавать агенты на основании данных, полученных от
пользователя.
Проактивная защита
Все инструменты, относящиеся к продвинутой предиктивной защите сайта от злоумышленников, собраны в платформе в модуле Проактивная защита. Обязательные для самостоятельного изучения инструменты:
Сканер безопасности
Проверяет код и настройки платформы и составляет отчет, насколько безопасен сайт в текущем виде.Проактивный фильтр
Набор специализированных средств, которые выполняют фильтрацию трафика. Например, заметив в пользовательских данных тег <script> именно проактивный фильтр заменит его на строку <sc ript>. Фильтр можно настроить, чтобы он не мешал там, где такая бдительность может нарушить работу пользователей, но в большинстве случаев его действия оправданы.Защита редиректов
О которой мы уже рассказали ранее в этом уроке.Защита сессий
Позволяет перенести хранение сессий из файлов в БД и настроить частоту смены идентификаторов сессий. Частая смена идентификатора существенно затрудняет атаку на сайт, но может сказаться и на UX пользователя.Контроль активности
Способ борьбы с ботами и DDoS-атаками, защищает от чрезмерно активных пользователей, программных роботов, и попыток подбора паролей перебором.Журнал вторжений
Хранит логи всех событий, связанных с модулем.
Практика
В этом видеоуроке продемонстрируем несколько распространенных уязвимостей веб-приложений и рассмотрим средства защиты при их эксплуатации.
Большинство примеров будут показаны на компонентах, работающих с новой сущностью “Уведомления”, с которой мы познакомились в предыдущем уроке.
НЕ РАЗМЕЩАЙТЕ МАТЕРИАЛЫ ЭТОГО УРОКА В РАБОЧИХ ПРОЕКТАХ И НА ПУБЛИЧНЫХ ВЕБ-СЕРВЕРАХ!
Материалы содержат специально подготовленные примеры с грубыми ошибками в безопасности, которые будут продемонстрированы и исправлены в ходе урока.
Никогда не размещайте эти материалы в рабочих проектах и, тем более, на публичных веб-серверах. Используйте их только для обучения в рамках вашего личного учебного проекта на локальном веб-сервере.
Безопасность
45 мин
Полезные ссылки и материалы
- Немного теории: уязвимости
- CDatabase::ForSql
- SqlHelper::forSql
- CDatabase::PrepareInsert
- CDatabase::PrepareUpdate
- SqlExpression
- htmlspecialcharsEx
- HtmlFilter::encode
- HTMLToTxt
- bitrix_sessid_post
- check_bitrix_sessid
- Защита редиректов
- CAgent::AddAgent
- Проактивная защита. Описание модуля
- Проактивная защита