A Pentester is usually expected to be a higher than average user in terms of interaction with an endpoint. For that reason, I decided to add an intermediary step between "Discovery" and "Exploiting" called "Interaction."
Today's article contains three real-life examples that hopefully provide insight into the pentester mentality when dealing with GraphQL endpoint.
Prerequisites: Play Around with the endpoint
Becoming a higher-than-average user requires passing through being an average user first. For that, there is no quick or ordered guide. You have to get your hands dirty, try interacting with the endpoint, send queries, access the front-end, understand what queries do, create or change some data through mutations, and get familiar with the available types.
This knowledge is essential when developing potential attack vectors and understanding the expected behaviors.
Determining if a Query Executed
One endpoint I was pentesting had a query that fetched the metadata of a webpage given a URL, and I needed a way to determine if a query with a specific input was being executed or not.
The query was the following:
but running the same query with a random string as the url results in nothing as a response:
So a valid URL will return some data, but a random string will return nothing, and so did the malicious URL I entered, but one essential detail caught my attention ... it was the timing.
A request that triggers a request would take ten times more to execute than a request that doesn't, so this 900-millisecond discrepancy was my indicator for determining the best SSRF payload.
Finding the Underlying Code for a Closed Source Project
While doing my "Playing Around" on an endpoint, a certain query invoked an error and returned a stack trace.
At first glance, not much could be implied, but a small curiosity is necessary, so I asked about the only unfamiliar word in the stack trace, what is "saleor"?
A quick search showed that "saleor" is an open source GraphQL commerce platform. Digging deeper, I finally found "/saleor/graphql/decorators.py" on Github.
And so I partially understood the back-end architecture and had default parameters to test, such as JWT passwords set by "Saleor" if the endpoint developer missed updating them.
Vulnerability: Multipath Evaluation
Lets start with a little technical background.
Consider the following schema:
Let us also assume that the developer's goal is to restrict access to the object "character" one approach used is to restrict access through a check placed in every query or object that accesses a "character."
In our schema's case, we will have to add a check in five locations:
- "character" query
- "characters" query
- "results" field of the "characters" object
- "resident" field of the "Location" object
- "characters" field of the "Episode" object
And every time an arrow towards the "Character" object is added.
But along with the growth of the API in terms of sheer size and complexity, forgetting to place a check for a newly added query/object becomes more and more probable.
There emerges "Multipath Evaluation," where an attacker will be able to fetch information that they are not authorized to access through a path that doesn't have enough authorization checks.
To understand the extent of this vulnerability, let us see a real-life example:
We have an endpoint (introspection was disabled) of a platform where clients register, so naturally, directly accessing client information without any form of authentication should be forbidden:
And that is indeed the case. But while in the "Playing Around" step, I stumbled on the "Banks" query, which was essentially a trivial record between the server and clients, but "client" was in its fields!
Finally fetching "client" from the "banks" query actually yields results.
and just like that we bypassed authentication while "Playing Around"
Getting familiar with an endpoint is like mastering a language. The better you get in a particular language; you'll spend less time thinking of the means to convey an idea and more time on that idea itself. Similarly, for an endpoint, the better you are in interacting with that endpoint, the more time you have to think about possible attacks against it.