Skip to content

Services, Wiki-Artikel, Blog-Beiträge und Glossar-Einträge durchsuchen

↑↓NavigierenEnterÖffnenESCSchließen
Cloud-Sicherheit Glossary

Serverless Security - Sicherheit in FaaS-Umgebungen

Serverless security refers to securing Function-as-a-Service (FaaS) environments such as AWS Lambda, Azure Functions, and Google Cloud Functions. Attack vectors: event injection, overprivileged roles, insecure dependencies, broken access control at the function level, cold-start timing attacks, and excessively long timeouts. Protection: OWASP Serverless Top 10, minimal IAM permissions, layer validation, dependency scanning.

Serverless Security refers to securing Function-as-a-Service (FaaS) environments where code runs in short-lived containers without the need for server management. The serverless model fundamentally changes the attack surface: no OS patching, but new risks arising from event-based triggers, IAM misconfigurations, and the complexity of many small functions.

Serverless Attack Surface

Typical Serverless Architecture (AWS Lambda)

A typical serverless architecture connects various event sources with Lambda functions and downstream services, for example:

  • API Gateway → Lambda function → DynamoDB
  • S3 upload → Lambda function → SQS queue
  • IoT event → Lambda function → RDS
  • SNS message → Lambda function → SES (email)

Attack vectors

  1. Event injection: Malicious input via API Gateway, S3, or SQS
  2. IAM misconfiguration: Lambda role with excessive permissions
  3. Insecure Dependencies: npm/pip packages with known vulnerabilities
  4. Secrets in Env-Vars: Credentials stored directly within the function
  5. Verbose Logging: Sensitive data in CloudWatch logs
  6. ZIP Path Traversal: Manipulation of the deployment package

OWASP Serverless Top 10

IDDescription
SAS-1Function Event-Data Injection
SAS-2Broken Authentication
SAS-3Insecure Serverless Deployment Configuration
SAS-4Over-Privileged Function Permissions and Roles
SAS-5Inadequate Function Monitoring and Logging
SAS-6Insecure Third-Party Dependencies
SAS-7Insecure Application Secrets Storage
SAS-8Denial of Service via Reserved Concurrency
SAS-9Serverless Business Logic Manipulation
SAS-10Improper Exception Handling and Verbose Error Messages

SAS-1: Event Data Injection

The attack exploits the fact that Lambda functions often process data from external event sources without validation. An attacker sends manipulated inputs to API Gateway that contain, for example, SQL injection:

POST /api/users
{"userId": "1 OR 1=1--"}

An insecure Lambda function (Python) would insert the input directly into the query:

def handler(event, context):
    user_id = event['body']['userId']
    query = f"SELECT * FROM users WHERE id = {user_id}"
    # → SQL injection!
    result = db.execute(query)

The secure version uses parameterized queries:

def handler(event, context):
    user_id = event['body']['userId']
    query = "SELECT * FROM users WHERE id = %s"
    result = db.execute(query, (user_id,))

Other injection vectors include S3 event triggers (malicious filenames such as ../../../../etc/passwd that trigger path traversal operations—protection: os.path.basename()) and SNS/SQS messages, where internal event injection is possible in another service via SSRF.

SAS-4: Overprivileged Roles

A common problematic example:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "*",
    "Resource": "*"
  }]
}

This configuration grants the Lambda function full AWS admin access. If there is an RCE vulnerability in the function, the entire AWS account is compromised. The attack typically proceeds as follows: An injection vulnerability is found, then the AWS Metadata Service is queried (for IMDSv1 via http://169.254.169.254/latest/meta-data/iam/security-credentials/), from which temporary AWS credentials for the Lambda role are extracted. With these credentials, S3 buckets can then be emptied, EC2 instances launched, and other resources misused.

Least Privilege Example

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["dynamodb:GetItem", "dynamodb:PutItem"],
      "Resource": "arn:aws:dynamodb:eu-west-1:123456789:table/users"
    },
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject"],
      "Resource": "arn:aws:s3:::my-bucket/uploads/*"
    }
  ]
}

The IAMzero tool analyzes CloudTrail logs, identifies which permissions are actually being used, and generates a minimal IAM policy based on that.

AWS Recommendation: Enforce IMDSv2 to prevent SSRF on the Metadata Service:

aws lambda put-function-configuration \
  --function-name my-function \
  --description "IMDSv2 required"
# Also: Instance-Metadata-Hop-Limit = 1 in Lambda configuration

SAS-7: Secrets Management

