Security Best Practices For Serverless Applications

Laptop with code
Related Content

Serverless architecture allows applications to be developed and deployed without the provisioning and managing of the underlying infrastructure or servers. Applications deployed by serverless architecture do not require any traditional host; instead, they run on serverless offerings managed by cloud providers. The most well-known serverless platforms are AWS LambdaMicrosoft Azure Functions, and Google Cloud Functions.

Serverless architecture offers various advantages over other architectures, such as scalability and innovation, by letting developers focus on writing code, but it has unique security risks.

3 Big Cybersecurity Concerns with Metaverse

3 Big Cybersecurity Concerns with M...
3 Big Cybersecurity Concerns with Metaverse

In this article, we’ll talk about those security risks and the best practices we can implement to properly secure serverless applications from those vulnerabilities.

Use the principle of Least Privilege where possible

The rule of Least Privilege limits the risk to data and systems in case of a compromised application. Applications that commonly access resources such as databases, file storage, and external systems and applications are restricted to the entities that need access to information for legitimate purposes.

Least Privileges also allows us to restrict application permissions to the minimum required at that time—only allowing access based on what is specifically needed for each function to operate at its best. This helps reduce the damage an attack can cause and decrease the scope for the overall integration of several functions.

For example, most functions probably don’t need access to databases or permissions to access servers, but default by various serverless frameworks execute these actions.

Take the following serverless.yml default configuration for AWS Lambda in Serverless Framework. This configuration will allow all Lambda functions in the service to perform the submit action on an SNS(Software Notification Service) resource.

provider:
  name: aws
  iamRoleStatements:
    - Effect: Allow
      Action:
        - sns:submit
      Resource:
        - Ref: SNS

Whereas, when we use the serverless-iam-roles-per-function plugin in AWS Lambda, it lets you limit the resources specific to the individual Lambda function.

Activate the plugin in serverless.yml:

plugins:
  - serverless-iam-roles-per-function

And then define iamRoleStatements for a particular function:

myfunction1:
  handler: src/functions/base/index
  events:
    - http:
        path: base
        method: get

  iamRoleStatements:
    - Effect: Allow
      Action:
        - sns:submit
      Resource:
        - Ref: SNS

With this configuration, only functions which are allowed access to the service will be able to use the submit action on the SNS resource.

Use secure storage for storing secrets

Many cloud providers provide native secrets management solutions on their platforms, such as AWS Secrets Manager or Azure Key Vault. These native solutions provided by serverless providers permit you to safely store and retrieve arbitrary values and provide functions such as authentication upheld by the provider’s IAM (Identity Access Management) solution.

Serverless applications can store secrets by calling the secret manager’s API or deployment. If your provider lacks a native secret management solution, the user can consider a third-party solution such as HashiCorp Vault or Conjur. They are not the best solution to secure a small number of serverless applications. However, these tools are well-equipped for cloud deployments and often include more functionality than a native secrets manager.

Secrets managers have many other features, too, such as unified access and audit logging, which help you better understand how sensitive information is being consumed in your environment. They also help secure the confidential information stored in static files in a code repository or in environment variables, significantly reducing the chance of sensitive information exposure.

Consider the following example, which uses the AWS Systems Manager to retrieve securely encrypted secrets using the AWS Parameter Store.

service:
 name: payapp

provider:
  name: aws

functions:
  pay:
    handler: pay.get
    environment:
      GITHUB_API_KEY: ${ssm:/github/api-key}

Here ${ssm:/github/api-key} will return that key’s encrypted value, which has to be decrypted to get the actual value.

Ensure Secure Communication of Transit Data

Using a secure medium for web communication is becoming more prominent as best practices for serverless applications are employed. Functions and the services that integrate with 3rd party services should be closely monitored while leveraging a secure medium for communication.

  • Leverage HTTPS or TLS for secure communication: Attackers may exploit the insecure communication medium to extract sensitive information or use unverified algorithms for security breaches, which can be mitigated using TLS or HTTPS as a secure means of communication. Implementing TLS or HTTPS within your internal perimeter of other functions or services will keep your credentials and sensitive information safe and encrypt it with proper cryptographically secure algorithms.
  • Limit unauthorized access to resources: Implement proper access control mechanisms, such as defaulting to denying access or an SSL certification verification. Verifying SSL certificates ensures secure communication between a user and server; any unauthorized communication will be halted when the identity and authenticity of the server do not match the information in the certificate. Also, enable rate-limiting and signed requests for cloud vendors to minimize attacks and chances of unsecured communication.
  • Restrict Lambda access to your VPC only: Launch your Lambda functions inside private subnets in your AWS account in a virtual private cloud (VPC). This will allow you to establish controlled network communication between the Lambda function and a private network for resources such as databases, cache instances, or other internal services.

