Blazor Server — как правильно защитить события?

В документации Microsoft «Руководство по устранению угроз для ASP.NET Core Blazor Server», раздел «События» говорится: «События предоставляют точку входа в приложение Blazor Server. Те же правила защиты конечных точек в веб-приложениях применяются к обработке событий в приложениях Blazor Server. Злоумышленник может отправлять любые данные, которые он хочет отправить, в качестве полезной нагрузки для события».

Пожалуйста, помогите мне понять это. Предположим, что мы находимся на сервере Blazor (НЕ в веб-сборке), имеется основная идентификация ASP.Net, и все страницы Blazor защищены тегами @attribute [Authorize] или <AuthorizeView...>. Итак, аутентификация и авторизация на месте, но дополнительно нам нужно убедиться, что определенные пользователи видят только определенные данные из базы данных.

случай №1, компонент Blazor с параметром

Этот параметр предоставляется родительской страницей. При загрузке компонента выполняется вызов базы данных для выборки данных на основе параметра:

[Parameter] public Guid companyGuid { get; set; }

protected override async Task OnInitializedAsync()
{
    using var context = DataService.CreateDbContext();
    var company = await DataService.GetCompanyByGuid(companyGuid, context);
}

случай № 2, раскрывающийся список показывает значение выбора для выбора

Источник данных представляет собой список, предварительно заполненный на основе разрешений пользователей. Когда срабатывает событие изменения раскрывающегося списка, данные извлекаются из базы данных на основе нового выбора:

<RadzenDropDown Data=@DataSourceCompanies TValue="Company" 
@bind-Value="@selectedCompany"
Change="@(args => CompanySelectionChanged(args as Company))" />

List<Company> DataSourceCompanies = await GetCompaniesAndObserveUserPermissions(userGuid);

async void CompanySelectionChanged(Company c)
{
    using var context = DataService.CreateDbContext();
    var company = await DataService.GetCompanyByGuid(c.guid, context);
}

Вопрос: Может ли пользователь изменить либо [Параметр] в случае 1, либо выбранный элемент в раскрывающемся списке в случае 2 не по назначению?

Другими словами, нужно ли мне дополнительно защищать запрос к базе данных «GetCompanyByGuid», делая что-то вроде этого:

var authState = await authenticationStateTask;
string? userId = authState.User.FindFirst(c => c.Type.Contains("nameidentifier"))?.Value;
var company = await DataService.GetCompanyByGuid(c.guid, userId, context);

(а затем используйте идентификатор пользователя внутри запроса к базе данных, чтобы дополнительно защитить запрос)

Хотя это звучит «более безопасно» для меня, это кажется действительно громоздким. В приложении есть сотни мест, где выполняются вызовы базы данных. Я хотел бы подтвердить, действительно ли необходим этот дополнительный код?

Спасибо!

Я читал документацию Microsoft, но не совсем понял, что там написано. Пробовал режим отладки браузера для проверки приложения, я вижу там только HTML/CSS (как и ожидалось). Никаких внутренних данных приложения, которые позволили бы мне изменить поведение приложения, не видно, например. гиды компании. Но я слишком новичок в SignalR, поэтому, вероятно, все еще есть способ злоупотребить этим. Отсюда мой вопрос.

На сервере Blazor в браузере не запускается код C#. Однако у браузера есть подключение SignalR к серверу, где события пользовательского интерфейса, созданные на клиенте, передаются обратно коду C#, работающему на сервере. Вам или вашей организации необходимо изучить уровни безопасности, предоставляемые SignalR, чтобы решить, соответствует ли он вашим требованиям безопасности. Здесь вам никто не ответит на этот вопрос. Существуют способы применения политик безопасности к каждому вызову в конвейере данных, но они сопряжены со значительными накладными расходами.

