Как защитить сайт с личными кабинетами от взлома: XSS, SQL-инъекции и ролевая модель

«Мой сайт взломали» — фраза, от которой у владельца бизнеса холодеет внутри. Слиты пароли клиентов, украдены данные, испорчена репутация. Для малого бизнеса это часто означает закрытие. Хорошая новость: большинства атак можно избежать, если изначально заложить правильную архитектуру и следовать базовым правилам.

В Falcon Space безопасность встроена на уровне ядра, но и вы сами можете многое сделать. Расскажу, от чего мы защищаем и как усилить защиту.

Основные угрозы для сайта с личными кабинетами

Для веб-приложений с авторизацией и передачей данных самые частые атаки:

Разберём, как платформа защищает от каждой угрозы и что ещё можете сделать вы.

Защита от SQL-инъекций: хранимые процедуры спасают

Классический веб-сайт часто строит SQL-запросы склеиванием строк: SELECT * FROM users WHERE id = ' + userId + '. Если злоумышленник передаст userId = 1 OR 1=1; DROP TABLE users; --, он может уничтожить базу данных.

В Falcon Space мы не конструируем запросы динамически из пользовательского ввода. Вся ваша бизнес-логика — это хранимые процедуры, которые вызываются с параметрами. Параметры строго типизированы и не могут быть интерпретированы как SQL-код. Это практически исключает SQL-инъекции на уровне приложения.

Пример процедуры (безопасно):

CREATE PROCEDURE [app].[get_user_by_id]
    @user_id int
AS
BEGIN
    SELECT * FROM users WHERE user_id = @user_id;
END

Даже если передать в @user_id строку '1; DROP TABLE users', SQL Server выдаст ошибку преобразования типов и ничего страшного не произойдёт.

Ваша задача: никогда не использовать динамическое выполнение SQL (sp_executesql с конкатенацией) внутри своих процедур. Пишите только параметризованные запросы.

Защита от XSS: экранирование вывода

XSS возникает, когда сайт выводит данные, введённые пользователем, без экранирования. Например, пользователь в поле «Имя» написал <script>alert('XSS')</script>, и этот код выполняется на страницах других пользователей.

В Falcon Space все данные, выводимые через стандартные компоненты (таблицы, формы), автоматически экранируются — теги превращаются в &lt; и &gt;. Но если вы выводите данные через свой HTML-код (например, в кастомном лендинге), то должны экранировать сами.

Для этого используйте функцию HtmlEncode в SQL-процедурах (платформа предоставляет такую возможность через внешнее действие или встроенные функции). Или, ещё проще, не позволяйте пользователям вводить HTML-теги вообще — добавьте валидацию.

У нас также есть глобальная настройка, которая фильтрует все пользовательские поля ввода, удаляя потенциально опасные теги. Рекомендуем её включить. Документация по XSS.

Ролевая модель: кто что видит

Одна из самых частых уязвимостей — пользователь с ролью «Клиент» может, подменив ID в URL, посмотреть данные другого клиента (например, /order/123 вместо /order/456).

В Falcon Space мы защищаемся двумя способами:

  1. На уровне страниц — каждой странице назначаются роли, которые имеют к ней доступ. Если пользователь не входит в эти роли, он увидит ошибку 403.
  2. На уровне данных — в SQL-процедурах вы всегда должны передавать @username текущего пользователя и фильтровать данные по нему. Например:
CREATE PROCEDURE [app].[get_my_orders]
    @username nvarchar(100)
AS
BEGIN
    SELECT * FROM orders WHERE customer_username = @username;
END

Таким образом, даже если злоумышленник догадается вызвать процедуру с чужим username, он не сможет (потому что @username подставляется системой автоматически из сессии, а не из запроса пользователя).

Важное правило: никогда не доверяйте параметрам, переданным с клиента, для идентификации пользователя. Всегда используйте внутренний @username.

Дополнительные меры, которые вы можете настроить сами

Платформа даёт инструменты, а вы их используйте:

Кейс: как мы защитили площадку от утечки данных

В одном из проектов (сервис для загородных домов) мы обнаружили, что заказчик в одной из кастомных процедур забыл фильтр по @username. В результате любой зарегистрированный пользователь мог, подставив order_id, посмотреть детали чужих заказов (адрес, телефон, стоимость). Это была серьёзная дыра.

Мы быстро исправили — добавили в процедуру условие:

AND customer_username = @username

Заодно написали скрипт, который проверил все процедуры на наличие такой уязвимости. В итоге нашли ещё 3 места с похожей проблемой. После исправления провели нагрузочное тестирование — скорость не упала.

С тех пор мы включили в наш чек-лист при сдаче проекта: проверка всех процедур, возвращающих данные, на фильтрацию по пользователю. Вы тоже можете попросить сделать такую проверку.

Что не может сделать платформа (и это ваша зона ответственности)

Некоторые аспекты безопасности зависят от вас:

Безопасность — это не тумблер «включить», а процесс. Но правильная архитектура решает 80% проблем. В Falcon Space она правильная.

Резюме:

Следуя этим правилам, вы будете защищены от 95% атак. А если сомневаетесь — напишите нам, проведём аудит безопасности вашего сайта.

Страница-источник на сайте falconspace.ru