Ensure Proper Authentication and Authorization using API Gateway

Proper authentication controls ensure that functions and resources are secured from unauthorized access. Decentralized serverless applications should be properly monitored to ensure that each application or service makes the proper checks. If applications are accessed from multiple sources, there can be a chance that it is exposed to security vulnerability which may lead to security breaches in the future.

An ideal approach to resolve this issue by utilizing an API gateway, which oversees validation and approval for the serverless applications behind it. The gateway will initially validate each request to the application based on the authorization information they are carrying. If validated, they will be sent to applications for handling, while unapproved requests will not be processed and rejected by the gateway.

Using an API gateway as a filter to limit input to your function based on a gateway policy encourages request/response mapping that complies with schemas. This is similar to Objects in programming languages where if inputted object type of functions does not map to the object class, they are rejected by the compiler.

Consider this code snippet, for example. There is a schema of how to store data that should be inputted based on type, price, unit, and quantity. If variables do not match the schema type, the gateway will not validate the request.

{
  "$schema": "https://json-schema.org/draft-04/schema#",
  "title": "StoreDataType",
  "type": "object",
  "properties": {
      "Bin" : {
        "type": "object",
        "properties": {
            "type": { "type": "string" },
            "price": { "type": "number" },
            "unit": { "type": "integer" },
            "quantity": { "type": "integer" }
        }
      }
   }  
}

Log and Monitor Functions

Insufficient function logging and monitoring is a significant issue among serverless applications. To mitigate this problem, leading serverless frameworks provides ease to use monitoring and logging tools, which checks the number of execution a function has received and the execution duration.

It’s a best practice to create alert thresholds for each of your functions on all provided monitoring solutions. This can help diagnose potential issues in serverless architecture by monitoring how long it takes for a function to execute. So the right amount of resources can be allocated to help develop an application that perfectly suits business needs.

  • Conduct Routine Audits: Auditing in serverless frameworks provide asset visibility and provide actionable results. They deliver an excellent overview in the form of statistical analysis, service dependencies, and routine configuration checks. There are also various policies, such as Undefined Conditions, SQS queues, and API gateways in a serverless environment for which routine audits can provide insights.

DashbirdRookoutLambda Guard, or IOpipe for working with AWS lambda-based applications are commonly used monitoring and auditing tools. SignalFx is a tool that ensures real-time visibility and performance monitoring for AWS Lambda, Google Cloud Functions, and Azure Functions. Stackdriver is a native solution for monitoring Google Cloud Functions logs.

Establish Secure Coding Practices

Serverless architecture introduces new risks, and traditional tools have not successfully dealt with some of these risks. As a result, many secure coding inventions and frameworks have been introduced to protect applications.

Mandating the use of secure coding inventions across developer teams not only prevents developers from re-inventing the possible mistakes for security concerns that already have standardized solutions but also promotes activities such as application review to catch code security issues early in the process of the software development lifecycle.

There are many secure coding conventions for securing serverless applications from which OWASP remains at the top for protecting serverless architectures. So let’s look at the top OWASP practices and see how they apply to serverless computing.

  • Broken Access Control: Broken access control in serverless functions can have broader exposure to security risks. Traditional applications typically authorize access to the entire application and use a single token for all functions as an overall unified authentication to control access to the application. To resolve this problem, Implement each function as a nano service with its own access controls. This will deny access to unauthorized parts of the application that follow a unified authorization model.
  • Injection Attacks: Injection attacks, where data isn’t filtered or encoded with the correct context, will result in being interpreted as a part of an unsecured execution. Injection generally applies to database execution, systems execution, HTML, and CSS code execution. To avoid injection attacks, implement minimum user input. Reducing user input to the bare minimum will decrease the chances of attackers including input in the form of various events (new or changed files or database fields) or message queues, which are usually triggered as a chain of unsecured functions in your serverless framework.
  • Sensitive Data Exposure: The serverless framework can expose sensitive data that attackers may exploit through the insecure communication medium to exfiltrate sensitive information. Issues can be resolved in the form of having “key vault” systems to share secrets throughout an application, KeyVault systems will encrypt and hash the credentials with proper cryptographically secure algorithms to decrease data exposure.

Secure Software Delivery Lifecycle

Applications must be secured with a software delivery life cycle. Secure applications integrate security into all phases of the delivery process and develop a strong baseline for serverless applications, which can be an asset as we build an extensive security program.

1200px-From-SDLC-to-SSDLC

Original image source: https://commons.wikimedia.org/wiki/File:From_SDLC_to_SSDLC.png.

Many processes must be considered, such as architecture review, development testing, and deployment, when enabling secure delivery for your serverless applications.

The initial step of assuring security in a serverless framework starts with the architecture review. It is one of the important steps of the application delivery lifecycle, where engineering is outlined. In this phase, the structuring of applications happens to distinguish how parts of applications will connect and communicate.

