2. Accidental exposure of private GraphQL fields

0 25
0x00 IntroductionGraphQL is an API query language developed by Facebook, aiming...

0x00 Introduction

GraphQL is an API query language developed by Facebook, aiming to improve communication efficiency between the client and the server. At certain times, REST API needs to be called multiple times to return the required resources, while GraphQL allows the client to explicitly specify the data it needs, which can be used for precise data queries. GraphQL official documentation:https://graphql.org/, Chinese document:https://graphql.cn/.

Here is a simple example,queryindicating the query operation,{}indicating the selection set,Bookindicating the object to be queried,id: "1"indicating the query with the specified parameter id of 1,nameandauthorindicating the fields to be queried.

2. Accidental exposure of private GraphQL fields
query {
Book(id: "1") {
name
author
}
}

To better learn and understand GraphQL Attack later, it is necessary to learn several related concepts of GraphQL, here we go.

1. Schema

Schema (pattern) in GraphQL is a definition of a data model, describing the data structure that the client can access and operate on. It is like a database schema diagram or API documentation, specifying the data types that can be queried (query) and modified (mutation) and their relationships. A Schema mainly includes three operation types, namely:query,mutationandsubscription.

This is a bit abstract, let's take a specific example, as follows: defined a namedBookThe object type, which has 4 fields, respectivelyid,title,author,year. It can be simply compared to a Book class, but this class only has properties without methods.Note: These types are defined on the server using SDL (Schema Definition Language).

type Book {
id: ID!
title: String!
author: String!
year: Int
}

