Mandiant security assessments frequently uncover publicly exposed serverless applications that lack proper authentication. These applications, often Google Cloud Run services and functions, run custom code incorporating third-party packages, making them prime targets for a range of application-level attacks. Successful exploitation, such as through Local File Inclusion (LFI) or Command Injection, can grant an attacker full control over the underlying container instance, establishing a foothold that could lead to a complete compromise of the victim’s cloud environment, according to Google Cloud’s blog.
This analysis details common attack scenarios against exposed serverless functions and outlines actionable guidance for securing these environments. While the focus is on Google Cloud Run, the principles apply universally to any public serverless deployment.
The Threat of Exposed Serverless Applications
Serverless applications, also known as Function-as-a-Service (FaaS), enable organizations to deploy individual code blocks as microservices within a flexible, event-driven cloud architecture without managing the underlying infrastructure. This architecture is crucial for scaling modern applications, including major e-commerce platforms, payment processing, and increasingly, generative AI workflows.
Publicly exposed serverless workloads represent a significant initial access point for threat actors. These services often contain vulnerabilities within their custom code, imported packages, or even the underlying runtime environment. Once an entry point is exploited, attackers commonly attempt Privilege Escalation or Lateral Movement within the compromised environment. Observed techniques include:
- Extracting secrets: Directly from application code or configuration files.
- Reviewing application logic: Identifying further attack vectors or sensitive data.
- Exfiltrating service account bearer tokens: Following successful RCE by targeting the metadata server.
Compromised secrets or service accounts can enable threat actors to pivot to adjacent systems and workloads. Without robust hardening strategies, this could result in a total cloud environment takeover.
Attack Scenarios: LFI and Command Injection in Cloud Run
Detecting Cloud Run LFI Vulnerabilities
In a common scenario, a Python/Flask function running on Cloud Run might accept user-controlled input to open a file without adequate validation. This represents an LFI vulnerability. For instance, a function using a file parameter directly in open():
import functions_framework
@functions_framework.http
def hello_http(request):
request_json = request.get_json(silent=True)
request_args = request.args
if request_json and 'file' in request_json:
file = request_json['file']
elif request_args and 'file' in request_args:
file = request_args['file']
with open(file, 'r') as resp:
filedata = resp.read()
return 'local file data {}!'.format(filedata)
An attacker can exploit this by sending a POST request to retrieve sensitive files. For example, curl -X POST https://cloudrun01-abc.europe-west3.run.app/ -H "Content-Type: application/json" -d '{"file": "main.py"}' would return the application’s source code. This code can then be analyzed for hardcoded secrets, business logic flaws, internal service endpoints, and technology stack details, which may reveal further CVE exposure. Furthermore, standard directory traversal (../../../etc/passwd) can be used to retrieve system files. Key files an attacker might target include requirements.txt, package.json, .env files, application configuration files (for credentials), and application logs.
Mitigating Cloud Run Command Injection and Token Theft
Another critical vulnerability arises when a Python function uses shell execution methods with unsanitized user input, enabling command injection. Consider a function where user input directly feeds into subprocess.run:
import functions_framework
import subprocess
@functions_framework.http
def hello_http(request):
request_json = request.get_json(silent=True)
request_args = request.args
if request_json and 'input' in request_json:
input = request_json['input']
elif request_args and 'input' in request_args:
input = request_args['input']
result = subprocess.run(input, shell=True,capture_output=True, text=True)
return format(result)
An attacker can leverage this to execute arbitrary commands, specifically targeting the GCP metadata service to retrieve the service account’s bearer token. A curl request, such as curl -X POST https://cloudrun02-abc.europe-west3.run.app/ -H "Content-Type: application/json" -d "{\"input\": \"curl 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token' -H 'Metadata-Flavor: Google'\"}", can extract a bearer token valid for one hour.
Once obtained, this token can be used on an attacker-controlled system by setting the CLOUDSDK_AUTH_ACCESS_TOKEN environment variable. If the Cloud Run service operates under the default Compute Engine service account with broad Editor permissions, this token theft can lead to a full GCP project takeover, allowing attackers to:
- Read, write, and delete most GCP resources.
- Deploy new services or modify existing configurations.
- Access secrets and encryption keys.
- Exfiltrate data from accessible storage systems.
- Establish persistent backdoors.
Hardening Recommendations: GCP Serverless Security Best Practices
Mandiant recommends a parallel approach to effective serverless security, combining secure development practices with compensating runtime controls.
-
Secure Software Development Lifecycle (S-SDLC): Integrate security scanning, code reviews, and least-privilege IAM into CI/CD pipelines. Implement continuous security testing before deployment.
-
Vibe Coding Security: For AI-generated code, ensure multi-layered security enforcement. Isolate AI experimentation in dedicated sandbox environments, enforce strict data egress controls, restrict development to approved IDEs with human-in-the-loop capabilities, and utilize verified plugins under least privilege to mitigate Supply Chain Attack vulnerabilities. Adherence to S-SDLC controls and clear internal guidelines for AI use are critical.
-
Compensating Runtime Controls: Implement defense-in-depth measures to limit and contain compromise even when application vulnerabilities exist:
-
Segregate Public Services: Host public-facing Cloud Run services in a dedicated, isolated Google Cloud project. This compartmentalization prevents a compromise from immediately affecting critical internal resources. Refer to the secured serverless architecture blueprint for detailed implementation.
-
Identity and Access Management (IAM): Use custom service accounts for service authentication instead of the default Compute Engine service account. Adhere strictly to the principle of least privilege. For example, grant
Storage Object Viewer(roles/storage.objectViewer) restricted to a specific bucket for read-only access, orSecret Manager Secret Accessor(roles/secretmanager.secretAccessor) only to individual secrets required. -
Layer 7 Application Load Balancer (ALB) Architecture: Restrict ingress traffic for serverless functions to internal-only and use an external Layer 7 ALB to manage internet exposure. This provides centralized traffic management, granular control over headers and SSL policies, Cloud Armor WAF integration for protection against LFI/RFI and SSRF, traffic shaping with rate limits, enhanced visibility through robust logging, and Identity-Aware Proxy (IAP) support for identity-based authentication.
-
Web Application Firewall (WAF) — Cloud Armor: Integrate Cloud Armor with your Load Balancer to filter malicious traffic. Specifically,
lfi-v33-stablepreconfigured WAF rules can block common local file inclusion attacks, andrce-v33-stablerules can block remote code execution attempts. These rules can prevent attacks like path traversal (../../../etc/passwd) and the metadata service token extraction described previously. -
Serverless Architecture Controls: When using direct VPC egress or VPC Access connectors, leverage VPC Service Controls to restrict lateral movement and exfiltration through granular access policies. Hardening individual Cloud Run services is only one component of a secure architecture; defense-in-depth across interconnected Google Cloud resources is crucial.
-
-
Cloud Run Threat Detection: Beyond these hardening recommendations, Google Cloud Security Command Center (SCC) provides built-in services to detect control plane attacks against Cloud Run resources, including credential access, reconnaissance, and the execution of scripts or reverse shells. This service is available for Premium and Enterprise tiers.
Conclusion
Serverless applications offer immense agility and business value, especially with the rapid adoption of AI-driven development. However, this speed necessitates integrating security early in the development lifecycle, moving beyond default configurations, and prioritizing a robust defense-in-depth strategy centered on strong identity governance and secure architecture. Proactive vulnerability identification and continuous security testing are essential to neutralize threats before serverless functions become publicly accessible.