Coming to Development when testing serverless applications in development, it’s imperative to have the option to rapidly check security controls. This initial step in the delivery lifecycle will guarantee that the authorizations made during the design stage are considered for the proper working of the serverless application.

Integrating security as a component of the Continuous Integration (CI) pipeline is also important. This includes reviewing conditions for known weaknesses during development to ensure that every serverless application which comes out of the pipeline easily integrates with security practices.

Lastly, a secured deployment environment can decrease the attacking surface for serverless application communication. Also, to support fast deployment, its prerequisites, such as packaging and installers, must be isolated from the execution phase. Further, it’s critical to consider the environment where packages are retrieved. Consider embracing systems that update packages on the backend while simultaneously providing full power over the working environment at the front end.

Deployment is also about dashboards and auditing capabilities that further reinforce and support the security practices included in the architecture review phase. Visibility and auditing help to enable the right role and permission access for a particular function.

For example, see the following example snippet of a serverless.yml file:

service: transaction

provider:
  name: aws
functions:
  func0:
    role: myRole0
  func1:
    role: myRole1

Here, two Lambda functions are declared as follows: func0func1.

Each of these functions is assigned its specific role, determined by the role specifier. Using different role specifiers can provide much more granular control by providing only what each function is assigned to do.

Integrate WAF but don’t rely completely on it

Having a WAF in place is important, but it should not be the only line of defense in securing serverless applications.

A Web Application Firewall (WAF) secures the API gateway and is explicitly intended to examine every HTTP/S request at the gateway. It is commonly user and session aware of the web applications behind the communication and the services they offer. Along these lines, you can think about a WAF as the middleman between the client and the application itself, examining all the communication before they come to the application or the client.

Conventional WAFs are also trusted as the first line of resistance for applications, particularly to ensure against the OWASP Top 10(the foundation for the most observed application weaknesses). which presently incorporates Injection attacks, Broken Authentication, Sensitive information introduction, XML External Entities (XXE), Security misconfigurations, and Insecure Deserialization.

  • Conventional WAFs won’t give you security against some other occasion trigger types. Web Application firewalls(WAF) can only inspect HTTP(s) traffic. This means it won’t help if you want to secure functions that are not API Gateway-triggered functions, for example, Lambda functions that are interacting with storage services (AWS S3, Azure Storage, or Google Cloud Storage), DynamoDB database, or other services.

Correctly Define IAM Roles Per Function

Identity and Access Management (IAM) is the heart of security for serverless frameworks. IAM policies, by default, are often less looked at by many developers, which is why many functions are defined as a single role exposing the application to security risks.

IAM policies must be defined differently for each task, granting only the permissions necessary for that function. This will restrict each function to its intended purpose, making it easier to define permissions/roles for your Lambda Functions to the specific actions and resources it needs.

For example, the block below provides the ability for the Lambda function to query and manipulate items in the DynamoDB table only.

provider:
  name: aws
  runtime: nodejs6.10
  iamRoleStatements:
    - Effect: "Allow"
      Action:
       - dynamodb:Query
       - dynamodb:Scan
       - dynamodb:GetItem
      Resource: "arn:aws:dynamodb:us-west-2:111110002222:table/data-table"

IAM role tip: You can use CloudFormation Intrinsic Functions to make it easier to define permissions/roles for your Lambda Functions. For example, if you’ve created your DynamoDB table in the resources section of your serverless.yml, you can use the Fn::GetAtt intrinsic function to get the Amazon Resource Names (ARNs).

provider:
  name: aws
  runtime: nodejs6.10
  iamRoleStatements:
    - Effect: "Allow"
      Action:
       - dynamodb:Query
       - dynamodb:Scan
       - dynamodb:GetItem
      Resource:
       Fn::GetAtt:
         - MyDynamoTable
         - Arn

After defining the Fn::GetAtt function, you can dynamically grab the ARN for the DynamoDB table and various other Amazon Resources such as (Amazon RDS) tags, API calls, and IAM policies. The function automatically executes requests to access resources in the resources block to retrieve the specific ARN.

Summary

Creating an application using a serverless architecture is a great way to reduce development costs and ensure your solution’s scalability. However, the development team must keep potential security issues in mind from deployment. New security challenges are always at bay, with scaling and performance. and the serverless community has to adopt a greater security posture since everything is at the function level, making it easier for attackers.

It is also important for teams to change their approach to application security in serverless deployments. Teams should know that Serverless apps require more than tools and tactics and equal collaboration from the people involved in both the application and security domains.

LIKE THIS ARTICLE?
Facebook
Twitter
LinkedIn
Pinterest
WANT TO BE AN AUTHOR OF ANOTHER POST?

We’re looking for skilled technical authors for our blog!

Table of Contents