is definedBookAfter defining the type, aQueryType (The query type is mandatory in each Schema, see:https://spec.graphql.org/draft/#sec-Root-Operation-Types)。

type Query {
# Query all books, returning an array containing all books
books: [Book!]!

# Query a single book by book ID
bookById(id: ID!): Book

# Query books by author, returning all books by the specified author
booksByAuthor(author: String!): [Book]!

# Query books published before a specified year
booksBeforeYear(year: Int!): [Book!]!
}

If you want to modify a piece of data, you also need to defineMutationtype (optional, if you need to modify the data, you must define the type).

type Mutation {
# Add a new book
addBook(id: ID!, title: String!, author: String!, year: Int): Book!

# Update book information
updateBook(id: ID!, title: String!, author: String!, year: Int): Book!

# Delete a book
deleteBook(id: ID!): Boolean!
}

In addition, there is also aSubscriptiontypes can be defined according to business requirements (optional).

type Subscription {
# Subscribe to the book addition event
bookAdded: Book!

# Subscribe to the book deletion event
bookDeleted: ID!
}

Alright, let's define the above-mentionedBook,Query,Mutation,SubscriptionFour object types combined together constitute a complete GraphQL Schema.

2. Type

The abstract data model (Schema) of GraphQL is described by Type, each Type consists of several Fields (fields), and each Field points to a certain Type. Types can be divided into:Scalar,Object,Interface,Union,Enum,Inputthese types, the focus is onScalar Type(scalar type)andObject Type(object type).

Scalar Typeincluding:String,Int,Float,Boolean,Enum,ID, such as the following code inID!,String!,Intare scalar types (followed by!notation, indicating that the field cannot be empty), in addition, new scalars (not the focus) can also be declared.Object TypeIt can be used to express some complex data types, such as the following code inBookThis is an object type, which includes 4 Fields (fields), each pointing to a certain Type.

type Book {
id: ID!
title: String!
author: String!
year: Int
}

The type of a field generally uses scalar types, but can also be another object type.

type User {
id: ID
name: String
}

type Book {
id: ID!
title: String!
author: User
}

3. Operations

The GraphQL specification mainly includes three operation types, namely: Query (used to query data from the server), Mutation (used to operate data on the server, including: add, modify, delete, etc.), and Subscription, which are also known asroot operation type, known as the root operation type.

In simple terms, it is defined as follows:Booktype, but this type cannot be accessed and operated directly, and needs to be implemented through the three root operation types Query, Mutation, Subscription in the specification, and these three root operation types need to be explicitly defined and cannot be used directly.Note: In the Schema, besides Query which is required, the other two are optional.

3.1 Query

define the root query type, you can customize the naming as needed (the default isQuery),after custom naming, it is necessary toschemadefined to identify. Can only be identified according toQueryformat defined to query.

# The schema definition is used to specify the entry for the three operation types Query, Mutation, Subscription
# If using the default naming (Query, Mutation, Subscription), the schema definition can be omitted

schema {
query: RootQueryType
mutation: RootMutation
}

type RootQueryType {
books: [Book!]!

# Query books by ID
bookById(id: ID!): Book
}

type Book {
id: ID!
title: String!
author: String!
year: Int
}

type RootMutation {
# Add a book
addBook(title: String!, author: String!, year: Int): Book!

# Update book information
updateBook(id: ID!, title: String, author: String, year: Int): Book!

# Delete a book
deleteBook(id: ID!): Boolean!
}

type Subscription {
# Subscribe to the book addition event
bookAdded: Book!

# Subscribe to the book deletion event
bookDeleted: ID!
}

GraphQL Query is similar to RESTful API's GET request, mainly used to obtain specified data from the server. The above is the GraphQL Schema defined by the server, and the following is the query request initiated by the client. The following three query methods are all general.

# Query all books
query {
books{
id
title
author
year
}
}

# Query by ID
query {
bookById(id: "1") {
id, title, author, year
}
}

# Query books by author
query {
booksByAuthor(author: "JJ1ng") {
id title year
}
}

# Query books by specified year
query {
booksBeforeYear(year: 2025) {
id
title
author
}
}

The keyword can be omitted when performing Query query operations, but it cannot be omitted for Mutation and Subscription operations.

query {
bookById(id: "1") {
id
title
author
year
}
}

# The above can be changed to the following form
{
bookById(id: "1") {
id
title
author
year
}
}

And you can also customize the name of the query (known as the operation name), which can be written or not. As shown in the followinggetBookById.

query getBookById {
bookById(id: "1") {
id
title
author
year
}
}

3.2 Mutation

GraphQL Mutation is mainly used for editing, modifying, and deleting operations. Mutation can also use types, names, structures, and other content to specify the data to be modified. If a Mutation operation type is defined in the Schema, predefined modifications can be made to the data on the server.

mutation {
addBook(title: "1984", author: "George Orwell", year: 1949) {
id
title
author
year
}
}

3.3 Subscription

GraphQL Subscription is used for real-time data updates. Clients can subscribe to certain events, and when the server-side data changes, the server will actively push updates to the client. It is mainly used in real-time interaction scenarios.

subscription {
bookAdded {
id
title
author
}
}

4. Introspection

Introspection is an inherent feature of GraphQL, used to query information about the Schema that has been defined on the server. In the introspection system, many metadata types are also built-in, including:__schema,__type,__typeKind,__field,__inputValue,__enumValue,__directive. For a complete structure and the specific meaning of each field, refer to the documentation:https://spec.graphql.org/draft/#sec-Schema-IntrospectionHere are several common metadata type prototypes introduced as follows.

type __Schema {
description: String
types: [__Type!]!
queryType: __Type!
mutationType: __Type
subscriptionType: __Type
directives: [__Directive!]!
}

type __Type {
kind: __TypeKind!
name: String
description: String
fields(includeDeprecated: Boolean = false): [__Field!]
interfaces: [__Type!]
possibleTypes: [__Type!]
enumValues(includeDeprecated: Boolean = false): [__EnumValue!]
inputFields(includeDeprecated: Boolean = false): [__InputValue!]
ofType: __Type
specifiedByURL: String
}

type __Field {
name: String!
description: String
args(includeDeprecated: Boolean = false): [__InputValue!]!
type: __Type!
isDeprecated: Boolean!
deprecationReason: String
}

in}}__schemaIn the structurequeryTyeis used to represent the query type of the GraphQL service, and the object type is__Type, and__Typefield in the typename, which is used to record the entry of the query type and also includes afieldsfield, which is a collection that records the query fields supported by the query type. The following request is used to query the query type name of the GraphQL service (if not modified, it is the defaultQuery), as well as all of its fields and the types of the fields.

