Serverless Hardening
Cloud Fast, Cloud Tight
Cloud environments change rapidly. That is why security must move along by default and in an automated fashion.
For Serverless Hardening, automation is the guiding principle: guardrails in code, least privilege, and continuous drift detection.
This way you maintain speed in the cloud without security depending on manual luck.
Immediate measures (15 minutes)
Why this matters
The core of Serverless Hardening is risk reduction in practice. Technical context supports the choice of measures, but implementation and assurance are central.
Defensive measures
Function Permissions: Least Privilege
The principle of least privilege is nowhere as crucial as with serverless. Each function must have exactly the permissions it needs – nothing more.
# SAM template -- goede IAM policy
Resources:
ProcessOrderFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: python3.11
Policies:
# Specifieke permissions, niet AmazonS3FullAccess
- Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:GetObject
Resource: !Sub "arn:aws:s3:::${OrderBucket}/orders/*"
- Effect: Allow
Action:
- dynamodb:PutItem
Resource: !GetAtt OrderTable.Arn
Condition:
ForAllValues:StringEquals:
dynamodb:LeadingKeys:
- "${aws:PrincipalTag/orderId}"VPC Placement
# Lambda in een VPC -- beperkt outbound traffic
Resources:
SecureFunction:
Type: AWS::Serverless::Function
Properties:
VpcConfig:
SecurityGroupIds:
- !Ref FunctionSecurityGroup
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
FunctionSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Lambda function security group
VpcId: !Ref VPC
SecurityGroupEgress:
# Alleen toegang tot specifieke services
- IpProtocol: tcp
FromPort: 443
ToPort: 443
DestinationPrefixListId: !Ref S3PrefixList # Alleen S3Dependency Scanning
# CI/CD pipeline stap: scan dependencies
# Python
pip install pip-audit safety
pip-audit -r requirements.txt --strict
safety check -r requirements.txt
# Node.js
npm audit --audit-level=high
npx snyk test
# Scan Lambda layers
aws lambda get-layer-version \
--layer-name shared-layer --version-number 1 \
--query 'Content.Location' --output text \
| xargs curl -o layer.zip
unzip layer.zip -d layer-scan/
pip-audit -r layer-scan/python/requirements.txtRuntime Protection
# Lambda wrapper voor runtime protection
import os
import socket
# Blokkeer outbound DNS naar niet-standaard servers
_original_getaddrinfo = socket.getaddrinfo
def _restricted_getaddrinfo(host, port, *args, **kwargs):
# Sta alleen bekende hosts toe
allowed = ['dynamodb.eu-west-1.amazonaws.com', 's3.eu-west-1.amazonaws.com']
if host not in allowed and not host.endswith('.amazonaws.com'):
raise socket.gaierror(f"DNS lookup blocked for: {host}")
return _original_getaddrinfo(host, port, *args, **kwargs)
if os.environ.get('RESTRICT_NETWORK') == 'true':
socket.getaddrinfo = _restricted_getaddrinfoReference table
| Technique | MITRE ATT&CK | AWS | Azure | GCP |
|---|---|---|---|---|
| Function enumeration | T1526 - Cloud Service Discovery | aws lambda list-functions |
az functionapp list |
gcloud functions list |
| Credential extraction | T1552.005 - Cloud Instance Metadata | Lambda env vars, Runtime API | IMDS token theft | Metadata endpoint |
| Event injection | T1190 - Exploit Public-Facing App | S3/SQS/SNS event manipulation | Event Grid, Service Bus | Pub/Sub, Cloud Storage |
| Layer poisoning | T1195.002 - Supply Chain: Software Supply Chain | Lambda Layers | NuGet/npm packages | pip/npm packages |
| /tmp persistence | T1027 - Obfuscated Files | Lambda /tmp directory | Function App temp storage | /tmp directory |
| DNS exfiltration | T1048.003 - Exfil Over Unencrypted Protocol | CloudWatch DNS logs | Azure DNS Analytics | VPC Flow Logs |
| Function URL abuse | T1190 - Exploit Public-Facing App | Lambda Function URLs (AuthType: NONE) | Anonymous HTTP triggers | allUsers invoker |
| Runtime API exploitation | T1059 - Command and Scripting | Lambda Runtime API (127.0.0.1:9001) | N/A | N/A |
| Managed identity abuse | T1550.001 - Application Access Token | Lambda execution role | Managed Identity tokens | Service account tokens |
| Dependency attack | T1195.001 - Supply Chain: Compromise Software Dependencies | pip/npm malicious packages | NuGet supply chain | pip/npm supply chain |
| Code download | T1530 - Data from Cloud Storage | S3 function code bucket | Kudu SCM interface | gcf-sources bucket |
| Durable orchestration abuse | T1565 - Data Manipulation | Step Functions manipulation | Durable Functions events | Cloud Workflows |
| Extension registration | T1547 - Boot or Logon Autostart | Lambda Extensions API | App Service extensions | N/A |
| Cold start exploitation | T1059.006 - Python | Init phase code execution | Startup code execution | Init phase code execution |
| Outbound HTTP exfil | T1048.001 - Exfil Over Encrypted Channel | VPC endpoint bypass | NSG bypass attempts | Firewall rule bypass |
| Storage staging | T1074.002 - Remote Data Staging | S3 bucket staging | Blob Storage staging | GCS bucket staging |
The beauty of serverless is that you don't have to manage a server. The downside of serverless is that your attacker doesn't have to either.
Further reading in the knowledge base
These articles in the portal provide more background and practical context:
- The cloud — someone else's computer, your responsibility
- Containers and Docker — what it is and why you should secure it
- Encryption — the art of making things unreadable
- Least Privilege — give people only what they need
You need an account to access the knowledge base. Log in or register.
Related security measures
These articles provide additional context and depth: