Modern web applications require a host of additional services to function and fulfil their objectives. These additional services have historically been run within the same server, process or as obtuse functions within the same codebase. Over the last decade or so, these monolithic applications have broken away to lead the way for microservices based architectures which allow each major function of the applications logic to exist as an independent function having its own compute and resources.
Cloud service providers have used this need of running applications as micro services to build out managed services that are owned and operated by the service providers but with the data provided by the customer. From a hacker point of view, new attack surfaces have replaced older easier ones. The access between different microservices and the flow of data and commands is completely transparent to the user (and the attacker). It is therefore, an interesting (and often sought after) hacker objective to escalate privileges within the cloud and to escape to the cloud layer so that access to these other micro services and their data is obtained.
Example app setup
Let’s take a look at an overly simplified example of a web app hosted on the Google Cloud. The part of the application visible to the world is just the tip of the iceberg in most cases. As an attacker, the primary avenue of access would be through the web application.
The web app interacts and accesses data and functionality across the cloud platform using access tokens that are either stored as environment variables on the compute instance or generated temporarily by accessing a metadata endpoint. Applications running on the VM use a service account that is attached to the compute instance to call Google Cloud APIs.
When configuring a compute instance, a service account is attached to the instance whose permission level can be configured. The default setting of “Allow default access” allows access to a few services including read access to Cloud Storage.
However, the only way to access the service account token is from within the compute instance by making a GET request with the “Metadata-Flavor: Google” header to “http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token“.
For an attacker, this would be possible via a Server Side Request Forgery (SSRF) that allows HTTP header control or a Remote Code Execution bug that would allow cURL or wget execution.
A vulnerable app
Consider the following application that serves as a simple app that fetches the HTTP headers of the domain that you provide.
Functionality of this type is often vulnerable to Server Side Request Forgeries (SSRF). However, since the functionality only retrieves HTTP headers, the actual functionality itself is not of great use to an attacker. The functionality, however, is also vulnerable to a command injection that allows an attacker to pass and execute arbitrary commands on the server.
A user input of ”example.org;id” shows the below output
Using a user input of example.org;curl -H “Metadata-Flavor:Google” ”http://metadata.google.internal/”, it is possible to interact with the metadata endpoint.
Next, making a request to ”http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token” will generate a token for the service account attached to the instance on which the app is running. This token can then be used to make requests to the Google Cloud Platform and escape to other services.
You can make a request to ”http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/scopes” to get a list of scopes the token is valid for. As mentioned earlier, the default scope token gives read access to Cloud Storage that can be used to then pilfer data.
Note that all the cURL requests have the mandatory “Metadata-Flavor:Google” HTTP header, without which the HTTP request will fail.
(Ab)using the token to escape to the Cloud Platform
Once the token is obtained, it can be used in REST API calls to the Google Cloud to retrieve information.
Along with the Google project ID obtained from ”http://metadata.google.internal/computeMetadata/v1/project/project-id”, the token allows read access to buckets as shown below
Individual files from buckets can then be enumerated and downloaded as well.
Similarly other services (for which scope is enabled) can be accessed using their API equivalents obtained via the Google Cloud documentation.
There are numerous tools also available that can be used with a token to identify what access is enabled, essentially making GET requests to every list and get REST API across Google Cloud services and see if which of them return data.
Attackers are constantly on the lookout for ways of subverting defences and to escalate their privileges within any system. Apps hosted on the Google Cloud platform are common targets for attackers as any weaknesses in an app hosted on a compute instance could lead to additional access based on the tokens and credentials being accessible to an attacker post exploitation.
Service accounts attached to instances can often have more privileges than required. Even the default access scope allows for listing of buckets and reading the contents of bucket objects. As infrastructure owners, it is important to ensure service accounts do not have excess privileges, apart from ensuring no web application vulnerabilities exist that could provide server side access to attackers.
Following the principle of least privileges (POLP) and access can help prevent attacks that would allow privilege and access elevation from a web app to the Google Cloud platform.
This article is brought to you by Kloudle Academy, a free e-resource compilation, created and curated byKloudle. Kloudle is a cloud security management platform that uses the power of automation and simplifies human requirements in cloud security. Receive alerts for Academy by subscribing here.