How a GraphQL Bug Resulted in Authentication Bypass
GraphQL is a very popular technology stack used by backend APIs of web services and mobile applications alike. Its versatility in batch fetching and updating records makes it simple to implement complex business logic. However, there are many unseen risks when using GraphQL to build APIs. One of the biggest challenges is the enforcement of proper access control.
In this blog, we will investigate an authentication bypass vulnerability report in an e-commerce application API. The researcher, J. Francisco Bolivar, found that he could abuse GraphQL as an alternate channel to escalate privileges and ultimately gain administrative access that can alter content on a front-page promotional banner and details of promotional products.
Along with doing our own research on GraphQL testing and remediation, we've also reached out to J. Francisco Bolivar for a Q&A on this bug report, so snippets from the Q&A will be gem-dropped throughout the blog.
What Is an Authentication Bypass Vulnerability?
An authentication bypass vulnerability is a weakness in a system that fails to protect against unauthenticated access, allowing an attacker to bypass authentication entirely. There are many different attack vectors and vulnerabilities that lead to authentication bypass, such as SQL injection, insecure account recovery flows, or insecure use of cookies, but ultimately the impact is the same.
In this particular instance, the authentication bypass was enabled by an alternate channel: a GraphQL API with little to no access control, which exposed user creation and modification functionality.
Business Impact of Authentication Bypass
The business impact of authentication bypass is typically severe. Depending on the level of access the vulnerability allows one to gain access without authentication, sensitive data could be accessed and manipulated without any accountable audit trail as to who performed them.
In the context of the bug discussed in this post, the impact would depend on how this promotional banner was implemented (via iframes or direct script loading). A malicious attacker may have abused this vulnerability to commit financial fraud, carry out social engineering attacks, redirect users to a different site, steal customer PII (Personally Identifiable Information), or deface the website, leading to financial, reputational, and regulatory consequences for the business.
Details: The Bug Report
The main e-commerce website had a promotion banner managed from a third-party integration, hosted on a separate subdomain but embedded on the main website. The third-party application had a GraphQL endpoint on which introspection was enabled, allowing full enumeration of all its endpoints and capabilities.
GraphQL introspection is a useful feature in development that exposes underlying schema via a query. This includes information such as the nodes and fields, their data types, and the queries and mutations that can be performed. It's also very helpful to any potential attackers, as it allows them to thoroughly enumerate your GraphQL database and potentially perform dangerous actions.
An example introspection query fired from GraphQL Playground
A "mutation" is the GraphQL term for an operation that changes the "graph" (the underlying data). In this case, a mutation called Register was found by the researcher, and used to register a user account. Sensitive actions such as user registration should only be called from a backend, from a registration page well protected with measures such as anti-bot reCAPTCHA and email verification. Enabling a registration functionality from an API is not only dangerous to the application, but in this case, allows more sensitive actions to be taken in the GraphQL endpoint.
Finally, after finding and calling the CreateAdminUser mutation, the researcher was able to access even more functionality of the API, including modification of the banner content and details about the promotional products.
How Hackers Find Authentication Bypass Via GraphQL
GraphQL is a very popular technology, and it's not uncommon to see it in use even if it's not tagged as a technology you can filter programs by on HackerOne. So how and why do hackers find GraphQL Authentication Bypass vulnerabilities?
Q: What is it about GraphQL that makes you want to test it?
J. Francisco Bolivar: Being a bug hunter I am always on the lookout for new technologies that have not yet received much scrutiny from the security community. GraphQL, a newer API design paradigm, stands out because of its unique approach to data retrieval and queries. [...] This capability also creates potential vulnerabilities such as DoS attacks through expensive queries or schema exposing introspection queries. Furthermore, since GraphQL is not as mature or widespread as REST, many implementations may lack robust security measures. Consequently, there exists a vast space for discovering unknown security flaws. My intention in testing GraphQL is to identify these gaps and contribute towards hardening this promising technology’s overall security posture.
Q: Immediately after you realize that GraphQL is being used, what's your next step?
J. Francisco Bolivar: Once I realize that GraphQL is being used, my next step involves a series of reconnaissance and analysis actions to understand the structure, capabilities, and potential security weaknesses of the GraphQL implementation, Some of the steps I use to apply are:
- Schema Introspection: Retrieve and examine the GraphQL schema, to grasp structure, types, queries, and mutations.
- Sensitive Data Analysis: Looking for all sensitive fields that it might handle.
- Query Complexity Testing: We want to make sure that the query complexity of our server is within certain limits and that its depth does not reach too deep so as to prevent potential resource exhausting attacks.
- Authorization Checks: Try to access restricted data or carry out unauthorized operations to find out if there are any high-level authorization bypasses.
- Input Validation Testing: Test input validation by sending crafted payloads that have been hand-crafted to fit the bill.
- Error Message Analysis: Analyze error responses from Web Services in order to find out what kind of information leaks about the underlying infrastructure there may be.
- Subscription Testing: If subscriptions are allowed, test for potential data leakage or unauthorized access while Real-Time data transmission is in use.
As Francisco Bolivar said, once the hacker finds the GraphQL endpoint, the first step is to enumerate any GraphQL endpoints for information about its schema. Note that queries can be sent both in the form of GET or POST requests. In a GET request, the query would be in a query parameter like this:
https://host/graphql?query=query{__typename} |
In a POST request, it would be a request sent to https://host/graphql with the body:
query=query{__typename} |
If the target endpoint is indeed running GraphQL, it would respond with something like:
{"data":{"__typename":"Query"}} |
To test if introspection is enabled, the hacker can send a basic introspection query:
query={__schema{types{name,fields{name,args{name,description,type{name,kind,ofType{name, kind}}}}}}} |
If introspection is enabled, the hacker might paste the returned schema into GraphQL Voyager to visualize the entire graph and the relationships between different types and fields within them, as well as use tools like GraphQL Playground or Postman to see all the queries that can be made.
If introspection is not enabled, insights can still be gained into the schema by analyzing frontend Javascript source code, as the web application making requests to GraphQL endpoints need to know where and how to make them. Using the browser's developer tools, an attacker may utilize the search functionality to search across all source code files on the site for keywords such as "graphql", "query" and "mutation".
Other ways to deduce schema information include brute-forcing and inspecting background HTTP traffic. A Burp extension called GraphQuail automatically analyzes traffic to GraphQL endpoints in Burp live proxy traffic to build a schema file, and it will emulate a GraphiQL or Voyager interface within the target website using an identifier added after the target endpoint.
If the hacker is not getting enough traffic, or doesn't have a frontend website to get legitimate GraphQL queries, they may use a tool called clairvoyance which can brute force potential types in a wordlist, and analyze error messages from GraphQL servers to guess the schema since they can leak names through typo guessing:
While enumerating the schema, the attacker will look for authentication-related mutations that can be performed, such as registration of users, resetting passwords, changing user details (like email), or access permissions (like whether the user is an admin).
Furthermore, they'll likely try to query fields belonging to users that might be sensitive to authentication-related information, such as auth tokens, passwords and MFA secrets that could aid in authentication bypass. During this process, they'll also check for other vulnerabilities commonly present in GraphQL APIs, such as IDORs (Insecure Direct Object References), leaking of sensitive PII, and broken access control.
So there are lots of vulnerabilities in GraphQL systems ripe for finding. But why are auth bypasses a common impact of GraphQL bugs? We asked Francisco Bolivar:
Q: Why is it common for GraphQL bugs to result in auth bypasses?
J. Francisco Bolivar: One often encounters authorization bypasses in GraphQL bugs, because of its query language and schema design which are both flexible and complex. A number of variables explain this:
- Field-Level Granularity: The client is allowed to request particular data fields and nested data from GraphQl within a single query. In such circumstances, not all fields and types undergo equal authentication checks. An ineffective access control logic may determine permissions at a higher level than it can enforce by field or nested objects, accidentally allowing access to sensitive information.
- Complex Schema Structures: GraphQL schemas can be quite complicated with deep nesting of types and relationships. This makes the implementation and maintenance of comprehensive access control rules more prone to oversight thereby resulting in chances of authorisation gaps.
- Introspection Queries: GraphQL supports introspection queries that clients can use to discover the schema by default. Introspections when lacking proper security measures may help attackers find out about hidden fields, types and operations hence giving them valuable information they need to form queries that dodge checking authorizations.
How Can You Avoid GraphQL-Related Bugs in Your Applications?
Disabling GraphQL introspection definitely reduces an attacker's visibility into your application, but there's a game of balance here: if you have a bug bounty program, it may be beneficial to leave it on for testing or staging environments that researchers have access to so that they can quickly find critical issues such as authentication bypass and address the root causes. On the other hand, if you only make your production environment available to bug bounty hackers, then you should turn introspection off to minimize risk.
As for protecting against discovering the GraphQL schema via leaking correct types from suggestions in validation error messages, it's currently not a first-class configuration feature in Apollo (which is one of the most popular GraphQL servers), but there's a workaround using the formatError handler where you can string match for "Did you mean" and change the error message to something more generic.
The root cause of these types of vulnerabilities are, however, not GraphQL introspection, but the broken access control that allowed unauthenticated users to escalate privileges through sensitive mutations which they shouldn't be allowed to call. To address this root cause, authorization must be explicitly specified for each query and mutation in the schema, with the appropriate permission levels (for example, a normal user should not be able to call the CreateAdminUser mutation). The most secure code is code that does not exist: extraneous functionality such as CreateAdminUser should not even exist if it's not needed - the same goes with any other queries and mutations in a large GraphQL database.
Conclusion
With the rising popularity of GraphQL in web applications, it is essential to secure authentication and authorization correctly in GraphQL API, lest it becomes a path for attackers to bypass authentication and escalate privileges. With its large attack surface, GraphQL APIs should be constantly audited to lock down security permissions and remove unnecessary functionality. Fortunately, this severe vulnerability was found and reported via HackerOne's bug bounty program and fixed within a matter of days.
This bug was found during the 2023 HackerOne Ambassador World Cup (AWC), an eight-month-long, competition-driven way to build community engagement, collaboration, and ambassador brand awareness throughout the hacker community. We have some words from Francisco Bolivar about his own experience at the AWC:
Q: What do you like about participating in the Ambassador World Cup?
J. Francisco Bolivar: Participating in the Ambassador World Cup was one of the best experiences I had. It's the most important bug bounty competition, and I'm proud to have won it with my team, Spain. The experience allows me to connect with a global community, challenge and enhance my skills, and engage in meaningful cultural exchanges. Winning the Best Bug prize for AS Watson adds to my pride and highlights the significant impact of our work.
The 2024 AWC is currently taking place! The AWC, led by HackerOne Brand Ambassadors, allows teams of hackers worldwide to identify impactful vulnerabilities in participating customer programs. Reach out to your customer success manager to learn more about how your program can engage in the 2024 tournament!
Secure Your Web Application From Authentication Bypass With HackerOne
The advantage of having a bug bounty program is that hackers from our community constantly test your new applications, domains, and API endpoints as soon as they go live. HackerOne and our community of ethical hackers are best equipped to help organizations identify and remediate Authentication Bypass and other vulnerabilities, whether through bug bounty, Pentest as a Service (PTaaS), Code Security Audit, or other solutions by considering the attacker's mindset on discovering a vulnerability.
Download the 7th Annual Hacker Powered Security Report to learn more about the impact of the top 10 HackerOne vulnerabilities, or contact HackerOne to get started taking on Authentication Bypass vulnerabilities at your organization.
The 8th Annual Hacker-Powered Security Report