Your Publicly Accessible Google API Key Could Be Giving Hackers Access to Your Files and Photos!

We’ve all seen them before, those long, seemingly random strings of characters starting with AIza. Yes, that’s right, the ubiquitous Google API key.

 

Table of contents

Why are Google API keys everywhere?

How do you protect your own Google API keys?

How to test Google API keys?

About the Author


Google is one of the largest organizations in the world and as such, they have an API for literally everything. What this means for security researchers is that Google API keys are also literally everywhere. 

If you're a developer, you probably have a few Google API keys of your own. Even if you’re not a developer, chances are you've seen a Google API key somewhere on the Internet, be it in the source code of a website, app, blog post, or forum discussion. These API keys are a necessary evil - they allow us to access Google's vast resources, but they can also be a source for potential abuse.

Our spiderSilk Resonance product scans the open internet on a continuous basis, giving us great insight into who runs what and where. As such, we regularly find Google API keys associated with our customers. Sometimes those Google API keys are scoped well beyond simply displaying information from Google Maps. By the end of this article, I hope to show how simply exposing a Google API Key through your website’s source code can end up costing your organization.


Why are Google API keys everywhere?

There are a few reasons.

First, many developers use public code repositories like GitHub to store and share their code. And when code is stored in a public repository, it is typically accessible to anyone. This means if a developer is using a Google API key and includes it in their code, anyone with access to the code can see the key.

 

Second, many developers use online forums and other public places like StackOverflow to ask questions and share information about their code. And when code is shared in a public place, again, it is typically accessible to anyone.

 

Then again, some developers expose their key directly in their website's source code on their production web server so anyone who visits their website can view the key, instead of storing the key in a file outside of their web-accessible directories or in an environment variable, as Google suggests.

 

Finally, some developers include their API keys in their code when they share it through a private message or maybe through one of those sites like PasteBin. This can happen if they forget to remove the key before sharing their code, or if they mistakenly include their key in a comment or other non-code text.

 

What can we do about it? How do you protect your own Google API keys?

First, never include API keys in your code. Anyone with access to your code, be it through your public website, a forum post asking how to resolve an issue, or a private message to an associate, will now have access to your API key.

Second, be careful about where you store your API keys. Don’t put them on a sticky note attached to your monitor, a text file on your PC desktop, or in the README.md of your GitHub repository.

Lastly, read Google’s best practices for securing your API keys. It’s an amazing resource and it absolutely cannot help you if you do not read it.

 

How to test Google API keys?

I’m glad you asked. When I queried our internal tools, we found nearly 300,000 Google API keys, and that’s just from the public Internet on ports 80 and 443 with a baseURL of /. Since I didn’t crawl past /, you’ll have to imagine how many Google API keys are lurking in other places like GitHub, GitLab, BitBucket, PasteBin, StackExchange, or even inside of your favorite mobile app. 

If you have gone looking and found your own Google API key floating around the Internet, the first thing you should do is not panic. Seriously? Seriously! You can and should, if you have not already done so, add restrictions to your key so that it can only be used from certain IP addresses or domain names. Google also lets you set billing limits too, but we aren’t going to talk about that since you’re now armed with enough information to continue down that path on your own.

If you found someone else’s Google API key floating around the Internet, chances are, you won’t get a big fat bug bounty. In fact, most bug bounty programs will mark the issue as N/A or maybe Informative if they’re feeling generous. We all know there is malicious intent all across the Internet, however, it’s never enough to prove intent, we need to show some sort of impact, therefore, I wrote a nuclei template for this very task. 

id: api-google-drive

info:

  name: Google Drive API Test

  author: geeknik

  severity: info

  reference:

    - https://developers.google.com/drive/api/guides/about-sdk

  tags: token-spray,google,drive

 

self-contained: true

requests:

  - raw:

      - |

        GET https://www.googleapis.com/drive/v3/files/{{randstr}}.txt/%3fkey={{token}}&supportsAllDrives=true HTTP/1.1

        Referer: {{referer}}

        Content-Type:application/json

    matchers:

      - type: word

        part: body

        words:

          - 'File not found: {{randstr}}.txt.'

This is a simple template that checks for the existence of a file that doesn’t exist, very non-invasive, and very easy to use:

“nuclei -t token-spray/api-google-drive.yaml -var token=$google_api_key -var referer=$host_name_or_ip”

Unfortunately due to the way this particular API works, you have to include a referer or the test will simply fail. Feel free to improve upon my template and submit a PR to the community repository

I was also tasked with creating a CSV file containing the IP address, the Company Name, and the Google API Key so we could have a list of organizations in a central location when it came time to start sending notifications. Considering the amount of data I had to go through, I felt as though Python was a good choice for automating this task. 

#!/usr/bin/env python3

import csv

import re

import os

import sys

