На связи Юлия Полозкова, ведущий разработчик отдела архитектурных решений и перспективной разработки «БАРС Груп». Наша команда специализируется на создании бизнес-приложений для государственного и корпоративного сектора. В этой статье делюсь опытом, как обеспечить достаточный уровень кибербезопасности.
![](https://habrastorage.org/getpro/habr/upload_files/289/275/a00/289275a0061309cd3573866ff827adcf.png)
В частности, разбираю техники и средства защиты Graph API, такие как отключение интроспекции средствами HotChocolate, лимиты размеров запроса, его глубины вложенности и количества запрашиваемых объектов. Ведь если ваше приложение – публично доступный сервис, то одной аутентификацией не обойтись. Вам стоит задуматься о безопасности, защите данных и самого веб-сервиса от злоумышленников.
Давайте рассмотрим, что такое интроспекция, почему опасно оставлять ее включенной и как ее отключать. Также разберем дополнительные средства защиты.
Интроспекция или самоанализ
Интроспекция позволяет запрашивать у сервера GraphQL информацию о базовой схеме, например: типы данных, поля, запросы, мутации и описание самих полей. Запрос схемы – это такой же обычный графовский запрос, как и другие.
Пример базовой схемы одного из наших проектов:
![](https://habrastorage.org/getpro/habr/upload_files/160/766/9f8/1607669f8a53d027922a8b4aaa2cab6f.png)
Интроспекция полезна на стадии разработки, т.к. используется некоторыми инструментами, с которыми работают разработчики, например: GraphQL IDEs, GraphQL, Postman. GraphQL IDEs обычно применяет ее, чтобы помогать тестированию и диагностике схемы во время разработки, а GraphQL – для подсказок при наборе запросов и их валидации.
Интроспекция в производственном окружении
Как уже было упомянуто ранее, используя интроспекцию можно раскрыть конфиденциальные данные о вашем приложении. Например, описание поля, где может быть указана какая-то часть бизнес-логики, которая должна быть скрыта от посторонних глаз. Да и в целом, нежелательно раскрывать подробности того, что умеет ваш сервис всем подряд. Более того, сами запросы интроспекции могут быть громоздкими и расходовать много ресурсов сервера. И при этом, по умолчанию, они доступны без аутентификации. Именно поэтому стоит отключать интроспекцию в продакшене.
О том, какие атаки бывают на сервисы GraphQL можно почитать тут.
Как отключить интроспекцию
HotChocolate дает возможность гибко настраивать условия отображения схемы. Для начала рассмотрим, как отключить интроспекцию в вашем проекте. Для этого необходимо при подключении GraphQL вызывать метод AddIntrospectionAllowedRule(), что спрячет схему от всех запросов. Вот фрагмент кода из файла Program.cs
![](https://habrastorage.org/getpro/habr/upload_files/601/525/b5d/601525b5db26d127c07b780db2a87e48.png)
![](https://habrastorage.org/getpro/habr/upload_files/2e8/51c/83d/2e851c83d4e440df34bd7c6f85d3576d.png)
![](https://habrastorage.org/getpro/habr/upload_files/2c5/78d/e9d/2c578de9d7d6abf58efd3a83dda45f50.png)
Если нужно отключать схему по определенным условиям, надо создать свой обработчик запросов к GraphQL конфигурации и в нем определить условия, при которых будут доступны запросы интроспекции, например, проверять аутентифицирован ли пользователь:
![](https://habrastorage.org/getpro/habr/upload_files/d39/46d/033/d3946d033c8efa8fa3941d9751a4edac.png)
Также добавить кастомный обработчик после регистрации GraphQL сервера.
![](https://habrastorage.org/getpro/habr/upload_files/bb4/c3c/f91/bb4c3cf91103c38f0de163752e06972d.png)
Дополнительная защита GraphQL API
Широкие возможности GraphQL позволяют удобно работать с данными, получать только те из них, которые вам нужны. Но эта гибкость также несет в себе некоторые последствия для безопасности. Например, злоумышленник может создать дорогой запрос, который перегрузит сервер, базу данных, сеть или все это вместе взятое. Без правильной защиты система может подвергнуться DoS-атакам.
Рассмотрим пример, когда у приложения есть сущности, которые имеют ссылки друг на друга. Так, на картинке ниже сущность Package ссылается на PackageCategory, а PackageCategory – на Package.
![](https://habrastorage.org/getpro/habr/upload_files/9c9/b7f/b9a/9c9b7fb9a36278bfad9fe7d15f1c15e6.png)
![](https://habrastorage.org/getpro/habr/upload_files/14e/c50/0b4/14ec500b43d051fc7a9ef7ad6262a338.png)
В таком случае, можно написать бесконечной вложенности запрос, как показано на скриншоте ниже. Тут вложенность не слишком большая – 21 запрос, но выполнение запроса уже заняло 5 секунд:
![](https://habrastorage.org/getpro/habr/upload_files/77f/3bb/548/77f3bb5486bc84ee976c32d21dd72618.png)
Понятно, что подобный запрос увеличивает объемы запрашиваемых объектов экспонентно и может повлиять на работу сервера. Поэтому следует вводить ограничения на вложенность и размеры запросов.
Ограничение размеров запроса
Тут все просто – создается Middleware, который проверяет длину запроса. Можно ограничиться двумя тысячами байтов и, если запрос больше, то не пропускать его в дальнейшую обработку конвейером запросов.
![](https://habrastorage.org/getpro/habr/upload_files/694/68d/bab/69468dbab6784b29bb5f86cf5b07280c.png)
![](https://habrastorage.org/getpro/habr/upload_files/c0e/8ce/52d/c0e8ce52daa59639c89e6e76d9f349b9.png)
Однако этого недостаточно, ведь, если у приложения короткие названия полей, то все еще можно написать запрос с высокой вложенностью.
Ограничение вложенности запросов
HotChocolate дает возможность определять правила валидации запросов, в том числе и правило для вложенности запроса. Добавить их можно так же, как и правило интроспекции при подключении в проект GraphQL. Ниже добавляется валидация на вложенность не более пяти:
![](https://habrastorage.org/getpro/habr/upload_files/450/480/ad3/450480ad31eb751f025dada931c27c06.png)
При написании сложного запроса увидим такую ошибку:
![](https://habrastorage.org/getpro/habr/upload_files/39f/df0/022/39fdf0022bbe3ae3edc109d680357ab2.png)
Также можно создавать свои кастомные правила валидации сложности запросов, об этом более детально можно прочитать тут.
Ограничение количества запрашиваемых объектов
Еще один вредный для сервера аспект – это запрос большого количества объектов за раз. Такой запрос всегда будет дорогим и для базы данных, и для сети. Чтоб избежать подобных ситуаций, рекомендуется использовать атрибут «UseOffsetPaging» предоставляемый HotChocolate с параметром «MaxPageSize» у тех запросов, которые поддерживают пагинацию:
![](https://habrastorage.org/getpro/habr/upload_files/86f/fd8/1ee/86ffd81eece4785cda6ba0df3a468d49.png)
Благодаря этому атрибуту мы получим ошибку, если запросим больше 10 объектов:
![](https://habrastorage.org/getpro/habr/upload_files/4c8/01a/06c/4c801a06cc5503b034f82fcb1c03b26f.png)
Подытожим
GraphQL перспективная современная технология, которая позволяет быстрее разрабатывать веб-приложения, но всегда нужно помнить о безопасности. Перечисленные в статье механизмы обеспечения безопасности – это базовые механизмы, которые в совокупности дают достаточный уровень защиты вашего API.