GraphQL
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Deepen your expertise in Mobile Security with 8kSec Academy. Master iOS and Android security through our self-paced courses and get certified:
GraphQL підкреслюється як ефективна альтернатива REST API, пропонуючи спрощений підхід до запитів даних з бекенду. На відміну від REST, який часто вимагає численних запитів до різних кінцевих точок для збору даних, GraphQL дозволяє отримувати всю необхідну інформацію через один запит. Це спрощення значно вигідно для розробників, зменшуючи складність їх процесів отримання даних.
З появою нових технологій, включаючи GraphQL, також виникають нові вразливості безпеки. Ключовий момент, який слід зазначити, полягає в тому, що GraphQL за замовчуванням не включає механізми аутентифікації. Відповідальність за впровадження таких заходів безпеки лежить на розробниках. Без належної аутентифікації кінцеві точки GraphQL можуть розкривати чутливу інформацію неаутентифікованим користувачам, що становить значний ризик для безпеки.
Щоб виявити відкриті екземпляри GraphQL, рекомендується включити специфічні шляхи в атаки грубої сили на директорії. Ці шляхи:
/graphql
/graphiql
/graphql.php
/graphql/console
/api
/api/graphql
/graphql/api
/graphql/graphql
Виявлення відкритих екземплярів GraphQL дозволяє перевірити підтримувані запити. Це важливо для розуміння даних, доступних через кінцеву точку. Система інтроспекції GraphQL полегшує це, детально описуючи запити, які підтримує схема. Для отримання додаткової інформації про це зверніться до документації GraphQL щодо інтроспекції: GraphQL: A query language for APIs.
Інструмент graphw00f здатний виявити, який движок GraphQL використовується на сервері, а потім надрукувати корисну інформацію для аудитора безпеки.
Щоб перевірити, чи є URL сервісом GraphQL, можна надіслати універсальний запит, query{__typename}
. Якщо відповідь містить {"data": {"__typename": "Query"}}
, це підтверджує, що URL містить кінцеву точку GraphQL. Цей метод спирається на поле __typename
GraphQL, яке розкриває тип запитуваного об'єкта.
Graphql зазвичай підтримує GET, POST (x-www-form-urlencoded) та POST(json). Хоча для безпеки рекомендується дозволяти лише json, щоб запобігти атакам CSRF.
Щоб використовувати інтроспекцію для виявлення інформації про схему, запитайте поле __schema
. Це поле доступне на кореневому типі всіх запитів.
З цим запитом ви знайдете назви всіх типів, що використовуються:
Цей запит дозволяє витягти всі типи, їх поля та аргументи (а також типи аргументів). Це буде дуже корисно для розуміння того, як запитувати базу даних.
Помилки
Цікаво знати, чи помилки будуть показані, оскільки вони нададуть корисну інформацію.
Перерахунок схеми бази даних через інспекцію
Якщо інспекція увімкнена, але вищезазначений запит не виконується, спробуйте видалити директиви onOperation
, onFragment
та onField
зі структури запиту.
Запит інтроспекції в рядку:
Останній рядок коду є запитом graphql, який виведе всю мета-інформацію з graphql (імена об'єктів, параметри, типи...)
Якщо інтроспекція увімкнена, ви можете використовувати GraphQL Voyager для перегляду всіх опцій у графічному інтерфейсі.
Тепер, коли ми знаємо, який тип інформації зберігається в базі даних, давайте спробуємо витягти деякі значення.
В інтроспекції ви можете знайти який об'єкт ви можете безпосередньо запитувати (оскільки ви не можете запитувати об'єкт лише тому, що він існує). На наступному зображенні ви можете побачити, що "queryType" називається "Query", і що одне з полів об'єкта "Query" - це "flags", який також є типом об'єкта. Отже, ви можете запитувати об'єкт прапора.
Зверніть увагу, що тип запиту "flags" - це "Flags", і цей об'єкт визначається як нижче:
Ви можете побачити, що об'єкти "Flags" складаються з name та value. Тоді ви можете отримати всі імена та значення прапорів за допомогою запиту:
Зверніть увагу, що якщо об'єкт для запиту є примітивним типом, таким як рядок, як у наступному прикладі
Ви можете просто запитати його за допомогою:
В іншому прикладі було 2 об'єкти всередині об'єкта типу "Query": "user" та "users". Якщо цим об'єктам не потрібні аргументи для пошуку, можна отримати всю інформацію з них, просто попросивши дані, які вам потрібні. У цьому прикладі з Інтернету ви могли б витягти збережені імена користувачів та паролі:
Однак у цьому прикладі, якщо ви спробуєте це зробити, ви отримаєте цю помилку:
Схоже, що якимось чином він буде шукати, використовуючи аргумент "uid" типу Int.
У будь-якому випадку, ми вже знали, що в розділі Basic Enumeration було запропоновано запит, який показував нам всю необхідну інформацію: query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}
Якщо ви прочитаєте зображення, надане, коли я запускав цей запит, ви побачите, що "user" мав аргумент "uid" типу Int.
Отже, виконуючи легкий uid брутфорс, я виявив, що в uid=1 було отримано ім'я користувача та пароль:
query={user(uid:1){user,password}}
Зверніть увагу, що я виявив, що можу запитувати параметри "user" та "password", тому що якщо я спробую шукати щось, що не існує (query={user(uid:1){noExists}}
), я отримую цю помилку:
І під час фази перерахунку я виявив, що об'єкт "dbuser" має поля "user" та "password.
Трюк з вивантаженням рядка запиту (дякую @BinaryShadow_)
Якщо ви можете шукати за рядковим типом, наприклад: query={theusers(description: ""){username,password}}
і ви шукаєте порожній рядок, це вивантажить всі дані. (Зверніть увагу, що цей приклад не пов'язаний з прикладом з навчальних посібників, для цього прикладу припустимо, що ви можете шукати, використовуючи "theusers" за полем рядка під назвою "description").
У цій конфігурації база даних містить осіб та фільми. Особи ідентифікуються за їх електронною поштою та іменем; фільми - за їх іменем та рейтинговою оцінкою. Особи можуть бути друзями один з одним і також мати фільми, що вказує на відносини в базі даних.
Ви можете шукати осіб за іменем і отримувати їх електронні адреси:
Ви можете шукати осіб за іменем і отримати їхні підписані фільми:
Зверніть увагу, як вказано отримати name
з subscribedMovies
особи.
Ви також можете шукати кілька об'єктів одночасно. У цьому випадку виконується пошук 2 фільмів:
Або навіть відносини кількох різних об'єктів за допомогою псевдонімів:
Мутації використовуються для внесення змін на стороні сервера.
У інтроспекції ви можете знайти оголошені мутації. На наступному зображенні "MutationType" називається "Mutation", а об'єкт "Mutation" містить назви мутацій (як "addPerson" у цьому випадку):
У цій конфігурації база даних містить осіб та фільми. Особи ідентифікуються за їх електронною поштою та іменем; фільми - за їх іменем та рейтинговою оцінкою. Особи можуть бути друзями один з одним і також мати фільми, що вказує на відносини в базі даних.
Мутація для створення нових фільмів у базі даних може виглядати як наступна (у цьому прикладі мутація називається addMovie
):
Зверніть увагу, як у запиті вказані як значення, так і тип даних.
Крім того, база даних підтримує операцію мутації, названу addPerson
, яка дозволяє створювати осіб разом з їх асоціаціями до існуючих друзів та фільмів. Важливо зазначити, що друзі та фільми повинні існувати в базі даних до того, як їх зв'яжуть з новоствореною особою.
Як пояснено в одній з вразливостей, описаних у цьому звіті, директивне перевантаження передбачає виклик директиви навіть мільйони разів, щоб змусити сервер витрачати ресурси, поки його не буде можливо вивести з ладу.
Цю інформацію було взято з https://lab.wallarm.com/graphql-batching-attack/. Аутентифікація через GraphQL API з одночасною відправкою багатьох запитів з різними обліковими даними для перевірки. Це класична атака брутфорсом, але тепер можливо відправити більше ніж одну пару логін/пароль за один HTTP запит завдяки функції пакетування GraphQL. Цей підхід обманює зовнішні програми моніторингу швидкості, змушуючи їх думати, що все в порядку і немає бота, що намагається вгадати паролі.
Нижче ви можете знайти найпростішу демонстрацію запиту аутентифікації програми з 3 різними парами електронна пошта/пароль одночасно. Очевидно, що можливо відправити тисячі в одному запиті таким же чином:
Як видно з скріншоту відповіді, перший і третій запити повернули null і відобразили відповідну інформацію в секції error. Другий мутаційний запит містив правильні дані аутентифікації і відповідь має правильний токен сесії аутентифікації.
Все більше graphql кінцевих точок відключають інспекцію. Однак помилки, які graphql викидає, коли отримує несподіваний запит, достатні для інструментів, таких як clairvoyance, щоб відтворити більшу частину схеми.
Більше того, розширення Burp Suite GraphQuail спостерігає за запитами GraphQL API, що проходять через Burp і будує внутрішню GraphQL схему з кожним новим запитом, який воно бачить. Воно також може відкрити схему для GraphiQL і Voyager. Розширення повертає фальшиву відповідь, коли отримує запит на інспекцію. В результаті GraphQuail показує всі запити, аргументи та поля, доступні для використання в API. Для отримання додаткової інформації перевірте це.
Гарний словник для виявлення суб'єктів GraphQL можна знайти тут.
Щоб обійти обмеження на запити інспекції в API, вставка спеціального символу після ключового слова __schema
виявляється ефективною. Цей метод експлуатує загальні помилки розробників у шаблонах regex, які намагаються заблокувати інспекцію, зосереджуючись на ключовому слові __schema
. Додаючи символи, такі як пробіли, нові рядки та коми, які GraphQL ігнорує, але можуть не враховуватися в regex, можна обійти обмеження. Наприклад, запит на інспекцію з новим рядком після __schema
може обійти такі захисти:
Якщо не вдалося, розгляньте альтернативні методи запитів, такі як GET запити або POST з x-www-form-urlencoded
, оскільки обмеження можуть застосовуватися лише до POST запитів.
Як згадувалося в цьому виступі, перевірте, чи можливо підключитися до graphQL через WebSockets, оскільки це може дозволити вам обійти потенційний WAF і змусити комунікацію через вебсокети витікати схему graphQL:
When introspection is disabled, examining the website's source code for preloaded queries in JavaScript libraries is a useful strategy. Ці запити можна знайти за допомогою вкладки Sources
у інструментах розробника, що надає інформацію про схему API та виявляє потенційно відкриті чутливі запити. The commands to search within the developer tools are:
Якщо ви не знаєте, що таке CSRF, прочитайте наступну сторінку:
CSRF (Cross Site Request Forgery)Ви зможете знайти кілька GraphQL кінцевих точок налаштованих без CSRF токенів.
Зверніть увагу, що запити GraphQL зазвичай надсилаються через POST запити з використанням Content-Type application/json
.
Однак більшість GraphQL кінцевих точок також підтримують form-urlencoded
POST запити:
Тому, оскільки CSRF запити, як попередні, надсилаються без попередніх запитів, можливо виконати зміни в GraphQL, зловживаючи CSRF.
Однак зверніть увагу, що нове значення за замовчуванням куки для прапора samesite
у Chrome - Lax
. Це означає, що куки будуть надсилатися лише з веб-сайту третьої сторони в GET запитах.
Зверніть увагу, що зазвичай можливо надіслати запит запиту також як GET запит, і токен CSRF може не перевірятися в GET запиті.
Також, зловживаючи XS-Search атака, може бути можливим ексфільтрувати вміст з кінцевої точки GraphQL, зловживаючи обліковими даними користувача.
Для отримання додаткової інформації перевірте оригінальний пост тут.
Подібно до вразливостей CRSF, зловживаючи graphQL, також можливо виконати викрадення WebSocket між сайтами, щоб зловживати аутентифікацією з GraphQL з незахищеними куками і змусити користувача виконувати несподівані дії в GraphQL.
Для отримання додаткової інформації перевірте:
WebSocket AttacksБагато функцій GraphQL, визначених на кінцевій точці, можуть перевіряти лише аутентифікацію запитувача, але не авторизацію.
Модифікація змінних вхідних запитів може призвести до витоку чутливих деталей облікового запису leak.
Мутація може навіть призвести до захоплення облікового запису, намагаючись змінити дані іншого облікового запису.
Зв'язування запитів разом може обійти слабку систему аутентифікації.
У наведеному нижче прикладі ви можете побачити, що операція - "forgotPassword" і що вона повинна виконувати лише запит forgotPassword, пов'язаний з нею. Це можна обійти, додавши запит в кінець, у цьому випадку ми додаємо "register" і змінну користувача, щоб система зареєструвалася як новий користувач.
У GraphQL псевдоніми - це потужна функція, яка дозволяє явно називати властивості під час виконання запиту API. Ця можливість особливо корисна для отримання кількох екземплярів одного типу об'єкта в одному запиті. Псевдоніми можна використовувати для подолання обмеження, яке заважає об'єктам GraphQL мати кілька властивостей з однаковим ім'ям.
Для детального розуміння псевдонімів GraphQL рекомендується наступний ресурс: Псевдоніми.
Хоча основна мета псевдонімів полягає в зменшенні необхідності в численних викликах API, було виявлено ненавмисний випадок використання, коли псевдоніми можуть бути використані для виконання атак грубої сили на кінцеву точку GraphQL. Це можливо, оскільки деякі кінцеві точки захищені обмежувачами швидкості, призначеними для запобігання атакам грубої сили шляхом обмеження кількості HTTP запитів. Однак ці обмежувачі швидкості можуть не враховувати кількість операцій у кожному запиті. Оскільки псевдоніми дозволяють включати кілька запитів в один HTTP запит, вони можуть обійти такі заходи обмеження швидкості.
Розгляньте наведену нижче ілюстрацію, яка демонструє, як псевдонімовані запити можуть бути використані для перевірки дійсності кодів знижок магазину. Цей метод може обійти обмеження швидкості, оскільки він компілює кілька запитів в один HTTP запит, потенційно дозволяючи перевірити численні коди знижок одночасно.
Перевантаження псевдонімів - це вразливість GraphQL, де зловмисники перевантажують запит багатьма псевдонімами для одного й того ж поля, змушуючи бекенд-резолвер виконувати це поле повторно. Це може перевантажити ресурси сервера, що призводить до відмови в обслуговуванні (DoS). Наприклад, у наведеному нижче запиті те саме поле (expensiveField
) запитується 1,000 разів, використовуючи псевдоніми, змушуючи бекенд обчислювати його 1,000 разів, що потенційно виснажує ЦП або пам'ять:
Щоб зменшити це, реалізуйте обмеження на кількість псевдонімів, аналіз складності запитів або обмеження швидкості, щоб запобігти зловживанню ресурсами.
Пакетування запитів на основі масиву - це вразливість, коли GraphQL API дозволяє пакетувати кілька запитів в одному запиті, що дозволяє зловмиснику надсилати велику кількість запитів одночасно. Це може перевантажити бекенд, виконуючи всі пакетовані запити паралельно, споживаючи надмірні ресурси (ЦП, пам'ять, з'єднання з базою даних) і потенційно призводячи до Відмови в обслуговуванні (DoS). Якщо немає обмеження на кількість запитів у пакеті, зловмисник може скористатися цим, щоб знизити доступність сервісу.
У цьому прикладі 10 різних запитів об'єднуються в один запит, змушуючи сервер виконувати їх усі одночасно. Якщо скористатися цим з більшим розміром пакету або запитами, що вимагають великих обчислень, це може перевантажити сервер.
Перевантаження директив відбувається, коли сервер GraphQL дозволяє запити з надмірними, дубльованими директивами. Це може перевантажити парсер і виконавця сервера, особливо якщо сервер неодноразово обробляє одну й ту ж логіку директиви. Без належної валідації або обмежень зловмисник може скористатися цим, створивши запит з численними дубльованими директивами, щоб викликати високе використання обчислень або пам'яті, що призводить до Відмови в обслуговуванні (DoS).
Зверніть увагу, що в попередньому прикладі @aa
є користувацькою директивою, яка може не бути оголошена. Загальною директивою, яка зазвичай існує, є @include
:
Ви також можете надіслати запит на інспекцію, щоб виявити всі оголошені директиви:
А потім використовуйте деякі з кастомних.
Дублювання Полів — це вразливість, коли сервер GraphQL дозволяє запити з однаковим полем, яке повторюється надмірно. Це змушує сервер вирішувати поле повторно для кожного випадку, споживаючи значні ресурси (ЦП, пам'ять та виклики бази даних). Зловмисник може створити запити з сотнями або тисячами повторюваних полів, викликаючи високе навантаження і потенційно призводячи до Відмови в Обслуговуванні (DoS).
https://github.com/dolevf/graphql-cop: Тестування поширених неправильних налаштувань graphql кінцевих точок
https://github.com/assetnote/batchql: Скрипт аудиту безпеки GraphQL з акцентом на виконання пакетних запитів та мутацій GraphQL.
https://github.com/dolevf/graphw00f: Визначення графіку, що використовується
https://github.com/gsmith257-cyber/GraphCrawler: Набір інструментів, який можна використовувати для отримання схем та пошуку чутливих даних, тестування авторизації, брутфорс схем та знаходження шляхів до певного типу.
https://blog.doyensec.com/2020/03/26/graphql-scanner.html: Може використовуватися як автономний інструмент або розширення Burp.
https://github.com/swisskyrepo/GraphQLmap: Може використовуватися як CLI клієнт також для автоматизації атак
https://gitlab.com/dee-see/graphql-path-enum: Інструмент, який перераховує різні способи досягнення певного типу в схемі GraphQL.
https://github.com/doyensec/GQLSpection: Наступник автономного та CLI режимів InQL
https://github.com/doyensec/inql: Розширення Burp для розширеного тестування GraphQL. Сканер є основою InQL v5.0, де ви можете аналізувати кінцеву точку GraphQL або локальний файл схеми інспекції. Він автоматично генерує всі можливі запити та мутації, організуючи їх у структурований вигляд для вашого аналізу. Компонент Атакуючий дозволяє вам виконувати пакетні атаки GraphQL, що може бути корисним для обходу погано реалізованих обмежень швидкості.
https://github.com/nikitastupin/clairvoyance: Спробуйте отримати схему навіть з вимкненою інспекцією, використовуючи допомогу деяких баз даних Graphql, які запропонують назви мутацій та параметрів.
https://github.com/graphql/graphiql: GUI клієнт
https://altair.sirmuel.design/: GUI Клієнт
Відео, що пояснює AutoGraphQL: https://www.youtube.com/watch?v=JJmufWfVvyU
Поглибте свої знання в Мобільній безпеці з 8kSec Academy. Опануйте безпеку iOS та Android через наші курси з самостійним навчанням та отримайте сертифікат:
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)