- Определение и использование GraphQL API
- Макетирование GraphQL API для атак
- Векторы атак на GraphQL API
- Аутентификация и авторизация
- Отказ в обслуживании из-за рекурсии
- Уязвимости во вторичных контекстах (secondary contexts)
- Является ли GraphQL менее безопасным, чем REST API?
- Проверки безопасности GraphQL API в Invicti
В мире, где доминирует REST, GraphQL представляет собой совершенно иной подход к проектированию и запросам к API. GraphQL был разработан в Facebook в 2012 году как специализированный интерфейс для NoSQL баз данных, он представляет собой переход от запросов, управляемых операциями, к запросам, управляемым данными. По сравнению с работой с REST API, возможность запрашивать и получать только определенный набор данных является фундаментальным изменением, как и работа с одним API интерфейсом.
Типичный REST API предоставляет отдельный интерфейс для каждой операции, которую он выполняет, и его пользователи ограничены вызовом одного из доступных интерфейсов с поддерживаемыми параметрами и работой с любыми данными, которые он возвращает. Если интерфейс, который бы точно соответствовал потребностям, отсутствует, придётся извлекать информацию из доступных результатов. Это может привести к увеличению накладных расходов с точки зрения производительности и пропускной способности, так как приложение будет вынуждено получать больше данных, чем ему нужно, только для того, чтобы отбросить часть из них.
С другой стороны, обращение к интерфейсу GraphQL похоже на выполнение запроса к базе данных: указывается, какие данные нужны из схемы, и затем получаются только соответствующие результаты. Помимо очевидного преимущества получения данных, готовых к использованию, такая точность также может значительно уменьшить требования к пропускной способности. Определения схем добавляют возможности валидации и проверки типов, чтобы минимизировать ошибки в данных. А поскольку интерфейс GraphQL просто передаёт запросы функции resolver и возвращает результаты, нет необходимости изменять API каждый раз, когда требуются другие данные или возникает необходимость модифицировать бэкенд сервис.
Определение и использование GraphQL API
В то время как спецификация REST API – это список интерфейсов, GraphQL API имеет только один интерфейс с определенной схемой данных. Подобно схеме базы данных, схема GraphQL определяет имена, типы и структуру полей данных, которые предоставляет API. Если REST API сообщает, какие операции доступны, то GraphQL API сообщает, какие данные доступны.
Так как необходимо определить схему и поддерживать её в актуальном состоянии, API само документируется, что является большим преимуществом для разработчиков, особенно в сочетании с автоматической проверкой типов как данных, так и аргументов.
Пример из документации Apollo (Apollo является популярной платформой GraphQL): простая схема для каталога книг может быть такой:
type Book {
title: String
author: Author
}
type Author {
name: String
books: [Book]
}
Итак, имеем книги и авторов как кастомные типы. Каждая книга имеет одно название (String) и одного автора (объект Author), а каждый автор имеет одно имя (String) и любое количество книг (объекты Book). REST API, предоставляющий такую информацию, вероятно, будет иметь два отдельных интерфейса с разными URL-адресами для возврата списка книг и списка авторов. В GraphQL все запросы отправляются на один URL-адрес, а результаты зависят только от структуры запроса. Кроме того, можно предоставлять входные данные и аргументы, чтобы получить именно те данные, которые нужны программе.
Макетирование GraphQL API для атак
Чтобы протестировать или атаковать API, нужно составить карту его поверхности атаки. Для REST API это только вопрос поиска интерфейсов, потому что когда о них известно, соответственно известно и о целевых URL-адресах.
Но просто знание интерфейсов GraphQL не дает много информации о том, как его использовать или тестировать – нужно знать схему, чтобы можно было создавать правильные запросы.
Чтобы облегчить разработку, GraphQL включает функцию интроспекции (introspection), которая позволяет дизайнерам и разработчикам просматривать схему и создавать действительные запросы в интерактивном режиме. Хотя интроспекция чрезвычайно полезна для разработки, она также может позволить злоумышленникам составить схему без доступа к полному определению схемы, поэтому желательно отключить ее для частных API после запуска в производство (где это возможно).
Для платформы Apollo злоумышленники также могут злоупотреблять другой удобной функцией, а именно автокоррекцией имен полей. По умолчанию Apollo GraphQL пытается исправить нереальные названия полей и возвращает ближайшее подходящее название. Тщательно подбирая входные строки, злоумышленники могут злоупотреблять автокоррекцией, чтобы найти правильные имена полей перебором.
Векторы атак на GraphQL API
GraphQL имеет свои уникальные проблемы с безопасностью из-за принципиального отличия от REST API, наряду с теми, что присущи всем API. Как и в случае с любым другим API, необходимо учитывать риск инъекций второго уровня в подчинённые интерфейсы или источники данных. Важным аспектом является также правильная реализация аутентификации и авторизации, причём авторизация в GraphQL создаёт дополнительные вызовы. Ещё одной опасностью, специфической для GraphQL, является риск отказа в обслуживании (DoS) из-за рекурсивных запросов.
Аутентификация и авторизация
Безопасный контроль автоматизированного доступа к любому API (и, косвенно, к данным за ним) является сложной задачей. В случае GraphQL, авторизация особенно сложна, поскольку существует несколько способов доступа к одним и тем же данным через разные запросы. Это создаёт трудности в обеспечении доступа к определённым полям только для авторизованных пользователей API.
Если авторизация доступа не внедряется централизованно и последовательно, это может привести к серьёзным уязвимостям в безопасности данных, особенно когда GraphQL накладывается на REST API. Это часто происходит на ранних этапах внедрения GraphQL, когда новый API добавляется к существующему приложению. Если аутентификация и авторизация не координируются для обоих API, могут возникнуть пробелы, которые позволят злоумышленникам получить доступ к конфиденциальным данным. Поэтому аутентифицированное сканирование уязвимостей является важной частью тестирования безопасности.
Отказ в обслуживании из-за рекурсии
Одним из главных преимуществ GraphQL является возможность переставлять и реструктурировать запросы различными способами. Вместе с тем, это свойство может быть использовано и как вектор атаки. Ничто не мешает пользователям API создавать и отправлять рекурсивные запросы, которые вызывают те же поля снова и снова. Без определённых ограничений частоты запросов это может привести к отказу в обслуживании (DoS), особенно при работе с большими наборами данных.
Этот вектор DoS-атаки чрезвычайно легко использовать, используя лишь несколько строк текста запроса, и трудно блокировать, так как рекурсивные запросы являются действительным синтаксисом GraphQL, поэтому такие запросы могут быть легитимными. Это усложняет определение ресурсоёмкого запроса как попытки атаки.
Уязвимости во вторичных контекстах (secondary contexts)
Последний вектор атаки не ограничивается GraphQL и касается любого случая, когда запросы передаются через несколько уровней. Например, существует GraphQL API, накладывающийся на REST API, который взаимодействует с базой данных. Без должной очистки входных данных злоумышленники могут нацеливаться на подчинённый REST API, вводя, например, вредоносный путь/перемещение по директориям как значение поля в запросе GraphQL. GraphQL воспримет это как действительную строку, но если её бездумно вставить в соответствующий вызов REST API, эта строка может позволить злоумышленнику перейти к другому интерфейсу для выполнения несанкционированных операций.
Является ли GraphQL менее безопасным, чем REST API?
GraphQL не является менее безопасным по своей сути, чем другие архитектуры веб-API. На самом деле, по сравнению с REST API, которые полагаются на соглашения, а не на четко определенный стандарт, GraphQL имеет встроенную проверку и контроль типов, что обеспечивает, по крайней мере, некоторый уровень безопасности с самого начала.
Однако, как относительно новая технология, GraphQL часто интегрируется в существующие приложения и интерфейсы, что увеличивает сложность и потенциальные уязвимости. Наибольший риск возникает от попыток пользователей внедрять интерфейсы GraphQL без понимания их отличий от REST API. Помимо обсуждаемых проблем безопасности, это также касается других аспектов, таких как удобство использования и производительность.
Проверки безопасности GraphQL API в Invicti
Помимо надежного набора проверок безопасности для REST API, Invicti теперь может применять многие из таких проверок и к GraphQL API. Чтобы начать тестирование приложения с использованием GraphQL API, достаточно просто импортировать существующую схему GraphQL из файла или по URL-адресу, указать URL-адрес интерфейса и позволить сканеру начать работу. Если схема импортируется по URL-адресу, Invicti может отслеживать изменения в схеме и всегда использовать последнюю доступную версию (the latest available definition) для каждого сканирования.
Уязвимости в веб-приложениях, которые могут быть автоматически обнаружены Invicti через GraphQL API, включают:
- Слепое выполнение команд
- Слепая SQL-инъекция
- Командная инъекция
- Локальное включение файлов
- Внеполосное удаленное выполнение кода
- Подделка запросов на стороне сервера (SSRF)
- Удаленное выполнение кода







