Полный цикл в digital

CSRF и SSRF уязвимости в Битрикс

CSRF и SSRF атаки представляют серьезную угрозу безопасности веб-проектов. Они позволяют выполнять нежелательные действия от имени пользователя или сервера.

CSRF-атака

CSRF (Cross-Site Request Forgery) межсайтовая подделка запроса. При этой атаке пользователь выполняет нежелательные действия на доверенном сайте, где он уже авторизован.

Принцип CSRF-атаки

  1. Пользователь авторизуется на сайте, cool-bank.com
  2. Браузер сохраняет cookie-файлы сессий
  3. Пользователя перенаправляют на вредоносный сайт, evil.com
  4. evil.com отправляет скрытую форму на cool-bank.com
  5. Браузер пользователя автоматически добавляет cookie авторизации
  6. cool-bank.com выполняет действие от имени пользователя

В примере используется форма, чтобы отправить запрос на перевод денег от имени пользователя:

<form action="https://cool-bank.com/sendmoney" method="POST">
  <input type="hidden" name="sendmoney" value="1000">
</form>  

Как защититься от CSRF

Существует два основных подхода, которые эффективно работают вместе: CSRF-токены и SameSite cookie.

CSRF-токены

CSRF-токен это секретное и непредсказуемое значение, которое сервер генерирует и передает пользователю. Пользователь включает токен в каждый запрос с авторизацией. Сервер проверяет токен перед выполнением действия.

Bitrix Framework предоставляет функции для работы с токенами.

bitrix_sessid ()

bitrix_sessid() возвращает CSRF-токен. Он является идентификатором сессии:

// feb8414592f24d96f6fd0c656e6ccd67
echo bitrix_sessid();
bitrix_sessid_post ()

bitrix_sessid_post() вставляет токен в форму:

// <input type="hidden" name="sessid" id="sessid" value="1bd24e8b34e32f1dc9d9463cf591729a" />
echo bitrix_sessid_post();
bitrix_sessid_get ()

bitrix_sessid_get() возвращает строку вида $varname=идентификатор_сессии для использования в GET параметрах, можно указать название параметра

// sessid=1bd24e8b34e32f1dc9d9463cf591729a
bitrix_sessid_get($varname='sessid')
check_bitrix_sessid ()

check_bitrix_sessid() проверяет, совпало ли значение bitrix_sessid с $varname из GET параметра или заголовка X-Bitrix-Csrf-Token:

check_bitrix_sessid($varname='sessid')

SameSite

SameSite это дополнительный атрибут для cookie. Он указывает браузеру, отправлять ли cookie в межсайтовых или внутрисайтовых запросах. Это обеспечивает частичную защиту от CSRF и других атак.

Безопасную cookie можно сделать двумя способами:

setcookie ():
setcookie('cookie_name', 'cookie_value', ['samesite' => 'Strict']);
\Bitrix\Main\HttpResponse:addCookie ()
$cookie = new Cookie("cookie_name", "cookie_value");
$cookie->setSameSite("Strict");
$context = Application::getInstance()->getContext();
$context->getResponse()->addCookie($cookie);

Атрибут SameSite может принимать следующие значения:

  1. None ограничения на файлы cookie не устанавливаются
  2. Strict cookie отправляются только в рамках одного домена и не передаются при переходах между разными сайтами
  3. Lax cookie передаются только при безопасных HTTP-запросах в межсайтовых переходах, но блокируются для небезопасных методов и при загрузке вложенных ресурсов

Установка атрибута SameSite=Strict для всех сookie может ухудшить пользовательский опыт, особенно при межсайтовых переходах. Например, если пользователь авторизуется на сайте, а затем переходит по внешней ссылке, сookie файлы не отправятся, и он окажется неавторизованным.

Атрибут SameSite=Lax более гибкий вариант, но его можно обойти, например, через GET запросы вместо POST или клиентские перенаправления.

Выбор между Strict и Lax зависит от типа сайта:

  1. Lax подходит для интернет-магазинов, где важна удобная навигация
  2. Strict предпочтителен для банковских приложений, где безопасность в приоритете

SSRF-атака

SSRF (Server-Side Request Forgery) подделка серверных запросов. Атака позволяет отправлять запросы от имени сервера.

$http = new HttpClient();
print_r($http->get($_GET['uri']));

В примере сервер напрямую обращается к произвольному адресу и выводит ответ на экран. Параметр uri может быть использован для доступа к внутренним сервисам.

Почему это опасно

Представьте, что на сервере работает служба на порте 1337. Доступ к службе закрыт для внешнего мира. Однако, если удастся отправить запрос от имени сервера, можно получить доступ к службе. Это позволит сканировать внутреннюю сеть или выполнять произвольный код.

Как защититься от SSRF

Для защиты от SSRF-атак ограничьте возможность отправки запросов к внутренним ресурсам. Это можно сделать с помощью встроенных механизмов Bitrix Framework.

Ограничение доступа к частным IP

Используйте метод setPrivateIp(false) в HTTP-клиенте, чтобы запретить запросы к частным адресам:

// создаем объект HTTP-клиента
$http = new HttpClient();
// запрещаем доступ к частным IP
$http->setPrivateIp(false);
// пытаемся отправить запрос
$http->get($_GET['uri']);

При попытке запроса к локальному адресу HTTP-клиент вернет ошибку.

Безопасная загрузка изображений

Используйте CFile::MakeFileArray() для безопасной загрузки изображений с удаленных хостов. Метод проверяет файл на корректность и предотвращает загрузку вредоносных данных:

$file = CFile::MakeFileArray($_GET['uri']);
if ($file) {
     $res = CFile::CheckImageFile($file);
     if ($res === null) {
         // Изображение корректно, можно продолжать
     } else {
         // Обработка ошибки
     }
}
Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!