Security Threat Analysis: AWS Lambda-URLs

Security Threat Analysis: AWS Lambda-URLs

/0 Intro

AWS released a new Lambda-URL functionality on April 06 2022. It allows invoking a Lambda function directly from the internet when the AUTH Type is set to NONE. The other authentication type available is AWS_IAM.

We will take a look at the security ramifications of this new feature by going through a lab, and then analyzing the results. But first, lets take a quick look at Lambda security in general.


/1 Lambda Security

AWS Lambda is a public service, meaning it can be launched inside a specific AWS account, but it lives outside of any VPCs, and such is by default and by design. When a Lambda is however placed within a VPC, it will be integrated with many of the security controls we usually work hard to implement: Security Groups, NACLs, AWS Network Firewalls, WAFs, ALBs, VPC-Endpoints and so on. The "VPC-Lambdas" will also use an Internet Gateway (attached to the VPC) or a NAT Gateway (attached to the subnets of a VPC). All in all, we have much more control over the network security architecture and traffic of a Lambda which is part of a VPC.

So why would anyone create and invoke a Lambda-URL directly from the internet without going through any API Gateways, WAFs, etc? AWS states that the need to have a No-Auth Lambda-URL functionality would be for example to use it as a Webhook handler.


/2 Lab

Let's go through the following quick lab to get a better understanding of this new feature (I suggest proceeding in a test-lab or a personal AWS account):

  1. Create a new S3 bucket, set it with server-side encryption if desired, and deny any and all public access, making it 100% private. Upload a text file named "secret_birthdays.txt" containing a random birthdate, for example, 01/01/1900.
  2. Detach any NAT and Internet Gateways from all VPCs. No IAM users or roles are required.
  3. All AWS security services such as GuardDuty, Security Hub, Inspector, Macie, AWS Network Firewall, AWS WAF, etc can all be left activated and enabled.
  4. Create a new Lambda, with the following settings:

  • Author from scratch, enter a function name (such as "Data-extractor", pun intended), set the Runtime to Python 3.8;
  • Make sure the Lambda execution role has the managed policy "AmazonS3ReadOnlyAccess"?attached to it (this is naturally needed so that Lambda can access the S3 bucket and objects, you can specify the bucket created in step 1 if desired);
  • Under Advanced Options, click on "Enable function URL - new", and set the Auth type to "NONE", proceeding to create the function;
  • Once the function is created, paste the following code (do mind it, as I am not a developer; this code is meant get the job done):

import boto3
??
def lambda_handler(event, context):
? ? 
? ? s3 = boto3.client('s3')
? ? s3data = s3.get_object(Bucket='YourS3BucketName',? Key='secret_birthdays.txt')
? ? readdata = s3data['Body'].read()
? ? print (readdata)
? ? return readdata
        

  • Deploy and test the function within the console. Somewhere in the output of the test, a birthday should be seen:

Test Event Name: Reading-Output-S
Response: "01/01/1900"        

  • If the Lambda was created through the AWS console, we are good to go; AWS has already created for us automatically a Lambda-resource policy to make things work. If AWS CLI or CloudFormation is being used, the following Lambda-resource policy should be attached:

{
? "Version": "2012-10-17",
? "Id": "default",
? "Statement": [
? ? {
? ? ? "Sid": "FunctionURLAllowPublicAccess",
? ? ? "Effect": "Allow",
? ? ? "Principal": "*",
? ? ? "Action": "lambda:InvokeFunctionUrl",
? ? ? "Resource": "arn:aws:lambda:ca-central-1:000000000000:function:Data-Extractor",
? ? ? "Condition": {
? ? ? ? "StringEquals": {
? ? ? ? ? "lambda:FunctionUrlAuthType": "NONE"
? ? ? ? }
? ? ? }
? ? }
? ]
}
        

5. Copy the Lambda URL and paste it in another browser: it should download a file with the birthday entry which was in the S3 bucket object. If it does not work, try refreshing the page a couple of times.


/3 What is happening?

So even after having in place all the below security measures in order to achieve a completely isolated and private AWS account:

  • AWS WAF, AWS Network Firewall, and the many other AWS security services activated;
  • No Internet, API, or NAT Gateways;
  • A 100% private S3 data source;
  • No IAM users or IAM Roles (!!)

with a mere 6 lines of code in a Lambda function, someone can (either through a security config/architectural mishap, or a purely malicious intent) potentially download massive amounts of sensitive production data which was never meant to be exposed directly from the internet.?

The take away here is that Lambda has made, by design, deploying code to production extremely easy, and quick. Security in a serverless world is yet another topic to continuously monitor, plan properly, and execute accordingly.

