With AWS Lambda, the stateless and ephemeral nature of serverless functions shifts the way attackers approach these systems. Some of the key ramifications of this shift are:

  • The move to repetitive stateless attacks, where attackers leverage one or more application weaknesses to do some small volume of the overall attack, and repeat this process until the attack is complete.
  • The importance of protecting against upstream supply chain injection attacks, where attackers take advantage of your functions’ dependency on third party code, and find one of these modules that doesn’t properly protect itself. The attacker then injects their malicious code into this module, and waits for the attack to trickle down into your functions.

If this does not sound scary to you, read David Gilbertson’s excellent work of fiction here.

(This is of course just as relevant in non-serverless applications, but because it is much harder to achieve persistence in ephemeral compute, attackers will look at this vector more seriously in the serverless realm.)

AWS Lambda Stateless Gives a False Sense of App Security

But let us revisit the assumptions. If there is one lesson you should learn in security, it’s that the greatest security flaws stem from faulty assumptions. It is precisely because you believe all the marketing about your new all-wheel-drive jeep that you may take a turn too quickly and put yourself in danger. If you were driving a Hyundai Accent you would probably be a lot more careful.

Much of our security thinking might be based on the assumption that attackers cannot live for more than a few minutes in our system. The fact that cloud providers are intentionally vague about how and when they recycle serverless runtimes makes it easy to miss the fact that these functions can live for hours, or maybe even days.

That being the case, we actually do need to consider the possibility that an attacker could find a way to stay in our system and do extended damage.

AWS Lambda Stateless – Cold Start

Anyone who has spent time with FaaS systems can often be found murmuring in his sleep “No, not a Cold Start!” Let us quickly cover a very simplified view of how the cloud providers handle events that trigger our functions.

The Lifecycle of a Function

As you can see, both you and the cloud provider want to stay away from the “cold start” penalty (both in terms of cost and in terms of latency) and so over the past few years, providers are keeping containers warm for longer and longer to try and make sure that your requests can be handled as quickly as possible.

From a performance perspective, that is a positive thing. From a security perspective, on the other hand, that can be a step backwards. That is because AWS Lambda stateless & ephemeral nature meant that even if an attacker found a way to infiltrate your running function, they couldn’t rely on being around for too long. With the function runtime containers surviving for longer and longer, we need to be concerned about these “persistent” attacks again.

Yeah? Show Me…

Ok, let us look at a quick, if slightly naive example. Say you have an AWS Lambda function that ties to an API Gateway entry that allows users to update their payment information.

Our code-injection vulnerable AWS Lambda

Now, you have read the serverless security blogs. You get it. You configured the permissions on this function perfectly. All it can do is insert a record into the database. Even if an attacker can exploit your eval instruction on line 8, how much damage could they do? After all, they can only insert extra rows in the table, but that is not the end of the world.

Except that this container could stick around for a while. Imagine an attacker that sends the following data to your function (I have added some line breaks in the JSON to make it more readable; JSON does not really support multiline strings…):

Attack message the injects code to steal credit cards

Instead of just containing some payment info, this attack payload actually injects some code into your function. From now on, each time an innocent user passes her credit card information to your application; our attacker is going to get a copy. If the attacker is smart, he will try to infect as many containers as possible. He can do this, for example, by sending this malicious attack several hundred times in parallel, infecting many containers at once. If he is even smarter, he will endeavor to keep your containers warm and prevent losing his foothold in the application.

The challenge for this attack is that there is a one-time spike of one or more attack payloads, followed by nothing malevolent. And yet, your attacker can receive a stream of payment details stolen from your customers for hours or even days.

So much for AWS Lambda stateless and ephemeral…

OK, Enough Fear Mongering, What Do I Do to Protect from Serverless Attacks?

Ok, sorry. We do not mean it badly, us security people. We just naturally focus on the challenges, not the benefits. None of this makes serverless bad. In fact, at most, it means serverless is just like non-serverless in this respect.

There are several things we should do, though, to help minimize our risk.

  1. Do not assume
  2. Educate your developers to write secure code, and practice secure development.
  3. Protect your application with state-of-the-art serverless security tools that will help prevent the attacks, and detect anything that slips through
  4. Control your ephemerality: some security tools, including our own Check Point CloudGuard solution, can force containers to recycle efficiently if they live too long, minimizing this attack surface

Serverless architectures are a leap forward in software engineering and present both challenges and opportunities when securing your applications. It is critical to keep your eyes open when considering all of the security risks and make sure you are using all the right tools and processes to protect your users and their data.

For more information on securing AWS Lambda serverless functions, download our AWS Lambda Security Best Practices Guide.