Статья GraphQL Security: уязвимости и методы тестирования

preview_graphql.webp

Введение: 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%
Топ самых эксплуатируемых уязвимостей (OWASP):
  • 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

1.webp

Обычно для авторизации или запрета запросов GraphQL используются белые или черные списки. Однако такой подход может быть уязвим, если он реализован неправильно.

IDOR через query arguments

IDOR (Insecure Direct Object Reference) - это уязвимость безопасности, возникающая, когда веб-приложение ненадлежащим образом контролирует доступ к объектам. Это означает, что пользователь может читать, изменять или удалять объект, который ему не принадлежит, например, конфиденциальную информацию или функции.

Horizontal и Vertical escalation

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

При вертикальном повышении пользователь несанкционированно получает доступ к данным или функциям администрирования более высокого уровня. Это происходит, когда непривилегированный пользователь выполняет мутацию или запрос, доступ к которым должен быть ограничен. Например, если пользователь изменяет переменную идентификатора или роли, чтобы повысить свой статус, или получает доступ к административным подграфам/полям без предоставления соответствующих учетных данных администратора.

Mutation-level authorization

Mutation-level authorization гарантирует, что пользователь имеет необходимые права для изменения данных на стороне сервера (путем создания, обновления или удаления). Поскольку изменения приводят к необратимым побочным эффектам, эти проверки обычно применяются на верхнем уровне с использованием пользовательских директив схемы, промежуточного ПО или встроенной логики.

Перед выполнением мутации необходимо убедиться, что вызывающий объект имеет необходимую роль, разрешение или область действия для выполнения действия.


Injection Attacks

2.webp

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

3.webp

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
 
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🧭 Навигатор · ИБ 2026
Не знаешь, какой трек твой?
5 направлений ИБ, реальные зарплаты и точка входа для каждого — в одном треде.
JuniorSenior+
100K → 600K+ ₽ /мес
Открыть навигатор →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab