GraphQL Exploitation Techniques | Fintech Bug Bounty — Part 2

0x4KD
4 min readDec 11, 2022

This article is the 2nd part of the “Fintech Bug Bounty” series.

Summary

GraphQL Exploitation Techniques — Generated with Stable Diffusion

After sending the report for the bugs found in Part 1, I had the chance to speak with the technical team and get some insider information: There was a service I hadn’t discovered yet, that was being used only on the mobile application.

I first did install Lucky Patcher on my phone, an application that allows you to back up APK files from applications installed on your phone.

Probably there are better options to do this, but I’ve been using it for over a decade now. Old habits die hard.

I sent the APK file to my computer and decompiled it with Apktool.
This is as easy as running:

sudo apt install apktool
apktool d <apk file>

Having the application decompiled, I opened the folder with Visual Studio and searched for the bank domain.

I was expecting to find, at least, a new subdomain. But that’s when I discovered they had a secondary domain. That’s why I missed the backend service for the mobile application!

Investigating the new domain

They were not using the base domain. The URL that I found in the application code had a production subdomain (f.e: production.medium.com)

This made me think that there could also exist subdomains for other environments. Instead of searching for them manually, I used Security Trails. It’s a great tool I like to use when I don’t want to use fuzzers.

Long story short, I found a development and a testing environment.
And on both of them, there was a GraphQL Playground instance.

Using the GraphQL Playground

Finding a GraphQL Playground can’t be considered a vulnerability (because it is not). We must prove there’s an impact on having it enabled.

However, if there’s a GraphQL Playground, there’s a high chance that Introspection Queries are enabled. These queries are used to fulfil the Documentation section.

An Introspection Query is a GraphQL query that returns information about the developed service. If enabled, it can return every available query, mutation and data type defined in the application.

In a conventional JSON:API, this would be like having an endpoint
called GET /schema that tells you what the available endpoints are, what parameters they need, and what should you be expecting in the response.
But without an official or public documentation site 😉

If you’re running a pentest against a company having an active bug bounty program, this may not be relevant: they may be offering this information on purpose. Instead, it is a big deal for companies that expect to keep this secret.

In this case, I didn’t need to run the Introspection Query because the Documentation section of the GraphQL Playground had plenty of info.
But in a different situation, I would have tried running:

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

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
}
}
}
}
}
}
}
}

You’ll identify if the response is successful or not easily. If it is, you can go to a public Playground website, intercept the Introspection Query request (using Burp, for example) and replace the original response with your result. This will give you a visual interface to investigate the “available endpoints”.

Analysis result

After spending some time looking at the endpoints, I discovered two different issues:

  • In the development and testing environments, there was a query that allowed me to retrieve all the users on the platform. It was not critical, but I could gather the personal information of multiple developers and business clients.
  • In production, there was a query that could be abused to check for existing emails and phones within the platform (PII disclosure, but only if you know what you’re searching for).

And none of this required authentication!

Conclusion

They awarded a bounty for the three vulnerabilities: 2 scored as High, and one scored as Low (The GraphQL Introspection Queries + Playground sites).

However, this is not the end. Some other queries and mutations seemed suspicious, but I couldn’t exploit them because they require authentication. And replicating the login process wasn’t that simple…

But we’ll talk about that in the next chapter!

--

--

0x4KD

Bug Bounty Hunter, Full-Stack Web Developer & Tech Team Leader