MrC aka Shaun Curtis 21.11.2022 00:35
Шаблоны Angular PrimeNg
Шаблоны Angular PrimeNg
Как привнести проверку типов в наши шаблоны Angular, использующие компоненты библиотеки PrimeNg, и настроить их отображение с помощью встроенной...
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Если вы веб-разработчик (или хотите им стать), то вы наверняка гик и вам нравятся "Звездные войны". А как бы вы хотели, чтобы фоном для вашего...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Начала с розового дизайна
Начала с розового дизайна
Pink Design - это система дизайна Appwrite с открытым исходным кодом для создания последовательных и многократно используемых пользовательских...
Шлюз в PHP
Шлюз в PHP
API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.
14 Задание: Типы данных и структуры данных Python для DevOps
14 Задание: Типы данных и структуры данных Python для DevOps
проверить тип данных используемой переменной, мы можем просто написать: your_variable=100
1
1
55
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вопрос: Может ли пользователь изменить [Параметр] в случае 1

Состояние пользователя хранится в памяти сервера по цепи. Примеры состояния пользователя, хранящегося в канале, включают:

  • Иерархия экземпляров компонентов и их самые последние выходные данные рендеринга в визуализируемом пользовательском интерфейсе.
  • Значения полей и свойств в экземплярах компонентов.

Поэтому для изменения информации о пользователе необходимо иметь доступ к оперативной памяти сервера, и переживать по этому поводу не стоит.

Для временных данных, которые пользователь активно создает, обычно используемым местом хранения являются коллекции браузера localStorage и sessionStorage:

  • localStorage ограничивается окном браузера. Если пользователь перезагружает страницу или закрывает и снова открывает браузер, состояние сохраняется. Если пользователь открывает несколько вкладок браузера, состояние распределяется между вкладками. Данные сохраняются в localStorage до тех пор, пока они не будут удалены явным образом.
  • sessionStorage ограничивается вкладкой браузера. Если пользователь перезагружает вкладку, состояние сохраняется. Если пользователь закрывает вкладку или браузер, состояние теряется. Если пользователь открывает несколько вкладок браузера, каждая вкладка имеет свою собственную независимую версию данных.

Сторонние пакеты NuGet предоставляют API для работы с localStorage и sessionStorage. Стоит подумать о выборе пакета, который прозрачно использует ASP.NET Core Data Protection. Защита данных шифрует сохраненные данные и снижает потенциальный риск подделки сохраненных данных.

Для получения дополнительной информации вы можете обратиться к Управление состоянием ASP.NET Core Blazor , а также Хранилище браузера (localStorage/sessionStorage)

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

Параметры компонента не могут быть закрытыми, это вызывает ошибку компилятора -> ошибка BL0004: параметр компонента «xxx.companyGuid» должен быть общедоступным.

Robert R 21.11.2022 14:37
Ответ принят как подходящий

Я собираюсь ответить на свой вопрос после того, как попрошу помощи у профессионального веб-тестера. Я думаю, что лучшее обобщение моего вопроса - «это зависит».

Давайте возьмем пример раскрывающегося списка и проанализируем его шаг за шагом:

Предположим, у нас есть список из 5 компаний в базе данных, идентифицированных с помощью Guid. 3 компании должны быть видны пользователю в пользовательском интерфейсе.

Определите раскрывающийся список для 3 компаний с помощью следующего фрагмента кода Blazor:

Это приводит к следующему коду HTML (и уже должно дать представление о том, как этим можно злоупотреблять):

Когда пользователь выбирает один из элементов раскрывающегося списка, в коде С# запускается «CompanySelectionCallback».

Так как же этим можно злоупотреблять? Открыв инструменты разработчика F12 в браузере и заменив одно из значений параметра на Guid одной из скрытых компаний:

Проанализировав это в прокси-инструменте, мы теперь можем увидеть измененный Guid, отправленный на сервер:

Поэтому в этом случае требуется дополнительная защита кода от злонамеренной модификации.

Теперь рассмотрим тот же пример, но вместо выбора используйте компонент RadzenDropDown из библиотеки Radzen Blazor. Сгенерированный html выглядит иначе:

Нет Guid, который можно изменить, единственное, что мы видим в нашем прокси-инструменте, это eventHandlerId:

Глубоко внутри AspNetCore этот eventHandlerId сопоставляется с фактическим идентификатором компании:

Поскольку в этот список внутреннего сопоставления входят только те компании, которые представлены пользователю, злонамеренный доступ к данным из других объектов компании невозможен.

Следовательно, в этом случае код достаточно защищен от модификации посредством внешнего взаимодействия.

Надеюсь, что этот анализ правильный и поможет другим.

Другие вопросы по теме