{
__schema {
queryType {
name
fields {
name
type {
name
}
}
}
}
}

Similar to this ismutationTypeandsubscriptionTypeobject.

{__schema{mutationType{name, fields{name type{name}}}}}
{__schema{subscriptionType{name, fields{name type{name}}}}}

in}}__schemaIn the structure, there is alsotypesThe field is a collection that records all types in the Schema (including: object types, scalar types, and metadata types).

{
__schema {
types {
name
}
}
}

in}}__schemastructure oftypesfield, the type of__Type, and__TypeThe type also contains afieldsfield infieldsThere is anameField, which is used to record the name of the field, that is, through the following query, you can obtain all types of GraphQL services and the fields contained in these types.

{
__schema {
types {
name
fields {
name
}
}
}
}

Query all fields of a specified type.

{
__type(name:\"user\"){
fields{
name
}
}
}

0x01 Vulnerability

GraphQL testing tools:

1. Detection

GraphQL defines how to handle queries through types and names, rather than through endpoints and HTTP request methods like RESTful API. That is, all GraphQL operations use the same endpoint (which can be understood as the same URL, usually with the POST request method). Common endpoint dictionary:https://github.com/danielmiessler/SecLists/blob/fe2aa9e7b04b98d94432320d09b5987f39a17de8/Discovery/Web-Content/graphql.txt.

After finding the GraphQL endpoint, a simple test can be performed to detect whether the target is using the GraphQL service, the request type isapplication/jsonIf the correct echo is not received, different request methods and types can be tried.

{"query": "{}"}
{"query": "{__schema}"}
{"query": "{__typename}"}
{"query": "{__schema{types{name}}}"}
{"query": "{__schema{queryType{name}}}"}
{"query": "{__schema{types{name,fields{name}}}}"}

The response as follows indicates a GraphQL service. Metadata field__typenameUsed to return the type of the current object, existing in any GraphQL service.

2. Info Gathering

Since it is impossible to know the supported query types and field names of the target GraphQL Schema in the real environment, this information can be obtained through introspection queries (similar to the Swagger API documentation). In addition, introspection queries may also leak some sensitive information, so remember to disable introspection queries in the real environment.

{"query": "query IntrospectionQuery{__schema{queryType{name}mutationType{name}subscriptionType{name}types{...FullType}directives{name description locations args{...InputValue}}}}fragment FullType on __Type{kind name description fields(includeDeprecated:true){name description args{...InputValue}type{...TypeRef}isDeprecated deprecationReason}inputFields{...InputValue}interfaces{...TypeRef}enumValues(includeDeprecated:true){name description isDeprecated deprecationReason}possibleTypes{...TypeRef}}fragment InputValue on __InputValue{name description type{...TypeRef}defaultValue}fragment TypeRef on __Type{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name}}}}}}}}"}

query {__schema{queryType{name}mutationType{name}subscriptionType{name}types{...FullType}directives{name description locations args{...InputValue}}}}fragment FullType on __Type{kind name description fields(includeDeprecated:true){name description args{...InputValue}type{...TypeRef}isDeprecated deprecationReason}inputFields{...InputValue}interfaces{...TypeRef}enumValues(includeDeprecated:true){name description isDeprecated deprecationReason}possibleTypes{...TypeRef}}fragment InputValue on __InputValue{name description type{...TypeRef}defaultValue}fragment TypeRef on __Type{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name}}}}}}}}

You can also perform introspection queries directly through the built-in functionality of BurpSuite.