import subprocess

from ipwhois import IPWhois

from time import sleep

import random

 

def main():

    ip_list = []

    with open("input.txt", "r") as f:

        for line in f:

            line = line.strip()

            match = re.search(r'[0-9]+(?:\.[0-9]+){3}', line)

            if match:

                ip_addr = match.group()

                print("IP Address: {}".format(ip_addr))

                match = re.search(r'AIza[0-9A-Za-z\-_]{35}', line)

                if match:

                    google_api_key = match.group()

                    print("Google API Key: {}".format(google_api_key))

                    ip_list.append({'IP Address':ip_addr, 'Google API Key':google_api_key})

    print("\n")

    print(ip_list)

    print("\n")

 

    with open("output.csv", "w") as f:

        writer = csv.writer(f)

        writer.writerow(['IP Address', 'Company Name', 'Google API Key'])

        for ip in ip_list:

            whois = IPWhois(ip['IP Address'])

            results = whois.lookup_whois()

            company_name = results['nets'][0]['description']

            writer.writerow([ip['IP Address'], company_name, ip['Google API Key']])

            print("IP Address: {}\nCompany Name: {}\nGoogle API Key: {}\n".format(ip['IP Address'], company_name, ip['Google API Key']))

            sleep(random.randint(3,10))

 

if __name__ == "__main__":

    main()

 

This script takes nuclei output, grabs the IP address and the Google API Key from each line and performs a WHOIS lookup on the IP. Here is an example of the output produced in the console. 

And an example of the CSV output.

Of the nearly 300,000 Google API keys I discovered in our data, many were duplicates and many were locked down. However, I was able to break it down by API for you:

API

# of API Keys

Cost for 1000 requests

Books API

29

$0

Custom Search API

185

$5

Directions API

9517

$5

Elevation API

8653

$5

FCM API

0

N/A

Find Place From Text API

11544

$17

Distance Matrix API

9008

$5

Geocoding API

20

$5

Geolocation API

0

N/A

Maps Embed API

18

$0

Maps Embed Advanced API

18

$0

Nearby Search API

11547

?

Nearest Roads API

1614

$10

Place Autocomplete API

11550

$2.83

Place Details API

11546

$17

Place Photo API

11526

$7

Playable Locations API

0

N/A

Directions API

1614

$5

Safe Browsing API

0

N/A

Speed Limits API

18

?

Maps Static API

6726

$2

Street View Static API

4765

$7

Text Search Places API

11545

$32

Timezone API

1805

$5

Your results may vary due to network conditions, rate limits, or IP reputation. Plus, some of the API keys likely have some sort of an origin or referer restriction in place. We’ve responsibly disclosed these findings to the affected organizations while also extending an invitation for them to peer into their attack surface using our spiderSilk Resonance product.

Now for the part, everyone has been waiting patiently for, “How many Google API keys are valid for Google Drive?” Well, first off, we have to worry about passing a referer to this particular Google API, so we had to write more Python:

import sys

import os

def main():

        if not os.path.exists(sys.argv[1]):

                print("[-] File does not exist")

                exit(0)

        f = open(sys.argv[1], "r")

        for line in f.readlines():

                line = line.split()

                bash_script = "nuclei -silent -t token-spray/api-google-drive.yaml -var referer=" + line[3] + " -var token=" + line[4]

                print(bash_script)

 

if __name__ == "__main__":

        main()

 

To run the script:

python3 nuclei2bash.py nuclei-input.txt | sed ‘s/[][]//g’ > api-google-drive.sh

Our newly created bash script looks properly formatted, so let’s run it!

Now that the heavy lifting is done, we found 1,419 Google API keys on the Internet which have access to Google Drive:

If you’re interested in doing your own research into Google API keys, there are currently, as of this writing, 24 Google API token-spray templates in the public repository.

 

The security advice in this article is valid for any API key, however, you should keep in mind that most organizations aren’t going to let you place as many restrictions on your API key as Google does, so in the end, you really should take better care of your API keys. Good luck out there!


spiderSilk is re-imagining threat detection from a multi-solution, resource-intensive proposition today, to an automated, intelligent, cost-effective & easy to deploy one. Schedule a complimentary external attack surface analysis today and let us show you what Resonance has to offer with ZERO setup and 100% non-intrusive!

About the Author

Brian is a Senior Security Engineer with spiderSilk, an emerging leader in attack surface management and threat detection. Brian is an expert in his field and before coming to spiderSilk, helped launch OpenDNS Umbrella before they were acquired by Cisco. He has decades of experience in law enforcement, security research, and system administration. He has been awarded many CVE since 2016 for his research into Firefox, OpenSSL, cURL, PHP, Perl, and more!

© 2024 All Rights Reserved spiderSilk Security DMCC.

All trademarks and company names are the property of their respective owners.