Environment variables in Lambda are only Base64-encoded, not encrypted. Console access to Lambda → Configuration displays passwords in plain text. CloudFormation templates that end up in Git expose secrets to anyone with repository access.

A bad practice is hard-coding secrets:

def handler(event, context):
    DB_PASSWORD = "secretpassword123"  # In the source code!
    API_KEY = os.environ['API_KEY']      # Visible in the Lambda console!

Good practice 1 - AWS Secrets Manager:

import boto3

_cached_secret = None

def get_secret(secret_name):
    client = boto3.client('secretsmanager')
    response = client.get_secret_value(SecretId=secret_name)
    return json.loads(response['SecretString'])

def handler(event, context):
    global _cached_secret
    if _cached_secret is None:
        _cached_secret = get_secret('myapp/production/database')
    db_password = _cached_secret['password']

Caching during cold start is important to prevent an API call to Secrets Manager from being made with every function invocation.

Best Practice 2 - AWS Parameter Store (more cost-effective):

ssm = boto3.client('ssm')
password = ssm.get_parameter(
    Name='/myapp/database/password',
    WithDecryption=True  # KMS-encrypted!
)['Parameter']['Value']

Mediocre - Encrypted Environment Variables: Configuring a KMS key for Lambda encrypts env-vars at rest, but they are visible in plain text when the function is executed.

Denial-of-Service via Reserved Concurrency

AWS Lambda has a default limit of 1,000 concurrent executions per account (which can be increased). If this limit is reached, all other Lambdas in the account are throttled. An attacker can trigger an "account-wide DoS" by sending 1000+ parallel requests to a function without a concurrency limit, causing all other services to go offline.

Mitigation Measures

# Set Reserved Concurrency:
aws lambda put-function-concurrency \
  --function-name api-handler \
  --reserved-concurrent-executions 100

Additionally, Provisioned Concurrency for critical functions, API Gateway throttling limits (e.g., 1000 RPS, burst 5000), and a WAF in front of the API Gateway for rate limiting per IP can help.

Monitoring and Audit

CloudWatch and Lambda Insights

Monitor metrics such as duration, memory, cold starts, and error rate. Set up alerts for unusual patterns, e.g., duration spikes as an indication of an ongoing attack.

CloudTrail

Monitor Lambda:CreateFunction and Lambda:UpdateFunctionCode: Who deployed? Lambda:InvokeFunction: Unusual callers?

Powertools for Lambda (AWS)

from aws_lambda_powertools import Logger, Tracer, Metrics

logger = Logger(service="api-handler")
tracer = Tracer(service="api-handler")

@logger.inject_lambda_context(log_event=True)
@tracer.capture_lambda_handler
def handler(event, context):
    user_id = event.get('requestContext', {}).get('authorizer', {}).get('principalId')
    logger.info("Processing request", extra={"user_id": user_id})
    # Structured logs → CloudWatch → SIEM

Falco for Serverless (Runtime Security): Detects unexpected syscalls and network connections from Lambda; integration via Lambda Layer.

SBOM for Dependencies: cyclonedx-python for Python Lambdas, @cyclonedx/cyclonedx-npm for Node.js Lambdas – scan automatically with every deployment (Snyk, OWASP Dependency Check).

Serverless Security Checklist

IAM

  • Least-privilege role per function (never AdministratorAccess!)
  • Use IAMzero or Access Analyzer to find unused permissions
  • No wildcard actions (*) in IAM policies
  • No Resource: "*" if specific ARNs are possible
  • Enforce IMDSv2 (token-based, prevents SSRF)

Secrets

  • No secrets in plain text in environment variables
  • No secrets in source code or CloudFormation templates
  • Use Secrets Manager or Parameter Store (SecureString)
  • Rotate secrets regularly (Secrets Manager can rotate them automatically)

Code Security

  • Input validation of all event data (API Gateway events, S3 events, etc.)
  • Use parameterized queries for DB access
  • Perform dependency scanning (Snyk, npm audit) in CI/CD
  • Include SAST in the pull request workflow

Deployment

  • Verify ZIP integrity (enable code signing for Lambda)
  • Configure VPC if DB access is required (do not make it public!)
  • Set reserved concurrency (DoS protection)
  • Enable API Gateway WAF (AWS WAF)

Monitoring

  • CloudTrail in all regions (Lambda management events)
  • Alerts for error rate, duration, throttling, and cold-start spikes
  • Structured logging without PII in logs
  • Configure Dead Letter Queue (DLQ) for failed invocations