Shopping Turned Into Breaking In Store's Network

(This vulnerability report was submitted without bug bounty program, hence I am writing this as a blog. Walk through with me on my journey on how I discovered it.)

I love seeing how things work underneath, and websites are no exceptions.

Prelude

Spring is coming, and it’s time for me to look for some new looks. While browsing several online stores for new clothes, out of curiosity, I analyzed how its frontend code fetches data.

One of them caught my eyes because it uses GraphQL. I love using GraphQL not only because it makes my web development easier (yes, I am also a full-stack developer), but it also could bring a whole lot more possibilities.

Redaction

Without revealing the identity of the company, let’s refer it as “MysteriousFashion” from now on.

Elaborations

GraphQL Resolvers

GraphQL is designed to be a thin layer for data fetching between frontend and backend. The way its resolvers work make it easy to fetch data from any source. It could be programmed to return data from a database, an external resource from the internet, or even a random number!

An interesting query field

MysteriousFashion uses GraphQL to take an URL as input, fetches the resource from the URL, and returns the Base64-encoded data from the resource. It is designed for fetching external image resource as Base64-encoded data URLs.

In a sense, this GraphQL query field (let’s refer it as bee from now on) acts as a proxy of given external resource URI.

Explorations

Can it fetch my selfie hosted somewhere else?

Since bee accepts a full URL as an input, I wonder if it also accepts URLs of any external image. So I tested it with an URL to my profile image file on Facebook. It worked! After decoding the Base64-encoded data back to its original form, not only the image data is recovered, so is the metadata (e.g. EXIF).

Can it fetch a file that’s not an image?

The fact it retains the metadata made me wonder if it just returns the raw data from the file without stripping anything. Hence base on this hypothesis, I am also wondering if the bee query field is also capable of returning non-image resources. So I fed it with Google’s human.txt file hosted on Google, and it worked as well!

Security risk found

This exposes the security risk of MysteriousFashion’s server being resource abused or made to proxy anything unaware.

Dox the server

Since it accepts any URLs as mentioned, I spun up a honeypot server to capture info from the requests made by the MysteriousFashion server. And I fed bee query field with a dummy URL on the honeypot server. The server IP is captured.

Based on the results of reverse DNS lookup, this IP belongs to Amazon Web Services (aka AWS) and this IP belongs to an AWS EC2 instance.

Server Side Request Forgery

According to AWS EC2 Documentation, their EC2 instances have access to a special internal IP 169.254.169.254 for accessing the instance metadata and user data from within the instance itself.

Let’s give it a try!

Server Request

HTTP POST /graphql
Host: mysteriousfashion.redacted

query {
  bee(url: "http://169.254.169.254/latest/user-data") {
    data
  }
}

Server Response (after decoding the Base64 string)

// The actual user data within the EC2 instance!!!
// REDACTED for obvious reason.

From this and other resources proxied from the internal IP, it leaked the software stack, the internal domain, server logs, etc out in the wild!

The thing is, this GraphQL query could be done without even logging in!

I know if I dug deeper, I could have found other super sensitive info.

I am both shocked and amused by this SSRF. So I went ahead to submit a vulnerability disclosure to MysteriousFashion.

Personal Anecdote

Although this online store does not have a formal bug bounty program, I still submitted it regardless because I believe preventing actual data breaches from happening is a right thing to do, regardless of monetary return.

Timeline

2019-01-08 03:54 HKT - Report Submitted

2019-01-09 17:50 HKT - Further Investigation by MysteriousFashion

2019-01-10 13:47 HKT - Fixed by MysteriousFashion

2019-01-10 13:47 HKT - Thank-you note and reward issued by MysteriousFashion