For the complete documentation index, see llms.txt. This page is also available as Markdown.

BugLot

Mystery Challenge (Medium) - by Leighlin Gunner Ramsay

The following post by 0xb0b is licensed under CC BY 4.0


Scenario

BugLot's own security page calls the platform hardened and independently audited, and at a glance it holds up. But a company that catalogs everyone else's vulnerabilities got careless with its own data. A program's public page is only the slice they chose to show; the rest of the record is still sitting there for anyone who looks past the listing.

Summary

Summary

The target is BugLot, a vulnerability-disclosure platform whose own GraphQL API leaks more than its public listings show. Recon through Burp reveals the site runs on Apollo Server, with the main page and leaderboard both backed by GraphQL. Standard introspection (__schema, __type) is blocked.

The core technique is error-based schema reconstruction. Apollo's validation errors leak type names, field names, and argument signatures even with introspection disabled. Querying program without subfields leaks its return type and argument signature (program(handle: String!) → Company); querying bogus fields triggers "Did you mean" suggestions that reveal real field names, including a hidden __key/apikey field. Extracting programs { handle apikey } yields API keys, but no obviously usable root field, so the keys sit idle.

Clairvoyance then automates the same validation-error oracle with a larger wordlist and recovers what manual probing missed: a hidden employees(key, handle) root field returning a hidden Employee type with a sensitive internalNote. Supplying the leaked API key as the key argument unlocks the employee records and the final flag.

Attack Path

Recon

We'll start by manually visiting the page and redirecting the request to Burp Suite through our proxy.Next, we'll look at the requests in the HTTP history.

It looks like we only have one main site and one leaderboard available.

When we visit the respective pages, we see that a GraphQL request is made and that we receive the result back as JSON.

We'll continue by enumerating the GraphQL schema. But standard introspection query returns a hard block from the Apollo Server.

We see also __type is also blocked.

We can research on that topic on the following resource, but the bypasses mentioned here do not work.

Exploit

Apollo's validation errors leak type names, field names, and argument signatures even with introspection disabled. So querying a field without its required subfields forces Apollo to leak the return type and argument signature.

This reveals: program(handle: String!) → Company without any introspection.

By querying a non-existent field it triggers Apollo's "Did you mean" suggestions, leaking real field names.

And probing with __key triggers a suggestion for a hidden field that was not in any standard wordlist:

Since we found the apikey field we try to request that. We extract the leaked API keys from all programs. At this point we had leaked credentials but no way to use them, manual enumeration had not found any root field that accepted them.

Our manual enumeration has limited coverage so we switch to Clairvoyance which automates the same validation-error oracle with a much larger wordlist:

Clairvoyance discovers a hidden root field and type that manual probing missed:

The reconstructed schema revealed what we missed A hidden Employee record with the internalNote field:

We try to query for the internal note, but without success. A key is required.

The employees field requires a key argument, this might be the API key we leaked from Company.apikey:

Providing the leaked API key grants us access to employee records and their internal notes including the final flag.

Last updated