DEV Community

Misha Bragin
Misha Bragin

Posted on • Originally published at netbird.io

AWS Lambda Serverless Security. Mistakes, Oversights, and Potential Vulnerabilities

Amazon Web Services (AWS) Lambda is a serverless function-as-a-service (FaaS) platform that lets you deploy, run, and scale code in the cloud as self-contained functions without having to manually configure any infrastructure. Lambda runs your functions on demand in response to specific events, such as an HTTP request from the internet or activity in another AWS service.

Using Lambda helps accelerate your development cycles by letting engineers stay focused on code, but going serverless is also a potential security risk. Incorrectly configured functions can harbor several kinds of vulnerabilities that can be exploited to allow unauthorized access or cause instability in your deployments.

In this guide, you'll explore some common Lambda security pitfalls and learn how to properly protect your functions. You need to understand how serverless changes the cloud security model so that you can confidently adopt the architecture while keeping your apps, data, and users safe.

Why Does AWS Lambda Serverless Security Matter

Security should be a primary concern when deploying a new AWS Lambda serverless function. Although Lambda handles infrastructure management for you, this doesn't mean you can trust its default configuration to automatically secure your functions and related resources.

Lambda operates under a shared responsibility security model. AWS secures the physical infrastructure that runs the service—including software components, such as the operating system and Lambda platform—but you're responsible for protecting your functions, their code, the generated data, and network routes to other stack components.

Correctly configuring serverless security is vital so you can safely use functions in business-critical scenarios, such as when your code processes sensitive or proprietary data. There are two main aspects to consider:

  1. Code security: This relates to vulnerabilities that exist within your function's code. It includes areas such as dependency supply chain security and the use of effective user input validation and sanitization.
  2. Function security: This covers the security of your Lambda functions and AWS environment, including the correct configuration of rate-limiting controls, resource constraints, and authorization requirements.

Unfortunately, it's easy to make errors in both of these areas.

Common AWS Lambda Security Mistakes and Oversights

Now that you've seen why it's important to secure your Lambda functions, let's analyze some of the most commonly experienced mistakes and oversights. Your functions could be vulnerable to these threats if you haven't already taken action to address them.

Inadequate Function-Level Permission Restrictions

Inadequate permission checks within your function's code can allow attackers to gain unauthorized access to your data. This risk can be present in any service, but the fast-paced Lambda development cycle can mean the threat easily goes unnoticed. Developers may also have a false sense of security that resources running within AWS or Lambda are already being protected.

You can address this problem by auditing all code for security issues before deployment. Additionally, you should shift security left and identify any privileged actions before you start development. This ensures that engineers know how to implement relevant permission checks as they build their functions.

Insufficient Error Handling and/or Logging

Functions should be observable so that you can spot errors and analyze suspected attack activity. Codes with insufficient error reporting and logging mask security incidents, making it easier for threat actors to acquire long-term access.

Log collection issues can be easily solved by instrumenting your function to emit logs on its standard output and error streams. Lambda automatically sends this output to the AWS CloudWatch Logs management service, allowing you to monitor log output and verify your function is working as expected.

Insufficient Resource Allocation

Lambda functions that have been allocated insufficient memory or CPU resources can cause resource exhaustion. At best, this leads to instability; at worst, malicious users could exploit it to achieve a denial-of-service (DoS) attack against your functions.

Resource constraints are controlled by setting the memory available to your Lambda functions. The available CPU capacity is then scaled automatically based on the amount of memory you've requested. You should assess your function's memory requirement before you deploy, then select an allocation that provides enough headroom for real-world usage. It's also important to set up CloudWatch alerts to receive notifications when a function invocation approaches its memory limit or exceeds defined thresholds for CPU or IO activity.

Excessive Resource Allocation

It's not just inadequate resource allocation that poses a security threat—assigning too much memory can be equally impactful. Because Lambda pricing is determined based on the amount of memory allocated and the total duration of each invocation, excessive allocation causes an unnecessary increase in your operating costs. Attackers could abuse this by directing malicious traffic to your services, forcing you to accept a higher bill.

To mitigate this threat, ensure you regularly monitor the actual resource utilization of your functions using the metrics available in CloudWatch. You can then rightsize your memory allocations to achieve an optimal balance of performance and cost efficiency.

Use of Insecure Dependencies

Functions that depend on vulnerable or outdated third-party packages pose security risks when running in Lambda, just like when any other deployment method is used.

