Skip to content

Instantly share code, notes, and snippets.

@abdilahrf
Forked from me0wday/BlindGraphQL.md
Created October 17, 2023 15:16
Show Gist options
  • Save abdilahrf/c172bf13907ea832bb41e42c0290a422 to your computer and use it in GitHub Desktop.
Save abdilahrf/c172bf13907ea832bb41e42c0290a422 to your computer and use it in GitHub Desktop.

Revisions

  1. @me0wday me0wday revised this gist Jun 30, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion BlindGraphQL.md
    Original file line number Diff line number Diff line change
    @@ -73,7 +73,7 @@ if (process.argv.length === 2) {
    process.exit(1);
    }
    const introspectionSchemaResult = JSON.parse(fs.readFileSync(process.argv[2]));
    const graphqlSchemaObj = buildClientSchema(introspectionSchemaResult);
    const graphqlSchemaObj = buildClientSchema(introspectionSchemaResult.data);
    fs.writeFileSync(process.argv[3], printSchema(graphqlSchemaObj));
    ```

  2. @me0wday me0wday revised this gist Jun 30, 2021. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions BlindGraphQL.md
    Original file line number Diff line number Diff line change
    @@ -46,6 +46,8 @@ python3 -m clairvoyancex -o output_schema.json -w farmed_words.txt -k https://so
    - `-d "mutation { FUZZ }"` changing the initial fuzzing query may help (default `"query { FUZZ }"`
    - `-H "Cookie: somecookie=something"` in case an auth cookie or header is required

    **Bonus note:** Highly recommended to throw the output JSON file into [GraphQL Voyager](https://apis.guru/graphql-voyager/) to get a nice map/view of the available names, types and schema.

    ## 2. Convert JSON schema to .gql schema file

    Here's a quick script to convert the JSON schema file into a .gql file supported by most GraphQL playground apps. Requires [NodeJS](https://nodejs.org/en/download/).
  3. @me0wday me0wday created this gist Jun 29, 2021.
    108 changes: 108 additions & 0 deletions BlindGraphQL.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,108 @@
    # Playing with GraphQL when introspection is disabled

    Quick write up on extracting a GraphQL schema when introspection is disabled. Bits and pieces sourced from various sources. Successfully tested on an Apollo instance.

    **TLDR:** Some GraphQL instances provide name autocomplete suggestions. Some peeps have written tools to automate the extraction process. (ref [https://youtu.be/nPB8o0cSnvM](https://youtu.be/nPB8o0cSnvM)).

    ## 1. Bruteforce schema without introspection

    First step is using a tool called clairvoyance by [@nikitastupin](https://github.com/nikitastupin) ([https://github.com/nikitastupin/clairvoyance](https://github.com/nikitastupin/clairvoyance)). I found the main repo to lack error handling and support for additional features such as proxy.

    The following fork by [@mchoji](https://github.com/mchoji) ([https://github.com/mchoji/clairvoyancex](https://github.com/mchoji/clairvoyancex)) has fixed most of these issues.

    ### Install

    ```bash
    git clone https://github.com/mchoji/clairvoyancex.git
    cd clairvoyancex
    pip3 install -r requirements.txt
    ```

    ### Get/create wordlist

    I recommend creating a compound wordlist, this can include general english words, common API objects etc. We also want to create a target specific list based on the site (as mentioned on the clairvoyance repo). Eg.

    1. Grab one of the wordlists from the most common English words extracted from Google: [https://github.com/first20hours/google-10000-english](https://github.com/first20hours/google-10000-english)
    2. Make a target specific list. I found the best way was to grab the following:
    - JS files from the target site
    - Any existing GraphQL queries and responses
    - HTML source files

    Put them all together and run a Regex query to grab all possible names `[[_A-Za-z][_0-9A-Za-z]*](http://spec.graphql.org/June2018/#sec-Names)`. Because we will have a lot of junk there, I recommend removing any short words with `sed -nri.bak '/^.{3,}$/p' farmed_words.txt`.

    3. Put the two lists together `cat google-10000-english.txt >> farmed_words.txt`.

    ### Run

    ```bash
    python3 -m clairvoyancex -o output_schema.json -w farmed_words.txt -k https://somesite.url/graphql
    ```

    **Note:**

    - `-k` ignores certificate errors on HTTPS sites
    - You may need the following flags too:
    - `-t 20` if the site is slow to respond add a longer timeout
    - `-d "mutation { FUZZ }"` changing the initial fuzzing query may help (default `"query { FUZZ }"`
    - `-H "Cookie: somecookie=something"` in case an auth cookie or header is required

    ## 2. Convert JSON schema to .gql schema file

    Here's a quick script to convert the JSON schema file into a .gql file supported by most GraphQL playground apps. Requires [NodeJS](https://nodejs.org/en/download/).

    **Setup commands**

    ```bash
    npm init
    npm install graphql --save
    touch index.js
    ```

    **index.js**

    ```jsx
    const { buildClientSchema, printSchema } = require("graphql");
    const fs = require("fs");
    if (process.argv.length === 2) {
    console.error('Expected at least one argument!');
    process.exit(1);
    } else if (process.argv.length === 3) {
    console.error('Syntax: node index.js input.json output.gql');
    process.exit(1);
    }
    const introspectionSchemaResult = JSON.parse(fs.readFileSync(process.argv[2]));
    const graphqlSchemaObj = buildClientSchema(introspectionSchemaResult);
    fs.writeFileSync(process.argv[3], printSchema(graphqlSchemaObj));
    ```

    **Run**

    ```bash
    node index.js <input.json> <output.gql>
    ```

    ## 3. Import into Altair

    [Altair](https://altair.sirmuel.design) is a GraphQL client that helps with a lot of the query building, autocomplete and refactoring of GraphQL queries. The Chrome plugin is invaluable for testing as it can be run inline with your proxy server and side by side on your web app test.

    1. Grab and install the Chrome plugin [here](https://chrome.google.com/webstore/detail/altair-graphql-client/flnheeellpciglgpaodhkhmapeljopja?hl=en)
    2. Open the Altair view in Chrome
    3. Chuck your GraphQL endpoint in the POST/GET text box and press `Docs`

    ![https://i.imgur.com/GoJtIKT.png](https://i.imgur.com/GoJtIKT.png)

    4. Hit the 3 dots and Load the .GQL schema file we generated earlier.

    ![https://i.imgur.com/RkTbY80.png](https://i.imgur.com/RkTbY80.png)

    5. The bruteforced schema will now be loaded into the Docs view and will help you navigate names and generate queries. If you hover over a Query/Mutation name or type it will let you `Add query` to your Query request pane.

    ![https://i.imgur.com/eAYGXPc.png](https://i.imgur.com/eAYGXPc.png)

    **Tip:** If you get errors when sending a request saying that a field requires subfields, put your cursor on the specific field in the query and hit `Ctrl+Shift+Enter` to auto populate the type.

    ## Summary

    Das' it. My leeched notes to help with GraphQL inspection when introspection doesn't exist. Thanks to a few people for pointing out some tools and refs ([@infosec_au](https://twitter.com/infosec_au), [@nnwakelam](https://twitter.com/nnwakelam)).

    My boring Twitter [@me0wday](https://twitter.com/me0wday)