Lastly, I still think AWS should offer us a "no-internet" option for Lambdas outside a VPC, especially for outgoing traffic to the internet...


/4 Security Recommendations:

1. First things first, let's discover if there were any Lambda-URLs configured quietly, "under the radar":

$ aws lambda list-functions 
 
 

$ aws lambda list-function-url-configs --function-name "Lambda-with-no-URL"
{
? ? "FunctionUrlConfigs": []
}
  
 

$ aws lambda list-function-url-configs --function-name "Data-Extractor"? ? ? ? ? ? 
{
? ? "FunctionUrlConfigs": [
? ? ? ? {
? ? ? ? ? ? "FunctionUrl": "https://zz00000zz.lambda-url.ca-central-1.on.aws/",
? ? ? ? ? ? "FunctionArn": "arn:aws:lambda:ca-central-1:00000000000:function:Data-Extractor",
? ? ? ? ? ? "CreationTime": "01/01/1900",
? ? ? ? ? ? "LastModifiedTime": "01/01/1900",
? ? ? ? ? ? "AuthType": "NONE"
? ? ? ? }
? ? ]
}
  
  
NOTE: Don't forget to update your AWS-CLI to the latest version, otherwise the last 2 commands wont work.
        

2. It would be a good idea to only allow a certain list of services and IAM permissions in the master-account's AWS Organizations, and then add new functionalities or services only after having the approval of the security team. This applies to AWS accounts with no Internet or NAT gateways, and especially for production workloads and accounts.

3. Applying the following SCP in the AWS Organizations master-account towards applicable OUs, until the functionality is well understood and reviewed by the IT/Cloud security teams. Note that the following SCP will disallow the creation of any Lambda-URL, whether Auth Type is set to AWS_IAM, or to NONE):


{
? "Version": "2012-10-17",
? "Statement": [
? ? {
? ? ? "Effect": "Deny",
? ? ? "Action": [
? ? ? ? "lambda:CreateFunctionUrlConfig",
? ? ? ? "lambda:UpdateFunctionUrlConfig",
? ? ? ? "lambda:InvokeFunctionUrl",
		"lambda:DeleteFunctionUrlConfig"
? ? ? ],
? ? ? "Resource": "*"
? ? }
? ]
}
        

4. If however the need is to allow the Auth Type to be set to AWS_IAM, then the following SCP can be used:


{
? "Version": "2012-10-17",
? "Statement": [
? ? {
? ? ? "Sid": "VisualEditor0",
? ? ? "Effect": "Deny",
? ? ? "Action": [
? ? ? ? "lambda:CreateFunctionUrlConfig",
? ? ? ? "lambda:UpdateFunctionUrlConfig"
? ? ? ],
? ? ? "Resource": "*",
? ? ? "Condition": {
? ? ? ? "StringEquals": {
? ? ? ? ? "lambda:FunctionUrlAuthType": "NONE"
? ? ? ? }
? ? ? }
? ? }
? ]
}
        

5. Always understand what lambdas are programmed to do and security-scan/review them. Let the security team validate their triggers, security groups, resource policies, and execution roles, especially if the lambdas were designed to access other AWS services containing important data, such as S3, databases, etc.

6. Restrict and control the IAM roles and permissions in regards to what internal employees can do with Lambdas in production and/or any environments with access to sensitive data.

7. Proceed carefully with the public AWS services which can have outgoing internet connectivity even when there are no Internet/NAT Gateways present.

8. One of my favorite AWS services (besides KMS, IAM, and surprisingly Lambdas!) is AWS PrivateLink. I would strongly advise using VPC endpoints whenever practical or possible, while having endpoint policies and Security Groups configured. Traffic which flows inside PrivateLink is encrypted by AWS.

9. Encrypt sensitive data with different KMS "service-CMKs", and only grant other AWS services permission to use those CMKs after careful considerations (code review, etc).

There are obviously more security recommendations, this list is geared more towards the lab and this topic.


/5 Conclusion

This is a good example of the dangers associated with newly released AWS services/functionalities, and why they should be investigated quickly and carefully by the security and DevSecOps teams before allowing them to be deployed or used in production.


Thank you for reading and I hope you enjoyed this article! To check out all the other articles, click here.


References:

https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html

https://aws.amazon.com/blogs/aws/announcing-aws-lambda-function-urls-built-in-https-endpoints-for-single-function-microservices/

要查看或添加评论,请登录

Ziyad Almbasher的更多文章

社区洞察

其他会员也浏览了