If the target disables introspection queries, you can use the Clairvoyance tool for automated collection of API information.

# Installation
pip install clairvoyance

# Use
clairvoyance https://xxx.com/graphql -o schema.json

In addition, you can also obtain information about the target through brute force, refer to the following section 'Information Disclousure'. Dictionary:https://github.com/Escape-Technologies/graphql-wordlist.

3. Visualizing

The result of the introspection query is often very long and difficult to handle, you can use graphql-voyager to visualize the association between Schema entities. It can be realized through an online website, the address is:https://graphql-kit.com/graphql-voyager/Copy the result of the introspection query to the arrow position.

4. DVGA

DVGA (Damn Vulnerable GraphQL Application, an easily attacked GraphQL application) is a GraphQL target environment that can be used for learning and exercising GraphQL security-related skills, the target site is:https://github.com/dolevf/Damn-Vulnerable-GraphQL-Application.

GraphQL is just a kind of API query technology, which will also have common vulnerabilities, such as: SQL injection may exist when involving databases, SSRF may exist when involving remote loading, and JWT-related vulnerabilities may exist when involving JWT, so when encountering GraphQL, in addition to its unique vulnerabilities, we can also carry out targeted testing of other vulnerabilities according to the actual situation.

The installation steps are as follows, after execution, you can access port 5013.

git clone https://github.com/dolevf/Damn-Vulnerable-GraphQL-Application.git && cdDamn-Vulnerable-GraphQL-Application
docker build -t dvga .
docker run -d -t -p 5013:5013 -e WEB_HOST=0.0.0.0 --name dvga dvga

4.1 Information Disclosure

Click 'Private Pastes' to capture GraphQL requests.

4.1.1 Introspection

Firstly, use 'introspection query' and visualization tools to view the associations between GraphQL entities.

4.1.2 GraphiQL

GraphiQL (GraphQL Interface) is a test page of an integrated development environment, which can be used to construct queries and view results in real-time, and it will provide descriptive information about the GraphQL API, which may lead to information leakage. Common paths include:

/graphiql
/playground
/v1/graphql
/v2/graphql
/console

It may also leak related debugging information.

4.1.3 Suggestions

Useful information can be mined from the hints returned by the server. You can collect related dictionaries and, without introspection queries, you can enumerate to mine information about the target.

4.2 Denial of Service

The GraphQL API is vulnerable to DoS attacks because GraphQL supports various features, such as batch queries, which allow GraphQL requests to include multiple queries. Without limits, this can lead to a DoS attack.

4.2.1 Batch Query Attack

4.2.2 Deep Recursion Query Attack

From the visual legend of the introspection query, it can be seen that the object PastesObject references OwnerObject, and in the object OwnerObject, it also references PastesObject. Such an infinite nesting query can lead to a DoS attack.

4.2.3 Resource Intensive Query Attack

If system updates can be performed without authorization and the system update will make the website unusable, it can lead to a DoS attack.

4.2.4 Field Duplication Attack

A large number of duplicate fields.

4.2.5 Aliases based Attack

GraphQL queries do not support multiple identical properties, but they can be implemented through aliases, which can also lead to a DoS attack.

4.2.6 Directives Overloading

When a query request contains a large number of directives, it can lead to a DoS attack.

4.2.7 Pagination Limit Bypass

Pagination limit bypass is an attack type where the attacker tries to bypass the pagination control settings limit in the server-side GraphQL implementation. This attack occurs when the attacker manipulates the pagination parameters in the GraphQL query to bypass the expected page limit and retrieve more data than the server expects. For more details, please refer to:https://www.imperva.com/blog/graphql-vulnerabilities-common-attacks/.

4.3 SSRF

SSRF attacks can be attempted at any location where there is remote loading.

4.4 Code Execution

4.5 Injection

4.5.1 XSS

When the submitted data is not cleaned, it will also lead to XSS attacks.

4.5.2 Log Spoofing&Log Injection

