Подтвердить что ты не робот

Как предотвратить вложенную атаку на сервер GraphQL/Apollo?

Как предотвратить вложенную атаку на сервер Apollo с запросом, например:

{
  authors {
    firstName
    posts {
      title
      author {
        firstName
        posts{
          title
          author {
            firstName
            posts {
              title
              [n author]
                [n post]
            }
          }
        }
      }
    }
  }
}

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

4b9b3361

Ответ 1

На момент написания статьи на GraphQL-JS или Apollo Server нет встроенной функции для решения этой проблемы, но это должно иметь определенное решение, так как GraphQL становится более популярным. Эта проблема может быть решена несколькими подходами на нескольких уровнях стека и всегда должна сочетаться с ограничением скорости, чтобы люди не могли отправлять слишком много запросов на ваш сервер (это также потенциальная проблема с REST).

Я просто перечислил все различные методы, о которых я могу думать, и я постараюсь обновить этот ответ, поскольку эти решения реализованы на разных серверах GraphQL. Некоторые из них довольно просты, а некоторые более сложны.

  • Проверка запроса. На каждом сервере GraphQL первым шагом к выполнению запроса является проверка - это то, где сервер пытается определить, есть ли какие-либо серьезные ошибки в запросе, чтобы мы могли избегайте использования реальных ресурсов сервера, если мы обнаружим, что есть синтаксическая ошибка или недопустимый аргумент вверх. GraphQL-JS поставляется с набором правил по умолчанию, которые соответствуют формату, очень похожим на ESLint. Точно так же, как есть правило для обнаружения бесконечных циклов в фрагментах, можно написать правило проверки для обнаружения запросов со слишком большим количеством вложенности и отклонить их на этапе проверки.
  • Тайм-аут запроса. Если невозможно обнаружить, что запрос будет слишком ресурсоемким, статически (возможно, даже мелкие запросы могут быть очень дорогими!), тогда мы можем просто добавить тайм-аут к выполнение запроса. У этого есть несколько преимуществ: (1) это трудный предел, который не слишком сложно рассуждать, и (2) это также поможет в ситуациях, когда один из бэкэндов требует неоправданно долго реагировать. Во многих случаях пользователь вашего приложения предпочел бы отсутствующее поле, ожидающее более 10 секунд, чтобы получить ответ.
  • Белые списки запросов. Это, вероятно, самый привлекательный метод, но вы можете заранее составить список разрешенных запросов и проверить все входящие запросы на этот список. Если ваши запросы полностью статичны (вы не создаете динамических запросов на клиенте с помощью чего-то вроде Relay), это самый надежный подход. Вы можете использовать автоматизированный инструмент для вытягивания строк запроса из своих приложений, когда они развернуты, так что в процессе разработки вы пишете все запросы, которые хотите, но в производстве пропускаются только те, которые вы хотите. Другим преимуществом такого подхода является то, что вы можете полностью пропустить проверку запроса, так как вы знаете, что все возможные запросы уже действительны. Для получения дополнительных преимуществ от статических запросов и "белых списков" прочитайте этот пост: https://dev-blog.apollodata.com/5-benefits-of-static-graphql-queries-b7fa90b0b69a
  • Ограничение стоимости запроса: (добавлено в редактирование). Подобно таймаутам запросов, вы можете назначить затраты на различные операции во время выполнения запроса, например запрос базы данных, и ограничить общую стоимость клиента может использовать для каждого запроса. Это можно комбинировать с ограничением максимального parallelism одного запроса, так что вы можете помешать клиенту отправлять то, что инициирует тысячи параллельных запросов на ваш сервер.

(1) и (2), в частности, вероятно, что-то, что каждый сервер GraphQL должен иметь по умолчанию, тем более, что многие новые разработчики могут не знать об этих проблемах. (3) будет работать только для определенных видов приложений, но может быть хорошим выбором, если есть очень строгие требования к производительности или безопасности.

Ответ 2

Чтобы добавить точку (4) в ответ stubailo, вот несколько реализаций Node.js, которые налагают границы затрат и глубины на входящие документы GraphQL.

Это настраиваемые правила, которые дополняют фазу проверки.

Ответ 3

Изменение белого списка запросов подписание запроса.

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

Преимущество перед "белым списком" заключается в том, что написание запросов в клиенте не требует каких-либо изменений на сервере. Это особенно ценно, если несколько клиентов обращаются к одному и тому же серверу (например, к веб-приложениям, настольным и мобильным приложениям).