# Insufficient GraphQL API vulnerability due to lack of validation of Authorization Bearer token

That day I got one private invitation from one private bug bounty program on HackerOne. And unexpectedly it was really fresh program with only few resolved reports.  So, far by this I've decided to hunt on this program. Program's front-end is written using Next.js JavaScript framework. It's really clean.

## **January 21th 2023**

While exploring on that program. I saw that they have pretty detailed API documentation. And whole API in their documentation is actually GraphQL API. And I started reading it, hence the time passing. I didn't find that day anything.

## January 22th 2023

So, while I was exploring their features, I've came across with one specific feature. And obviously I went to their API documentation again and I found that feature in their API documentation and it was pretty detailed, so it took me some time to understand it.

## January 23th 2023

So, after I was done with reading API documentation about that feature, I started testing that feature. Also feature was about Authorization Controls / Rule Types. It was for bank stuff.

## January 24th 2023

What I've noticed is that `Authorization` header with `Bearer` token is being invalidated from server-side. Basically it wasn't checking for  **Authorization.** This Rules Types feature was using same GraphQL API query `FindSpendRule` for every Rule type. Let's take one type as a example which was vulnerable obviously, as all of them were vulnerable to this vulnerability since it was affecting whole feature. So, this is the type that I was talking about `Street Address`&#x20;

Now let's see it's GraphQL API mutation:

```css
mutation CreateStreetAddressRule($input: CreateStreetAddressSpendRuleInput!) {
  createStreetAddressSpendRule(input: $input) {
    __typename
    ... on StreetAddressSpendRule {
      id
      name
      version
      allowed
      blocked
      createdAt
      updatedAt
    }
    ... on UserError {
      errors {
        code
        path
      }
    }
    ... on AccessDeniedError {
      message
    }
  }
}
```

So, this is a GraphQL mutation that creates a Street Address Rule Type and it's using the `CreateStreetAddressSpendRuleInput` input type. The mutation returns many different fields, depends on the result of the operation such as the rule's ID, name, version, and timestamps if the rule is created successfully, or it will return an `AccessDeniedError` from back-end side. Which means we can't access it.

Also I forgot to include our variables of our GraphQL mutation:

```css
{
  "input": {
    "name": "test",
    "allowed": ["MATCH"]
  }
}
```

So,  you can see it's a JSON object with a key `input` and a value that is also a object too. The `input` object has two keys which is the `name` and `allowed`. The value of `name` is a string `test` and the value of `allowed` is an array containing a single string `MATCH`. Also it used as a variable for the above GraphQL mutation `CreateStreetAddressRule`&#x20;

Now let's execute this GraphQL mutation and let's see what happens on back-end:

```json
{
  "data": {
    "createStreetAddressSpendRule": {
      "__typename": "StreetAddressSpendRule",
      "id": "<UUID>",
      "name": "My Street Address Rule",
      "version": "0",
      "allowed": ["MATCH"],
      "blocked": [],
      "createdAt": "2022-08-23T14:13:30.989Z",
      "updatedAt": "2022-08-23T14:13:30.989Z"
    }
  },
  "extensions": {
    "requestId": "31d7f305-9059-9d92-b827-4158a522e859"
  }
}
```

So, here we have a `data` object and a value. The `data` object has a mutation`createStreetAddressSpendRule` and a value that represents a street address spend rule. The object has some few fields including `__typename`, `id`, `name`, `version`, `allowed`, `blocked`, `createdAt`, `updatedAt` and the values of these fields are `string, string, string, array, array, string, string`. Also this JSON object has a key `extensions` with a `requestId` field and a string value that is a unique identifier for the request.

So, by this logic the implementation of the `createStreetAddressSpendRule` function does not properly check for the authorization before creating a new rule, and therefore attacker is able to gain sensitive information about another user. Basically there's a bad sanitization and it's not well validated from server-side.&#x20;

I will provide here how I was able to gain another's users sensitive information. I couldn't post `id` within variables directly since they don't have that in their API documentation but I've made it and I will show you how this happened:

```css
{
  "input": {
    "spendRuleId": "AAAAAAAAAAAAAA",
    "allowed": [
      "AUTOMATED_FUEL_DISPENSERS"
    ],
    "blocked": []
  }
}
```

So, In this JSON object, there's a object called `input` with a value of another object. The input object has three keys: `spendRuleId`, `allowed`, and `blocked`. The `spendRuleId` key has a string value of `AAAAAAAAAAAAA`, which is  a unique identifier for a spend rule. The `allowed` key has an array value with a single string `AUTOMATED_FUEL_DISPENSERS`, which represents a category that is allowed under the spend rule type. The `blocked` key also has an empty array value, which means that no spend categories are blocked under the spend rule.

Basically this will return user's information via `FindSpendRule` GraphQL API query. And via this way all we need to do is to manipulate ID with another's users spend rule type ID in order to gain his sensitive information which is bypassing access controls.&#x20;

## January 25th 2023

**- I reported this**&#x20;

## **January 30th 2023**

* HackerOne's triager marked it as `needs-more-info`

## January 31st 2023

* Triager change status to `Pending program review`

## February 1st 2023

* Program's staff member triaged my report and immediately awarded me with a $700 bounty.&#x20;

<figure><img src="/files/rjexBRic0Os9mWir2Zec" alt=""><figcaption></figcaption></figure>

Thank you for reading this. Follow me on Twitter: [https://twitter.com/intlulz](#january-21th-2023)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0x1int.gitbook.io/blogs/insufficient-graphql-api-vulnerability-due-to-lack-of-validation-of-authorization-bearer-token.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