For GraphQL's query and mutation operations, an operation name can be assigned, which is to note the approximate content of the request and facilitate debugging. As follows, give a query request aGetUserthe operation name, which can easily show that the request content is to obtain user information.

query GetUser {
User {
id
name
pass
}
}

However, since the operation name is customizable, the attacker can mislead the administrators by modifying the operation name to avoid detection. For example, the following is a change operation, but the operation name isGetUserThis can mislead the administrators to some extent.

mutation GetUser {
updateUser(name:"admin", pass:"123456") {
id
name
pass
}
}

4.5.3 SQLi

There is a risk of SQL injection at any place where there is database interaction, and GraphQL API is no exception.

4.5 Authorization Bypass

4.6.1 JWT Token Forge

First go throughcreateUserinterface.

Then create a new user throughlogininterface to return the JWT.

and change the identity in the JWT to admin.

Finally, use a forged JWT to go through the interfacemeObtain the administrator's password.

4.6.2 Interface Protection Bypass

Querying on the test page is denied.

can be modifiedCookieForenableto bypass.

4.6.3 Query Deny List Bypass

Creating a GraphQL API whitelist and blacklist is a common method to prevent malicious queries from accessing the API. However, it is easy to bypass the blacklist. As can be seensystemHealthIt is not allowed to be accessed and exists on the blacklist.

By adding the operation name, it is possible to bypass the restrictions of the blacklist.

4.7 Miscellaneous

4.7.1 Query Weak Password Protection

Due to the feature of GraphQL supporting aliases, multiple queries can be performed in one request, so if the website has restrictions on enumerations, it can try to use aliases for brute-force attacks.

4.7.2 Arbitrary File Write // Path Traversal

0x02 PortSwigger

The general approach is to obtain data similar to API documentation through 'introspection query', and construct related queries to obtain target sensitive information based on these data. Lab address:https://portswigger.net/web-security/all-labs#graphql-api-vulnerabilities

1. Accessing private GraphQL posts

First step, obtain information about the target GraphQL through 'introspection query'.

Second step, visualize the query results through online websites. Website address:https://graphql-kit.com/graphql-voyager/.

The final step is to construct requests to obtain sensitive information. It can be easily modified on the 'GraphQL' panel.

2. Accidental exposure of private GraphQL fields

Use 'introspection query' to obtain information about the target GraphQL and visualize the associations between entities through online websites.

Construct requests to obtain sensitive information.

3. Bypassing GraphQL introspection defenses

To prevent attacks, developers often filter__schemaThese characters are used to prevent 'introspection query'. As an attacker, you can try the following methods to bypass.

  • Add some special characters, such as: spaces, line breaks, comments, etc.
  • Change the request method to POST
  • Change the request type tox-www-form-urlencoded

Firstly, find the GraphQL Endpoint.

An error message indicating that introspection query is not allowed is prompted during the scan.

