THREAT RESEARCH BLOG POST
Avoid Detection with Shadow Keys
July 23, 2018 | | arikkublanov
CyberArk Labs has discovered a vulnerability using Google APIs. This blog post introduces the vulnerability, which we call “shadow keys.”
The vulnerability was reported to Google by CyberArk Labs in January 2018 through the responsible disclosure process, and subsequently fixed by Google. A detailed timeline is below.
Google automatically creates API keys that are associated with a user’s project. Shadow keys are essentially illegitimate “copies” of these keys. Because valid API keys are created unbeknownst to users, they would also be unaware of any shadow keys.
This was a significant vulnerability because if an attacker were to obtain a Google API key through nefarious actions, they could then create a shadow key to access applications as if it was the original user key. The attacker could also bypass the detection/billing system of some Google API services.
The shadow key technique described in this blog post enables an attacker or a malicious user to find, enumerate and create a list of such shadow keys using Google services.
Google APIs Explained
The API key allows you to monitor your application’s API usage in the Google API console. For a standard plan customer, the API key gives access to a generous free daily quota, as well as the option to pay to increase the daily quota. For a premium plan customer, a user must use an API key to access all the custom features and benefits of the premium plan.
Registering for an API key ensures that Google can contact the user about the application, if necessary. In the Google API console, the user can also look up an existing key or view a list of enabled APIs. By using an API key to authenticate applications, users can manage all of their APIs in the Google API console, access real-time usage data and 30 days of historical usage data for their application in the console, and view usage reports with more than 30 days of data in the Google Cloud Support Portal.
The API key has two major roles:
- Project identification — Identify the app or the project that’s making a call to this API.
- Project authorization — Check whether the calling app has been granted access to call the API and has enabled the API in its project.
By identifying the calling project, API keys enable usage information to be associated with that project, and allow the Google Extensible Service Proxy (ESP) to reject calls from projects that haven’t been granted access or enabled by the API (see Figure 1).
Figure 1- Google API key Identification and Authorization.
Shadow Key Discovery
Google API loader allows you to easily import APIs and specify additional settings (such as language, location, API version and so on). In addition to the basic loader functionality, savvy developers can also use dynamic loading or auto-loading to enhance the performance of their application.
Prior to Google’s fix of the shadow key vulnerability, CyberArk Labs found the following API service located in Google’s script loader. According to Google at the time, “Google Loader no longer requires keys. You don’t need to make any changes if you’re already using one, but if you choose you may simply remove the key parameter from your requests. Note that some APIs use other keys (e.g., from the Google APIs Console) which are unaffected by this change.”
The API that enumerates the valid API keys was meant to be used for old Google API keys, which are very different in structure. The API sent back information on the validity of new Google API keys that were generated at the console.developers.google.com site.
For a valid Google console API key, it returned google.loader.KeyVerified = true:
And for an invalid API key, it returned google.loader.KeyVerified = false:
Using this service, we were able to enumerate valid and invalid API keys.
According to Google, “Enumerating API keys is infeasible by design. A 64-alphanumeric key would have 36^64 combinations, a brute force attack is not even feasible given the time constraints to discover valid keys.”
However, we found it possible to forge a shadow key when the original key was malformed. We used a vector that we called “Malform,” which allowed us to rotate one valid key from left to right from index=6 until the end of the key index=39, and each time we could change one character to be from the following characters: abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.
The algorithm is best demonstrated in the following screen shot.
As a result, we received three more keys – the shadow keys. Only the character in the index of 39 was changed, and all three were valid keys that could be used to access the user’s application data.
For proof of concept, we created a real Google API key. To start, we had only one key on our project as the image below indicates.
We rotated it, and then got our three shadow keys (see image below).
We used the following services to get information regarding the API keys, such as project number, project name and configuration settings on that key.
All of the shadow keys were associated with our project ID 131071927382, and not presented on the project credentials as shown above.
Shadow Key Usage
We created a Google web application hosting our simple Google map script, which displayed the location from where any user browses using the original key generated to us by Google API services. We used the original API key on our code:
Any user who browsed to this web page was able to receive its location on the browser.
The server responded to the user and we were able to see the responses using the “response code” filter on the owner project dashboard.
Next we used one of the shadow keys that we discovered earlier – AIzaSyBYgdZ_Q8Rgi1XT1cR5PLn7Jh94xD6CbAF – in our application code.
We were able to browse to the site because the shadow key is valid. It worked.
On the owner dashboard you can see that the server responded to the user requests using the shadow key.
But when using the credential filter, there was no detection of the shadow key and it wasn’t logged.
We made more requests with the shadow key and with our original API key.
We gained access to the API with the shadow key without being detected. All the blank spots were made with the shadow key.
In the following screen shots, you’ll notice that we were limited in the “Quotes” tab by the Map loads as users can only use up to 20 loads per day.
When using the original key within our code, the system detected that the user made and exceeded all of their permitted daily loads.
A red line was displayed on the owner UI, indicating that they exceeded the daily limit.
But with our shadow key, the system didn’t detect that we exceeded our Map loads per day.
No red line was displayed on the owner UI.
We were able to access the application, bypass detection and avoid payment – even after we had exceeded our daily request limit – because the shadow API key didn’t belong to the owner’s application according to the credentials tab of the owner’s dashboard.
Using only a single valid Google API key, it was possible to create shadow keys that went undetected and could avoid payments to Google.
With only a valid key, an attacker could create shadow keys and sell them to other malicious actors, giving them the ability to access the same applications and data as the original valid key, but go undetected by Google.
As stated above, CyberArk Labs followed the rules of responsible disclosure and alerted Google to the vulnerability, which it has since fixed. It’s now no longer possible to enumerate keys on Google’s script loader. CyberArk Labs also recently tested several shadow keys that were created prior to Google’s fix, and they no longer work.
- January 28, 2018: Shadow keys concept reported to Google
- March 9, 2018: Google responded that a bug was filed with the API team
- March 20, 2018: Google confirmed that shadow keys is an issue and rewarded the CyberArk researcher with a bug bounty as part of Google’s Vulnerability Reward Program
- April 3, 2018: Google indicates this issue will be addressed in a few weeks
- May 23, 2018: CyberArk researcher noticed that the vulnerability was fixed
- May 24, 2018: Google stated that they issued a fix for shadow keys