Using unmaintained packages exposes you to actively exploited Common Vulnerabilities and Exposures (CVEs), insecure or buggy code, and the prospect of backdoors or intentional weaknesses inserted by malicious authors. You should practice safe supply chain security to identify these problems before you deploy, such as by generating a software bill of materials (SBOM) that lists your dependencies and any known issues they contain.

Data Injection

Unprotected Lambda functions can be vulnerable to data injection issues, such as improper user input sanitization or acceptance of malformed commands generated by attacks against other AWS services that can trigger your function. These weaknesses give threat actors the opportunity to execute code while making it difficult for you to detect them. Practicing robust code reviews, static and dynamic source security scans (static/dynamic application security testing [SAST/DAST]), and fuzz testing can help you uncover potential weaknesses.

Improper Access Control

Missing or incorrectly configured access controls allow unauthorized users to invoke your functions. You can prevent this by creating appropriate AWS Identity and Access Management (IAM) policies to precisely define which users and applications can interact with your functions.

It's also important to assign your functions a narrowly scoped execution role. This configures the AWS resources that your function's code can access using the credentials that are injected into its environment. Functions should be assigned the minimum privileges they require, such as permission to access files in a specific Amazon Simple Storage Service (Amazon S3) bucket but not any other type of resource.

Secure AWS Lambda: Protect Your Functions with a Mesh Network

Lambda security issues often stem from functions being unnecessarily publicly exposed. Although this can be unavoidable in some situations, many functions interact only with other components in your stack. Setting up private networking flows for these functions removes the need to expose them on the internet, reducing your attack surface.

The best way to securely connect your functions to your other resources is with an encrypted mesh network like NetBird. NetBird lets you link your infrastructure together using a zero-config private WireGuard network that works across cloud, serverless, and on-premise infrastructure.

Joining serverless environments like AWS Lambda to a mesh network has traditionally been difficult because you can't directly access the network interfaces on the hosts that run your functions. The NetBird netstack mode addresses this by providing a simulated TUN device and a SOCKS5 proxy that targets that device. This allows your Lambda function to access other services in your NetBird network via the proxy.

How to Securely Run Lambda Functions with NetBird

To use NetBird with your Lambda functions, you need to follow a few simple steps:

  1. Write your function's code: Create your function in the usual way, including any network connections you require. However, you should ensure the networking libraries you use are configured to connect using the SOCKS5 proxy that NetBird provides.
  2. Create a Docker image for your function: Your Lambda functions must be deployed as container images so the NetBird binary can be run alongside your code. Within your container image's build, you should select a relevant AWS Lambda image as your base image, then add your code and the /go/bin/netbird binary from the NetBird official image.
  3. Enable the NetBird netstack mode: You need to set the NB_USE_NETSTACK_MODE and NB_FOREGROUND_MODE environment variables inside your container image to ensure NetBird is correctly configured for in-container netstack operation.
  4. Create a command script that starts NetBird before your function runs: You can achieve this by setting a custom script as your container's entry point. It should start the NetBird binary and then invoke your code using the AWS Lambda platform binary.
  5. Set your NetBird setup key as a Lambda environment variable: Before running your function, you should set the NB_SETUP_KEY environment variable using the Lambda console or API. Setup keys connect your apps to your NetBird network. You can generate one by logging into your NetBird account.

After following these steps, you can deploy your Lambda project. NetBird will register your function in the network and assign it a private NetBird IP address.
You can use this IP to call your function. It executes inside the container using the image you've created.
Because the NetBird binary is configured to run inside the container, too, your code can access the other resources in
your network without being exposed to the public internet. You can even connect your Lambda to on-premise resources like databases or legacy systems,
or even multiple serverless functions running in different cloud providers.

NetBird connects lambda

Check out the NetBird documentation for more information on how to set up your Lambda functions with NetBird.

Best Practices for AWS Lambda Security

AWS Lambda simplifies cloud deployment by letting you launch services as serverless functions that run on demand with high availability and scalability. Although this can help you deliver code more quickly and cost-effectively, it also makes you vulnerable to new security threats if you don't properly harden your AWS accounts and the functions within them. Here's a recap of the best practices you should follow to defend your serverless functions against these risks:

  • Configure correct IAM policies to restrict access to your functions.
  • Allocate appropriate resources to your Lambda functions to avoid resource exhaustion or overprovisioning.
  • Practice secure coding methods, including proper input sanitization and safe supply chain hygiene.
  • Ensure that activities in functions are observable through logs and error reports.
  • Avoid exposing functions on the public internet.
  • Connect functions to other infrastructure using a private VPN.

These steps ensure your Lambda functions are performant, safe, and secure, letting you fully benefit from the development efficiency improvements that serverless computing allows.

Top comments (0)