The__schemaand{Line breaks can bypass detection.

The result of introspection query is saved to a JSON formatted file, then import the Inql plugin, which can construct corresponding operations based on the result of introspection query. Download address of Inql plugin:https://github.com/doyensec/inql.

The result of introspection query can tell usDeleteOrganizationUserInputType an Int parameter called id.

4. Bypassing GraphQL brute force protections

GraphQL queries do not support multiple identical properties, such as the following query is aIncorrect example.

query getProductDetails {
getProduct(id: 1) {
id
name
}
getProduct(id: 2) {
id
name
}
}

If you want to implement the above requirements, you can use Aliases (aliases) to achieve this.

query getProductDetails {
product1: getProduct(id: 1) {
id
name
}
product2: getProduct(id: 2) {
id
name
}
}

The returned results are roughly in the following form:

{
"data": {
"product1": {
"id": 1,
"name": "Juice Extractor"
},
"product2": {
"id": 2,
"name": "Fruit Overlays"
}
}
}

Many websites have various anti-brute force measures, some of which limit the number of HTTP requests rather than the number of operations in a single request. In GraphQL, the 'alias' can send multiple query requests in a single request, which can effectively bypass the brute force measures.

When performing password brute force attacks, the error prompts are too many, and the account is banned for one minute.

to conduct brute force attacks based on 'alias'.

5. Performing CSRF exploits over GraphQL

for requests whose type isapplication/jsonofPOSTrequests cannot implement CSRF attacks, becauseapplication/jsontype requests cannot be sent in the form of web forms. Even if JSON format requests are sent through JavaScript, they will be restricted by the same-origin policy. But if the GraphQL server does not verify the request type and there is no related CSRF protection, it may also lead to CSRF vulnerabilities.

after logging in, the data packet to modify the user's email is obtained.

because it isapplication/jsontype packets cannot be used directly for CSRF attacks. But the GraphQL endpoint also supportsx-www-form-urlencodedformat.

0x03 Root-Me

Target field address:https://www.root-me.org/en/challenge/network-server/?titre_co=graphql

1. Introspection

Obtain target information through introspection queries and visualize it through Graphql-vayager.

2. Injection

This level restricts direct interaction with the GraphQL endpoint.

Through conjecture, it may be the data submittedq=ChinaConcatenate it to the normal query request and then query by the server.

Successfully verify the previous conjecture by constructing Payload.

Query all types and fields of the Schema.

3. Mutation

Directly querying 'flag' prompts that there is no permission.

After the Mutation operation is executed, the execution result will be returned, which means that Mutation can also achieve the function of querying, but the content of the query is the content after the Mutation operation. As shown below, you can see that the result of the Mutation operation is returned after the execution of the Mutation operation.

The results of introspection queries indicate that the 'flag' field is in the Nude object, and the Nude object can be controlled through nudeId. Although there is no permission to query the content of the Nude object, the content of the flag can be leaked based on the characteristic that the result of the Mutation operation will be returned.

0x04 Reference

https://graphql.org/

https://spec.graphql.org/

https://www.freebuf.com/articles/377142.html

https://xz.aliyun.com/t/14913

https://www.cnblogs.com/zhibing/p/17350053.html

https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/GraphQL%20Injection

https://medium.com/search?q=Hacking+GraphQL+for+Fun+and+Profit

https://www.imperva.com/blog/graphql-vulnerabilities-common-attacks/

https://cheatsheetseries.owasp.org/cheatsheets/GraphQL_Cheat_Sheet.html

https://github.com/nicholasaleks/graphql-threat-matrix

你可能想看:

graphw00f: A powerful GraphQL server engine fingerprinting tool

5. Collect exercise results The main person in charge reviews the exercise results, sorts out the separated exercise issues, and allows the red and blue sides to improve as soon as possible. The main

Data security can be said to be a hot topic in recent years, especially with the rapid development of information security technologies such as big data and artificial intelligence, the situation of d

In today's rapidly developing digital economy, data has become an important engine driving social progress and enterprise development. From being initially regarded as part of intangible assets to now

It is possible to perform credible verification on the system boot program, system program, important configuration parameters, and application programs of computing devices based on a credible root,

d) Adopt identification technologies such as passwords, password technologies, biometric technologies, and combinations of two or more to identify users, and at least one identification technology sho

Article 2 of the Cryptography Law clearly defines the term 'cryptography', which does not include commonly known terms such as 'bank card password', 'login password', as well as facial recognition, fi

Distributed Storage Technology (Part 2): Analysis of the architecture, principles, characteristics, and advantages and disadvantages of wide-column storage and full-text search engines

Camera intrusion, inciting suicide, guiding to graveyards... How far is the road to AI intelligent security?

ExploitPack (cracked) is an offensive penetration tool that includes 0day and a large number of undetectable exploit programs.

最后修改时间:
admin
上一篇 2025年03月25日 13:07
下一篇 2025年03月25日 13:30

评论已关闭