Serverless.com Security
Reading time: 17 minutes
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Basic Information
Organization
An Organization is the highest-level entity within the Serverless Framework ecosystem. It represents a collective group, such as a company, department, or any large entity, that encompasses multiple projects, teams, and applications.
Team
The Team are the users with access inside the organization. Teams help in organizing members based on roles. Collaborators
can view and deploy existing apps, while Admins
can create new apps and manage organization settings.
Application
An App is a logical grouping of related services within an Organization. It represents a complete application composed of multiple serverless services that work together to provide a cohesive functionality.
Services
A Service is the core component of a Serverless application. It represents your entire serverless project, encapsulating all the functions, configurations, and resources needed. It's typically defined in a serverless.yml
file, a service includes metadata like the service name, provider configurations, functions, events, resources, plugins, and custom variables.
service: my-service
provider:
name: aws
runtime: nodejs14.x
functions:
hello:
handler: handler.hello
Function
A Function represents a single serverless function, such as an AWS Lambda function. It contains the code that executes in response to events.
It's defined under the functions
section in serverless.yml
, specifying the handler, runtime, events, environment variables, and other settings.
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get
Event
Events are triggers that invoke your serverless functions. They define how and when a function should be executed.
Common event types include HTTP requests, scheduled events (cron jobs), database events, file uploads, and more.
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get
- schedule:
rate: rate(10 minutes)
Resource
Resources allow you to define additional cloud resources that your service depends on, such as databases, storage buckets, or IAM roles.
They are specified under the resources
section, often using CloudFormation syntax for AWS.
resources:
Resources:
MyDynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: my-table
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
Provider
The Provider object specifies the cloud service provider (e.g., AWS, Azure, Google Cloud) and contains configuration settings relevant to that provider.
It includes details like the runtime, region, stage, and credentials.
yamlCopy codeprovider:
name: aws
runtime: nodejs14.x
region: us-east-1
stage: dev
Stage and Region
The stage represents different environments (e.g., development, staging, production) where your service can be deployed. It allows for environment-specific configurations and deployments.
provider:
stage: dev
The region specifies the geographical region where your resources will be deployed. It's important for latency, compliance, and availability considerations.
provider:
region: us-west-2
Plugins
Plugins extend the functionality of the Serverless Framework by adding new features or integrating with other tools and services. They are defined under the plugins
section and installed via npm.
plugins:
- serverless-offline
- serverless-webpack
Layers
Layers allow you to package and manage shared code or dependencies separately from your functions. This promotes reusability and reduces deployment package sizes. They are defined under the layers
section and referenced by functions.
layers:
commonLibs:
path: layer-common
functions:
hello:
handler: handler.hello
layers:
- { Ref: CommonLibsLambdaLayer }
Variables and Custom Variables
Variables enable dynamic configuration by allowing the use of placeholders that are resolved at deployment time.
-
Syntax:
${variable}
syntax can reference environment variables, file contents, or other configuration parameters.functions: hello: handler: handler.hello environment: TABLE_NAME: ${self:custom.tableName}
-
Custom Variables: The
custom
section is used to define user-specific variables and configurations that can be reused throughout theserverless.yml
.custom: tableName: my-dynamodb-table stage: ${opt:stage, 'dev'}
Outputs
Outputs define the values that are returned after a service is deployed, such as resource ARNs, endpoints, or other useful information. They are specified under the outputs
section and often used to expose information to other services or for easy access post-deployment.
¡outputs:
ApiEndpoint:
Description: "API Gateway endpoint URL"
Value:
Fn::Join:
- ""
- - "https://"
- Ref: ApiGatewayRestApi
- ".execute-api."
- Ref: AWS::Region
- ".amazonaws.com/"
- Ref: AWS::Stage
IAM Roles and Permissions
IAM Roles and Permissions define the security credentials and access rights for your functions and other resources. They are managed under the provider
or individual function settings to specify necessary permissions.
provider:
[...]
iam:
role:
statements:
- Effect: 'Allow'
Action:
- 'dynamodb:PutItem'
- 'dynamodb:Get*'
- 'dynamodb:Scan*'
- 'dynamodb:UpdateItem'
- 'dynamodb:DeleteItem'
Resource: arn:aws:dynamodb:${aws:region}:${aws:accountId}:table/${self:service}-customerTable-${sls:stage}
Environment Variables
Variables allow you to pass configuration settings and secrets to your functions without hardcoding them. They are defined under the environment
section for either the provider or individual functions.
provider:
environment:
STAGE: ${self:provider.stage}
functions:
hello:
handler: handler.hello
environment:
TABLE_NAME: ${self:custom.tableName}
Dependencies
Dependencies manage the external libraries and modules your functions require. They typically handled via package managers like npm or pip, and bundled with your deployment package using tools or plugins like serverless-webpack
.
plugins:
- serverless-webpack
Hooks
Hooks allow you to run custom scripts or commands at specific points in the deployment lifecycle. They are defined using plugins or within the serverless.yml
to perform actions before or after deployments.
custom:
hooks:
before:deploy:deploy: echo "Starting deployment..."
Tutorial
This is a summary of the official tutorial from the docs:
- Create an AWS account (Serverless.com start in AWS infrastructure)
- Create an account in serverless.com
- Create an app:
# Create temp folder for the tutorial
mkdir /tmp/serverless-tutorial
cd /tmp/serverless-tutorial
# Install Serverless cli
npm install -g serverless
# Generate template
serverless #Choose first one (AWS / Node.js / HTTP API)
## Indicate a name like "Tutorial"
## Login/Register
## Create A New App
## Indicate a name like "tutorialapp)
This should have created an app called tutorialapp
that you can check in serverless.com and a folder called Tutorial
with the file handler.js
containing some JS code with a helloworld
code and the file serverless.yml
declaring that function:
exports.hello = async (event) => {
return {
statusCode: 200,
body: JSON.stringify({
message: "Go Serverless v4! Your function executed successfully!",
}),
}
}
- Create an AWS provider, going in the dashboard in
https://app.serverless.com/<org name>/settings/providers?providerId=new&provider=aws
.- To give
serverless.com
access to AWS It will ask to run a cloudformation stack using this config file (at the time of this writing): https://serverless-framework-template.s3.amazonaws.com/roleTemplate.yml - This template generates a role called
SFRole-<ID>
witharn:aws:iam::aws:policy/AdministratorAccess
over the account with a Trust Identity that allowsServerless.com
AWS account to access the role.
- To give
Yaml roleTemplate
Description: This stack creates an IAM role that can be used by Serverless Framework for use in deployments.
Resources:
SFRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS: arn:aws:iam::486128539022:root
Action:
- sts:AssumeRole
Condition:
StringEquals:
sts:ExternalId: !Sub "ServerlessFramework-${OrgUid}"
Path: /
RoleName: !Ref RoleName
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AdministratorAccess
ReporterFunction:
Type: Custom::ServerlessFrameworkReporter
Properties:
ServiceToken: "arn:aws:lambda:us-east-1:486128539022:function:sp-providers-stack-reporter-custom-resource-prod-tmen2ec"
OrgUid: !Ref OrgUid
RoleArn: !GetAtt SFRole.Arn
Alias: !Ref Alias
Outputs:
SFRoleArn:
Description: "ARN for the IAM Role used by Serverless Framework"
Value: !GetAtt SFRole.Arn
Parameters:
OrgUid:
Description: Serverless Framework Org Uid
Type: String
Alias:
Description: Serverless Framework Provider Alias
Type: String
RoleName:
Description: Serverless Framework Role Name
Type: String
Trust Relationship
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::486128539022:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "ServerlessFramework-7bf7ddef-e1bf-43eb-a111-4d43e0894ccb"
}
}
}
]
}
- The tutorial asks to create the file
createCustomer.js
which will basically create a new API endpoint handled by the new JS file and asks to modify theserverless.yml
file to make it generate a new DynamoDB table, define an environment variable, the role that will be using the generated lambdas.
"use strict"
const AWS = require("aws-sdk")
module.exports.createCustomer = async (event) => {
const body = JSON.parse(Buffer.from(event.body, "base64").toString())
const dynamoDb = new AWS.DynamoDB.DocumentClient()
const putParams = {
TableName: process.env.DYNAMODB_CUSTOMER_TABLE,
Item: {
primary_key: body.name,
email: body.email,
},
}
await dynamoDb.put(putParams).promise()
return {
statusCode: 201,
}
}
- Deploy it running
serverless deploy
- The deployment will be performed via a CloudFormation Stack
- Note that the lambdas are exposed via API gateway and not via direct URLs
- Test it
- The previous step will print the URLs where your API endpoints lambda functions have been deployed
Security Review of Serverless.com
Misconfigured IAM Roles and Permissions
Overly permissive IAM roles can grant unauthorized access to cloud resources, leading to data breaches or resource manipulation.
When no permissions are specified for the a Lambda function, a role with permissions only to generate logs will be created, like:
Minimum lambda permissions
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogStream",
"logs:CreateLogGroup",
"logs:TagResource"
],
"Resource": [
"arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/jito-cranker-scripts-dev*:*"
],
"Effect": "Allow"
},
{
"Action": ["logs:PutLogEvents"],
"Resource": [
"arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/jito-cranker-scripts-dev*:*:*"
],
"Effect": "Allow"
}
]
}
Mitigation Strategies
-
Principle of Least Privilege: Assign only necessary permissions to each function.
provider: [...] iam: role: statements: - Effect: 'Allow' Action: - 'dynamodb:PutItem' - 'dynamodb:Get*' - 'dynamodb:Scan*' - 'dynamodb:UpdateItem' - 'dynamodb:DeleteItem' Resource: arn:aws:dynamodb:${aws:region}:${aws:accountId}:table/${self:service}-customerTable-${sls:stage}
-
Use Separate Roles: Differentiate roles based on function requirements.
Insecure Secrets and Configuration Management
Storing sensitive information (e.g., API keys, database credentials) directly in serverless.yml
or code can lead to exposure if repositories are compromised.
The recommended way to store environment variables in serverless.yml
file from serverless.com (at the time of this writing) is to use the ssm
or s3
providers, which allows to get the environment values from these sources at deployment time and configure the lambdas environment variables with the text clear of the values!
caution
Therefore, anyone with permissions to read the lambdas configuration inside AWS will be able to access all these environment variables in clear text!
For example, the following example will use SSM to get an environment variable:
provider:
environment:
DB_PASSWORD: ${ssm:/aws/reference/secretsmanager/my-db-password~true}
And even if this prevents hardcoding the environment variable value in the serverless.yml
file, the value will be obtained at deployment time and will be added in clear text inside the lambda environment variable.
tip
The recommended way to store environment variables using serveless.com would be to store it in a AWS secret and just store the secret name in the environment variable and the lambda code should gather it.
Mitigation Strategies
- Secrets Manager Integration: Use services like AWS Secrets Manager.
- Encrypted Variables: Leverage Serverless Framework’s encryption features for sensitive data.
- Access Controls: Restrict access to secrets based on roles.
Vulnerable Code and Dependencies
Outdated or insecure dependencies can introduce vulnerabilities, while improper input handling may lead to code injection attacks.
Mitigation Strategies
-
Dependency Management: Regularly update dependencies and scan for vulnerabilities.
plugins: - serverless-webpack - serverless-plugin-snyk
-
Input Validation: Implement strict validation and sanitization of all inputs.
-
Code Reviews: Conduct thorough reviews to identify security flaws.
-
Static Analysis: Use tools to detect vulnerabilities in the codebase.
Inadequate Logging and Monitoring
Without proper logging and monitoring, malicious activities may go undetected, delaying incident response.
Mitigation Strategies
-
Centralized Logging: Aggregate logs using services like AWS CloudWatch or Datadog.
plugins: - serverless-plugin-datadog
-
Enable Detailed Logging: Capture essential information without exposing sensitive data.
-
Set Up Alerts: Configure alerts for suspicious activities or anomalies.
-
Regular Monitoring: Continuously monitor logs and metrics for potential security incidents.
Insecure API Gateway Configurations
Open or improperly secured APIs can be exploited for unauthorized access, Denial of Service (DoS) attacks, or cross-site attacks.
Mitigation Strategies
-
Authentication and Authorization: Implement robust mechanisms like OAuth, API keys, or JWT.
functions: hello: handler: handler.hello events: - http: path: hello method: get authorizer: aws_iam
-
Rate Limiting and Throttling: Prevent abuse by limiting request rates.
provider: apiGateway: throttle: burstLimit: 200 rateLimit: 100
-
Secure CORS Configuration: Restrict allowed origins, methods, and headers.
functions: hello: handler: handler.hello events: - http: path: hello method: get cors: origin: https://yourdomain.com headers: - Content-Type
-
Use Web Application Firewalls (WAF): Filter and monitor HTTP requests for malicious patterns.
Insufficient Function Isolation
Shared resources and inadequate isolation can lead to privilege escalations or unintended interactions between functions.
Mitigation Strategies
-
Isolate Functions: Assign distinct resources and IAM roles to ensure independent operation.
-
Resource Partitioning: Use separate databases or storage buckets for different functions.
-
Use VPCs: Deploy functions within Virtual Private Clouds for enhanced network isolation.
provider: vpc: securityGroupIds: - sg-xxxxxxxx subnetIds: - subnet-xxxxxx
-
Limit Function Permissions: Ensure functions cannot access or interfere with each other’s resources unless explicitly required.
Inadequate Data Protection
Unencrypted data at rest or in transit can be exposed, leading to data breaches or tampering.
Mitigation Strategies
-
Encrypt Data at Rest: Utilize cloud service encryption features.
resources: Resources: MyDynamoDBTable: Type: AWS::DynamoDB::Table Properties: SSESpecification: SSEEnabled: true
-
Encrypt Data in Transit: Use HTTPS/TLS for all data transmissions.
-
Secure API Communication: Enforce encryption protocols and validate certificates.
-
Manage Encryption Keys Securely: Use managed key services and rotate keys regularly.
Lack of Proper Error Handling
Detailed error messages can leak sensitive information about the infrastructure or codebase, while unhandled exceptions may lead to application crashes.
Mitigation Strategies
-
Generic Error Messages: Avoid exposing internal details in error responses.
javascriptCopy code// Example in Node.js exports.hello = async (event) => { try { // Function logic } catch (error) { console.error(error); return { statusCode: 500, body: JSON.stringify({ message: 'Internal Server Error' }), }; } };
-
Centralized Error Handling: Manage and sanitize errors consistently across all functions.
-
Monitor and Log Errors: Track and analyze errors internally without exposing details to end-users.
Insecure Deployment Practices
Exposed deployment configurations or unauthorized access to CI/CD pipelines can lead to malicious code deployments or misconfigurations.
Mitigation Strategies
- Secure CI/CD Pipelines: Implement strict access controls, multi-factor authentication (MFA), and regular audits.
- Store Configuration Securely: Keep deployment files free from hardcoded secrets and sensitive data.
- Use Infrastructure as Code (IaC) Security Tools: Employ tools like Checkov or Terraform Sentinel to enforce security policies.
- Immutable Deployments: Prevent unauthorized changes post-deployment by adopting immutable infrastructure practices.
Vulnerabilities in Plugins and Extensions
Using unvetted or malicious third-party plugins can introduce vulnerabilities into your serverless applications.
Mitigation Strategies
- Vet Plugins Thoroughly: Assess the security of plugins before integration, favoring those from reputable sources.
- Limit Plugin Usage: Use only necessary plugins to minimize the attack surface.
- Monitor Plugin Updates: Keep plugins updated to benefit from security patches.
- Isolate Plugin Environments: Run plugins in isolated environments to contain potential compromises.
Exposure of Sensitive Endpoints
Publicly accessible functions or unrestricted APIs can be exploited for unauthorized operations.
Mitigation Strategies
- Restrict Function Access: Use VPCs, security groups, and firewall rules to limit access to trusted sources.
- Implement Robust Authentication: Ensure all exposed endpoints require proper authentication and authorization.
- Use API Gateways Securely: Configure API Gateways to enforce security policies, including input validation and rate limiting.
- Disable Unused Endpoints: Regularly review and disable any endpoints that are no longer in use.
Excessive Permissions for Team Members and External Collaborators
Granting excessive permissions to team members and external collaborators can lead to unauthorized access, data breaches, and misuse of resources. This risk is heightened in environments where multiple individuals have varying levels of access, increasing the attack surface and potential for insider threats.
Mitigation Strategies
- Principle of Least Privilege: Ensure that team members and collaborators have only the permissions necessary to perform their tasks.
Access Keys and License Keys Security
Access Keys and License Keys are critical credentials used to authenticate and authorize interactions with the Serverless Framework CLI.
- License Keys: They are Unique identifiers required for authenticating access to Serverless Framework Version 4 which allows to login via CLI.
- Access Keys: Credentials that allow the Serverless Framework CLI to authenticate with the Serverless Framework Dashboard. When login with
serverless
cli an access key will be generated and stored in the laptop. You can also set it as an environment variable namedSERVERLESS_ACCESS_KEY
.
Security Risks
- Exposure Through Code Repositories:
- Hardcoding or accidentally committing Access Keys and License Keys to version control systems can lead to unauthorized access.
- Insecure Storage:
- Storing keys in plaintext within environment variables or configuration files without proper encryption increases the likelihood of leakage.
- Improper Distribution:
- Sharing keys through unsecured channels (e.g., email, chat) can result in interception by malicious actors.
- Lack of Rotation:
- Not regularly rotating keys extends the exposure period if keys are compromised.
- Excessive Permissions:
- Keys with broad permissions can be exploited to perform unauthorized actions across multiple resources.
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.