Введение: GraphQL
GraphQL часто представляют как революционно новый путь осмысления API. Вместо работы с жёстко определёнными на сервере конечными точками (endpoints) вы можете с помощью одного запроса получить именно те данные, которые вам нужны. И да – GraphQL гибок при внедрении в организации, он делает совместную работу команд frontend- и backend-разработки гладкой, как никогда раньше. Однако на практике обе эти технологии подразумевают отправку HTTP-запроса и получение какого-то результата, и внутри GraphQL встроено множество элементов из модели REST.REST и GraphQL работают с понятиями, которые принципиально очень похожи. Некоторые из различий говорят в пользу GraphQL. Но для GraphQL пока нет такого множества инструментов и решений по интеграции, как для REST.
Почему GraphQL: проблемы безопасности
GraphQL позиционируют как замену REST: гибкость, меньше запросов, получаем и запрашиваем именно те данные, которые нужно. Но в реальности, разработчики сталкиваются с некоторыми проблемами в backend части. От N+1 запросов до проблем с безопасностью.В системах с чувствительными к уровню привилегиями пользователя данными очень сложно реализовать контроль доступа пользователя к данным, появляются уязвимости.
Статистика уязвимостей (Salt Security 2025)
Из документа Salt Security State of API (данные для скачивания можно ввести липовые), узнаём основные проблемы в production API:- 99% организаций столкнулись с проблемами безопасности API за последний год.
- 55% замедлили выпуск новых приложений из-за опасений по безопасности API.
Самые частые типы инцидентов (в production):
- Уязвимости - 37%
- Утечки чувствительных данных - 34%
- Проблемы аутентификации - 29%
- API8: Security Misconfiguraiton - 54% атак
- API1: Broken Object level Authorization (BOLA) - 27%
Другие цифры, но не менее важные:
- Только 20% организаций мониторят API в реальном времени.
- Только 10% имеют стратегию API Posture Governance
- 58% мониторят API реже, чем ежедневно
Reconnaissance
Этап разведки необходим для оценки поверхности атаки, если клиент не предоставит полную документацию по API. После получения этой информации мы перейдем к этапу выявления уязвимостей. Рассмотрим уязвимости, endpoint’ы, Introspection query, а также GraphQL Voyager.Обнаружение endpoint
Первый решающий шаг в тестировании на проникновение GraphQL API - это обнаружение его конечной точки. Это не всегда очевидно, особенно если API используется только для определенных функций или для определенных ролей.Поэтому проводится фаззинг целевого объекта, чтобы найти конечную точку, используя, например, этот список слов Seclists с телом запроса "query{__typename}".
Если мы получим ответ, содержащий {"data":{"__typename": "Query"}}, это подтвердит наличие GraphQL API на тестируемом URL.
Introspection query
Introspection query - это встроенный механизм, который позволяет клиенту запрашивать у сервера информацию о его структуре данных. Атакующий мгновенно узнает структуру базы данных, скрытые административные функции (deleteUser, makeAdmin) и типы данных. Зная все доступные поля, хакеру гораздо проще найти точки для инъекций (SQL/NoSQL), логических ошибок или обхода авторизации (BOLA/IDOR). Если разработчики добавили описания к полям в коде, они также отобразятся в интроспекции, раскрывая логику работы процессов.GraphQL Voyager: визуализация схемы
GraphQL Voyager - это ценный инструмент, который можно использовать для визуализации схемы GraphQL API на основе схемы, полученной с помощью интроспекции или Clairvoyance.Из его интерфейса можно получить запрос интроспекции. Вкратце, GraphQL Voyager очень полезен для быстрого выявления областей, представляющих интерес для исследования.
Authorization Testing
Обычно для авторизации или запрета запросов GraphQL используются белые или черные списки. Однако такой подход может быть уязвим, если он реализован неправильно.
IDOR через query arguments
IDOR (Insecure Direct Object Reference) - это уязвимость безопасности, возникающая, когда веб-приложение ненадлежащим образом контролирует доступ к объектам. Это означает, что пользователь может читать, изменять или удалять объект, который ему не принадлежит, например, конфиденциальную информацию или функции.Horizontal и Vertical escalation
При горизонтальном повышении пользователь читает или изменяет записи других пользователей с тем же уровнем привилегий. Часто это аналогично небезопасным прямым ссылкам на объекты. Клиент запрашивает конкретный узел или объект, используя его переменную id, а сервер не может проверить, действительно ли запрашивающий пользователь владеет этим конкретным объектом или имеет ли он разрешение на его просмотр.При вертикальном повышении пользователь несанкционированно получает доступ к данным или функциям администрирования более высокого уровня. Это происходит, когда непривилегированный пользователь выполняет мутацию или запрос, доступ к которым должен быть ограничен. Например, если пользователь изменяет переменную идентификатора или роли, чтобы повысить свой статус, или получает доступ к административным подграфам/полям без предоставления соответствующих учетных данных администратора.
Mutation-level authorization
Mutation-level authorization гарантирует, что пользователь имеет необходимые права для изменения данных на стороне сервера (путем создания, обновления или удаления). Поскольку изменения приводят к необратимым побочным эффектам, эти проверки обычно применяются на верхнем уровне с использованием пользовательских директив схемы, промежуточного ПО или встроенной логики.Перед выполнением мутации необходимо убедиться, что вызывающий объект имеет необходимую роль, разрешение или область действия для выполнения действия.
Injection Attacks
Injection Attacks в GraphQL происходят, когда вредоносные пользовательские данные небезопасно передаются непосредственно в запрос к базе данных, среду выполнения или другой API через точку входа GraphQL. Хотя сам слой GraphQL обеспечивает строгую проверку типов, он по своей сути не проверяет содержимое данных, что делает базовые системы уязвимыми, если запросы формируются путем конкатенации строк.
SQL injection в arguments
Атаки SQL-инъекций в GraphQL - тип уязвимости безопасности в API GraphQL, позволяющий злоумышленнику выполнять вредоносные SQL-запросы к базе данных на стороне сервера. В GraphQL атаки SQLi происходят, когда предоставленные пользователем данные не проходят надлежащую проверку или очистку перед использованием в запросе к базе данных. Злоумышленники могут использовать эту уязвимость, внедряя вредоносный SQL-код в запрос GraphQL, который затем выполняется базой данных на стороне сервера. Этот тип атаки может использоваться для обхода средств аутентификации и авторизации, выполнения произвольных SQL-запросов, а также для доступа к конфиденциальным данным или их изменения.
JSON:
query {
users(name:"1' OR '1'='1'"){
name
email
}
}
NoSQL injection
Инъекции NoSQL в GraphQL происходят, когда небезопасно обрабатываемые аргументы пользователя обходят систему типов GraphQL и манипулируют командами, отправляемыми в нереляционную базу данных, таких как MongoDB или CouchDB. Поскольку GraphQL проверяет только типы данных (например, проверяет, является ли входная строка строкой), он не распознает, содержит ли эта строка вредоносные операторы базы данных, предназначенные для изменения логики запроса.Разработчик использует стандартный драйвер MongoDB. Он ошибочно передает аргументы непосредственно в объект запроса без проверки, полагая, что проверки типа String в GraphQL достаточно для обеспечения безопасности. Злоумышленник не знает пароль администратора, но знает, что имя пользователя — admin. Он атакует поле пароля, передавая JSON-объект, содержащий оператор NoSQL, вместо текстовой строки.
JSON:
{
"user": "admin",
"pass": { "$gt": "" }
}
OS command injection через resolvers
CMD injection - это уязвимость безопасности, позволяющая злоумышленнику выполнять произвольные команды на сервере, где размещено приложение. Она возникает, когда приложение включает необработанные пользовательские данные в команду, передаваемую операционной системе для выполнения.В контексте GraphQL уязвимость внедрения команд ОС может возникнуть, если у вас есть мутация или запрос, который принимает пользовательские данные и использует их в системной команде.
Например, предположим, что сервер имеет функцию, которая извлекает изображение аватара по предоставленному URL-адресу для локального сохранения или выполнения какой-либо обработки. Если для этого используется какая-либо команда оболочки, например wget или cURL, и она напрямую вставляет предоставленный пользователем avatarUrl в командную строку без проверки или очистки, то может произойти внедрение команды.
Batching и Brute-Force
Чтобы понять суть атаки, сначала необходимо понять что такое пакетная обработка запросов в этом случае. Так вот, пакетная обработка запросов — это функция оптимизации производительности, реализованная многими серверами GraphQL, такими как Apollo Server и Express-GraphQL. Она позволяет клиенту отправлять несколько запросов или мутаций на сервер в одном сетевом запросе. Это особенно полезно для мобильных приложений или сред с высокой задержкой, где сокращение количества HTTP-запросов имеет решающее значение для производительности.Array queries для bypass rate limiting
Клиент отправляет массив JSON-объектов запроса вместо одного объекта. Если сервер разрешает массив из 1000 запросов, злоумышленник может запросить 1000 различных записей о пользователях в одном HTTP-запросе. Если ваш WAF настроен на блокировку IP-адреса после 100 запросов в минуту, злоумышленник все равно не будет заблокирован, поскольку он отправил только один запрос.Brute-force OTP через batching
Пакетная обработка запросов GraphQL может обойти стандартное ограничение скорости обработки одного запроса, объединяя несколько попыток ввода одноразового пароля (OTP) в один HTTP-запрос. Это происходит, когда приложение обрабатывает массив запросов последовательно в рамках одного сетевого обмена данными, не отслеживая общее количество попыток в пакете.Denial of Service
GraphQL особенно уязвим для атак типа "отказ в обслуживании" (DoS). Поскольку клиенты контролируют точную структуру ответа, злоумышленники могут создавать вредоносные запросы, которые перегружают серверы, встраивая поля глубоко, дублируя поля или используя псевдонимы, заставляя сервер выполнять дорогостоящие вычисления или получать огромные массивы данных.
Nested query depth attack
JSON:
query {
pastes {
owner {
pastes {
owner {
pastes {
owner {
pastes {
owner {
pastes {
owner {
pastes {
owner {
pastes {
Circular fragments
Фрагменты — это логические элементы, которые можно использовать во многих запросах и мутациях. Фрагмент можно объявить и затем использовать в любом объекте. По сути, это подмножество полей, принадлежащих соответствующему типу. Если в схеме бэкенда есть объект PasteObject, который используется многими типами данных и может применяться в нескольких местах - то, можно объявить фрагмент в объекте PasteObject, который можно использовать, просто вызвав имя фрагмента, не вводя все поля объекта PasteObject целиком.Field duplication
Иногда GraphQL-серверы допускают дублирование или повторение полей в запросе. Это позволяет конечному пользователю заставлять сервер обрабатывать одно и то же поле снова и снова "n" раз. Если фиксируем, что увеличение количества одинаковых полей в запросе влияет на время ответа сервера и, следовательно, создает возможность атаки типа "отказ в обслуживании". Если дублирование допустимо, существует вероятность того, что сервер будет тратить время на обработку одного и того же параметра снова и снова, тем самым отвлекаясь от обработки реальных запросов от конечных пользователей. Учитывая увеличение времени ответа при увеличении количества дублирующихся полей, в этом случае можно организовать атаку злоумышленника, чтобы отвлечь сервер на обработку этого единственного запроса, что приведет к атаке типа "отказ в обслуживании".Инструментарий
Разберём 2 незаменимых инструмента при работе с GraphQL которые выполняют абсолютно разные задачи.InQL Scanner (Burp extension)
Это расширение разработано для оказания помощи в тестировании безопасности GraphQL. Основной предоставляемый инструмент - это настраиваемый сканер, который анализирует конечную точку GraphQL или локальный файл схемы интроспекции. Он генерирует все возможные запросы и мутации, представляя их в организованном виде для тщательного анализа. Результаты сканирования могут быть отправлены в инструменты Burp Repeater или Intruder для дальнейшего тестирования.Altair GraphQL Client
Altair - это многофункциональная IDE для разработки GraphQL-клиентов для всех платформ. Altair GraphQL Client помогает отлаживать GraphQL-запросы и реализации, беря на себя сложную работу, чтобы вы могли сосредоточиться на выполнении реальных задач. Встроенный документационный обозреватель с поиском и сортировкой позволяет мгновенно изучать типы, мутации и подписки большой схемы, а автоматическое обновление подтягивает изменения API на лету. Мощный редактор Query pane с автодополнением и контекстными действиями ускоряет написание кода, пока панель Query variables изолирует динамические параметры.Защитные меры
Вот три защитные меры которые усилят защиту GraphQL-серверов от перегрузки и раскрытия структуры данных.Depth и cost limiting
Защищает сервер от ресурсоемких запросов, способных вызвать отказ в обслуживании. Злоумышленник может создать циклический запрос огромной вложенности (например, user -> friends -> friends -> friends...). Ограничение глубины (обычно до 3-5 уровней) парсит абстрактное синтаксическое дерево до выполнения запроса и сразу отклоняет его, если вложенность превышает лимит.Persisted queries
Вместо того чтобы клиент отправлял на сервер огромный и произвольный текст GraphQL-запроса, разработчики заранее компилируют все легитимные запросы приложения, хэшируют их и сохраняют этот список на сервере. В продакшене клиент отправляет только хэш. Это полностью исключает возможность отправки произвольных запросов. Злоумышленник не сможет выполнить несанкционированную мутацию.Disable introspection in production
Отключение интроспекции на продакшене усложняет поиск скрытых или административных функций. Атакующему придется угадывать имена полей и мутаций (Стоит помнить, что ошибки валидации GraphQL иногда могут подсказывать правильные имена полей, поэтому их вывод тоже нужно минимизировать).Литература
https://habr.com/ru/articles/335158/https://vc.ru/dev/2211687-problemy-graphql-na-servere
https://content.salt.security/state-api-report.html
https://www.vaadata.com/en/blog/graphql-api-vulnerabilities-common-attacks-and-security-tips/
https://www.vaadata.com/en/blog/exploiting-a-broken-access-control-vulnerability-on-graphql/
https://www.imperva.com/blog/graphql-vulnerabilities-common-attacks/
https://blogs.jsmon.sh/what-is-graphql-batching-attack-ways-to-exploit-examples-and-impact/
https://github.com/altair-graphql/altair
https://portswigger.net/bappstore/296e9a0730384be4b2fffef7b4e19b1f
https://medium.com/@ibm_ptc_security/denial-of-service-attacks-with-graphql-77189a6ba85b
https://medusa0xf.medium.com/bypassing-2fa-in-graphql-apis-a-step-by-step-guide-4b73816bd4c3