{
	"id": "4d04aaf0-e2e9-4952-8195-97b83fbd68a8",
	"created_at": "2026-04-06T00:14:42.486113Z",
	"updated_at": "2026-04-10T03:24:18.006697Z",
	"deleted_at": null,
	"sha1_hash": "5c4d48bb3ac8d6ea7a48ba25605f217d506ffab4",
	"title": "Privilege Escalation in Google Cloud Platform - Part 1 (IAM)",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1570623,
	"plain_text": "Privilege Escalation in Google Cloud Platform - Part 1 (IAM)\r\nBy Spencer Gietzen\r\nPublished: 2020-05-05 · Archived: 2026-04-05 16:30:53 UTC\r\nIntroduction to GCP Privilege Escalation\r\nSimilar to what we’ve done for AWS in the past, this blog post aims to provide a source for privilege escalation\r\ntechniques, this time for Google Cloud Platform (GCP).  Last week we released a blog post, here, that outlines a\r\nprivilege escalation method using the cloudbuild.builds.create IAM permission.\r\nThis week will be a two part blog series, each one outlining different types of privilege escalation in GCP.\r\nChris Moberly (of GitLab) recently released a great blog post on privilege escalation and other attack vectors in\r\nGCP (we’re big fans).  While that focused on methodology and education, this post aims to be Rhino’s list of\r\nspecific IAM permissions enabling privilege escalation, guides how to abuse them, and PoC scripts to demonstrate\r\nimpact.\r\nIf you are not interested in the details of each privilege escalation, consider jumping down to the  new privilege\r\nescalation scanner for GCP. This tool allows you to scan your GCP Organizations/environment for all the methods\r\noutlined here.\r\nNote that none of these privilege escalation methods are vulnerabilities in the GCP infrastructure, but rather\r\nweaknesses in the configuration of a GCP environment.  It’s on the customer to fix the associated IAM issues.\r\nBefore we get started: Access Tokens\r\nOne last thing before jumping into each method. The scripts for each method require an access token from GCP to\r\nauthenticate.\r\nTo fetch an access token for a gcloud CLI-Authenticated user, you can run the following command:\r\ngcloud auth print-access-token\r\nIn a real attack, this access token may come from Server Side Request Forgery, from someone’s local file system,\r\nor similar methods. \r\nFirst (and most exciting) PrivEsc Method:\r\ndeploymentmanager.deployments.create\r\nThis permission is probably the most simple, yet powerful method of privilege escalation that we have found in\r\nGCP. This single permission lets you launch new deployments of resources into GCP as the \u003cproject\r\nnumber\u003e@cloudservices.gserviceaccount.com Service Account, which, by default, is granted the Editor role on\r\nthe project. The kicker is that the iam.serviceAccounts.actAs permission (touched on in more detail below) is not\r\nhttps://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/\r\nPage 1 of 11\n\nrequired, even though you are essentially acting as that Service Account. This was reported to the Google Bug\r\nBounty program, but we were told it is working as intended and that it is a feature of the service.\r\nDeployment Manager allows you to specify resources to create and configure in your projects in YAML or Jinja\r\nformat. It basically can be viewed as an infrastructure-as-code service, similar to CloudFormation in AWS. The\r\nresources we specify use the permissions granted to that Service Account, rather than our own user. So as long as\r\nwe have deploymentmanager.deployments.create, we can take control of that Service Account.\r\nThe screenshot above shows us using a YAML configuration file, which has a Compute Engine VM instance\r\nspecified in it. Then we run the exploit script that reads that YAML file and submits it to GCP. After a few\r\nminutes, Deployment Manager will create that VM instance for us with the configuration we supplied. Take note\r\nthat compute.instances.create is not required to create a Compute Engine instance, because the Service Account\r\nhas the permission and that is all that matters.\r\nThe YAML templates can be customized to include a variety of different resources, so the possibilities of this\r\nmethod are nearly endless. To see what resources are supported, you can check out this link or run the following\r\ngcloud command:\r\nhttps://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/\r\nPage 2 of 11\n\ngcloud deployment-manager types list\r\niam.v1.serviceAccount and iam.v1.serviceAccount.keys would be of particular interest when trying to escalate\r\nprivileges.\r\nThe exploit script for this method can be found here.\r\nIAM-Based Methods\r\nThe Identity and Access Management (IAM) service manages authorization and authentication for a GCP\r\nenvironment. This means that there are very likely multiple privilege escalation methods that use the IAM service\r\nand/or its permissions. We’ll start out with the most simple methods and move into the more complicated methods\r\nas we go.\r\niam.roles.update\r\nIf your user is assigned a custom IAM role, then iam.roles.update will allow you to update the\r\n“includedPermissons” on that role. Because it is assigned to you, you will gain the additional privileges, which\r\ncould be anything you desire.\r\nThe screenshot above shows the custom role “privtesting” only granted iam.roles.update. We then use that\r\npermission to add the iam.serviceAccountKeys.create permission to it, which then is inherited by our user.\r\nThe exploit script for this method can be found here.\r\niam.serviceAccounts.getAccessToken\r\nThis permission allows you to request an access token that belongs to a specified Service Account. We can\r\nescalate privileges by requesting an access token for a Service Account that has more privileges than us. The\r\nfollowing screenshot shows an example of it, where the “iamcredentials” API is targeted to generate a new token.\r\nYou can even specify the associated scopes for the token.\r\nhttps://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/\r\nPage 3 of 11\n\nThe exploit script for this method can be found here.\r\niam.serviceAccountKeys.create\r\nThis permission allows us to do something similar to the previous method, but instead of an access token, we are\r\ncreating a user-managed key for a Service Account, which will allow us to access GCP as that Service Account.\r\nThe screenshot below shows us using the gcloud CLI to create a new Service Account key. Afterwards, we would\r\njust use this key to authenticate with the API.\r\nThe exploit script for this method can be found here.\r\niam.serviceAccounts.implicitDelegation\r\nAs a Service Account, you may not necessarily need iam.serviceAccounts.getAccessToken to get an access token\r\nfor another Service Account. If you have the iam.serviceAccounts.implicitDelegation permission on another\r\nService Account that has the iam.serviceAccounts.getAccessToken permission on a third Service Account, then\r\nyou can use implicitDelegation to create a token for that third Service Account. Here is a diagram to help explain.\r\nhttps://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/\r\nPage 4 of 11\n\nIn short, A has implicitDelegation on B, B has getAccessToken on C, so A is allowed to getAccessToken on C.\r\nThe following screenshot shows a Service Account (Service Account A) making a request to the “iamcredentials”\r\nAPI to generate an access token for the “test-project” Service Account (Service Account C). The “scc-user”\r\nService Account (Service Account B) is specified in the POST body as a “delegate”, meaning you are using your\r\nimplicitDelegation permission on “scc-user” (Service Account B) to create an access token for “test-project”\r\n(Service Account C). Next, a request is made to the “tokeninfo” endpoint to verify the validity of the received\r\ntoken.\r\nhttps://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/\r\nPage 5 of 11\n\nThe exploit script for this method can be found here.\r\niam.serviceAccounts.signBlob\r\nBecause this method (and the next) is very difficult to do by hand, the screenshots will be using the provided\r\nscripts for these methods.\r\nThe iam.serviceAccounts.signBlob permission “allows signing of arbitrary payloads” in GCP. This means we can\r\ncreate a signed blob that requests an access token from the Service Account we are targeting. The script for this\r\nmethod handles all the hard work for you. The following screenshot demonstrates an access token being retrieved\r\nfor a Service Account.\r\nThe exploit scripts for this method can be found here and here.\r\niam.serviceAccounts.signJwt\r\nSimilar to how the previous method worked by signing arbitrary payloads, this method works by signing well-formed JSON web tokens (JWTs). The script for this method will sign a well-formed JWT and request a new\r\naccess token belonging to the Service Account with it. The following screenshot shows the script returning the\r\nService Account’s access token.\r\nThe exploit script for this method can be found here.\r\nhttps://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/\r\nPage 6 of 11\n\niam.serviceAccounts.actAs\r\nIf you are familiar with IAM in AWS, the iam.serviceAccounts.actAs permission is practically equivalent to the\r\niam:PassRole permission in AWS. This means that as part of creating certain resources, you must “actAs” the\r\nService Account for the call to complete successfully. For example, when starting a new Compute Engine instance\r\nwith an attached Service Account, you need iam.serviceAccounts.actAs on that Service Account. This is because\r\nwithout that permission, users could escalate permissions with fewer permissions to start with.\r\nThere are multiple individual methods that use iam.serviceAccounts.actAs, so depending on your own\r\npermissions, you may only be able to exploit one (or more) of these methods below. These methods are slightly\r\ndifferent in that they require multiple permissions to exploit, rather than a single permission like all of the\r\nprevious methods.\r\ncloudfunctions.functions.create\r\nFor this method, we will be creating a new Cloud Function with an associated Service Account that we want to\r\ngain access to. Because Cloud Function invocations have access to the metadata API, we can request a token\r\ndirectly from it, just like on a Compute Engine instance.\r\nThe required permissions for this method are as follows:\r\ncloudfunctions.functions.call OR cloudfunctions.functions.setIamPolicy\r\ncloudfunctions.functions.create\r\ncloudfunctions.functions.sourceCodeSet\r\niam.serviceAccounts.actAs\r\nThe script for this method uses a premade Cloud Function that is included on GitHub, meaning you will need to\r\nupload the associated .zip file and make it public on Cloud Storage (see the exploit script for more information).\r\nOnce the function is created and uploaded, you can either invoke the function directly or modify the IAM policy\r\nto allow you to invoke the function. The response will include the access token belonging to the Service Account\r\nassigned to that Cloud Function.\r\nhttps://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/\r\nPage 7 of 11\n\nThe script creates the function and waits for it to deploy, then it runs it and gets returned the access token.\r\nThe exploit scripts for this method can be found here and here and the prebuilt .zip file can be found here.\r\ncloudfunctions.functions.update\r\nSimilar to cloudfunctions.functions.create, this method updates (overwrites) an existing function instead of\r\ncreating a new one. The API used to update the function also allows you to swap the Service Account if you have\r\nanother one you want to get the token for. The script will update the target function with the malicious code, then\r\nwait for it to deploy, then finally invoke it to be returned the Service Account access token.\r\nThe following permissions are required for this method:\r\ncloudfunctions.functions.sourceCodeSet\r\ncloudfunctions.functions.update\r\niam.serviceAccounts.actAs\r\nThe exploit script for this method can be found here. The output of this script is similar to\r\ncloudfunctions.functions.create.\r\nhttps://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/\r\nPage 8 of 11\n\ncompute.instances.create\r\nThis method creates a new Compute Engine instance with a specified Service Account, then sends the token\r\nbelonging to that Service Account to an external server. This means you don’t need to access the instance at all.\r\nThe following permissions are required for this method:\r\ncompute.disks.create\r\ncompute.instances.create\r\ncompute.instances.setMetadata\r\ncompute.instances.setServiceAccount\r\ncompute.subnetworks.use\r\ncompute.subnetworks.useExternalIp\r\niam.serviceAccounts.actAs\r\nThe first terminal above shows the script being run, which creates a new Compute Engine instance. The bottom\r\nterminal shows our listening server receiving the access token of the Compute Engine Service Account. If you\r\nspecify IP_PORT in the script, the script will automatically listen for the credentials on 0.0.0.0 on the specified\r\nport and print them when they are received, otherwise they will be sent to the host specified in EXFIL_URL.\r\nhttps://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/\r\nPage 9 of 11\n\nThe exploit script for this method can be found here.\r\nrun.services.create\r\nSimilar to the cloudfunctions.functions.create method, this method creates a new Cloud Run Service that, when\r\ninvoked, returns the Service Account’s access token by accessing the metadata API of the server it is running on.\r\nThe following screenshot shows the script being run to create the new Cloud Run service, then the follow-up\r\ncommand being run to invoke the service and retrieve the access token.\r\nThis method uses an included Docker image that must be built and hosted to exploit correctly. The image is\r\ndesigned to tell Cloud Run to respond with the Service Account’s access token when an HTTP request is made.\r\nFor more information on how to set this up for your own attacks, see the respective exploit script.\r\nThe following permissions are required for this method:\r\nrun.services.create\r\niam.serviceaccounts.actAs\r\nrun.services.setIamPolicy OR run.routes.invoke\r\nThe exploit script for this method can be found here and the Docker image can be found here.\r\ncloudscheduler.jobs.create\r\nCloud Scheduler allows you to set up cron jobs targeting arbitrary HTTP endpoints. If that endpoint is a\r\n*.googleapis.com endpoint, then you can also tell Scheduler that you want it to authenticate the request as a\r\nspecific Service Account, which is exactly what we want.\r\nBecause we control all aspects of the HTTP request being made from Cloud Scheduler, we can set it up to hit\r\nanother Google API endpoint. For example, if we wanted to create a new job that will use a specific Service\r\nAccount to create a new Storage bucket on our behalf, we could run the following command:\r\nhttps://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/\r\nPage 10 of 11\n\ngcloud scheduler jobs create http test –schedule=’* * * * *’ –\r\nuri=’https://storage.googleapis.com/storage/v1/b?project=\u003cPROJECT-ID\u003e’ –message-body\r\n“{‘name’:’new-bucket-name’}” –oauth-service-account-email 111111111111-\r\ncompute@developer.gserviceaccount.com –headers Content-Type=application/json\r\nThis command would schedule an HTTP POST request for every minute that authenticates as 111111111111-\r\ncompute@developer.gserviceaccount.com. The request will hit the Cloud Storage API endpoint and will create a\r\nnew bucket with the name “new-bucket-name”.\r\nTo escalate our privileges with this method, we just need to craft the HTTP request of the API we want to hit as\r\nthe Service Account we pass in. Instead of a script, you can just use the gcloud command above.\r\nThe following permissions are required for this method:\r\ncloudscheduler.jobs.create\r\ncloudscheduler.locations.list\r\niam.serviceAccounts.actAs\r\nA similar method may be possible with Cloud Tasks, but we were not able to do it in our testing.\r\nConclusion (and Continuation to P2)\r\nThere are all kinds of privilege escalation methods in GCP (and other clouds), you just need to be creative. This\r\nlist of privilege escalation methods is not a definitive list, because there are likely more methods out there (such as\r\nin GKE, which wasn’t touched on in this post). Again, these are not vulnerabilities in GCP, they are vulnerabilities\r\nin how you have configured your GCP environment, so it is your responsibility to be aware of these attack vectors\r\nand to defend against them. Make sure to follow the principle of least-privilege in your environments to help\r\nmitigate these security risks.\r\nNow go check out Part 2 of this blog series for even more GCP privilege escalation methods!\r\nSource: https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/\r\nhttps://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/\r\nPage 11 of 11",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/"
	],
	"report_names": [
		"privilege-escalation-google-cloud-platform-part-1"
	],
	"threat_actors": [
		{
			"id": "eb3f4e4d-2573-494d-9739-1be5141cf7b2",
			"created_at": "2022-10-25T16:07:24.471018Z",
			"updated_at": "2026-04-10T02:00:05.002374Z",
			"deleted_at": null,
			"main_name": "Cron",
			"aliases": [],
			"source_name": "ETDA:Cron",
			"tools": [
				"Catelites",
				"Catelites Bot",
				"CronBot",
				"TinyZBot"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434482,
	"ts_updated_at": 1775791458,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/5c4d48bb3ac8d6ea7a48ba25605f217d506ffab4.pdf",
		"text": "https://archive.orkl.eu/5c4d48bb3ac8d6ea7a48ba25605f217d506ffab4.txt",
		"img": "https://archive.orkl.eu/5c4d48bb3ac8d6ea7a48ba25605f217d506ffab4.jpg"
	}
}