Channel: CodeSection,代码区,网络安全 - CodeSec
Viewing all articles
Browse latest Browse all 12749

Serverless Code Security


I’ve been kicking around these ideas for a while, but the recent (excellent) talk by Rich Jones spurred me into putting thoughts into an article. The ideas should apply to any FaaS offering, but will be framed for AWS Lambda.

There are two primary motivations here: how can you be sure that a function’s code as stored is what you expect and intend it to be? And then, how can you be sure that the function code you are invoking is the code you expect and intend it to be?

For the first theme, Lambda provides a hash (SHA-256, to be precise) of a function’s code in the CodeSha256 attribute, available in the responses for create/get/update function code/configuration. This allows you to verify, when creating or updating the code, that the code uploaded and stored is what you expect it to be. It also allows you to verify later that the code hasn’t changed.

When you publish a version (that is, snapshot the code and configuration), you can pass in a value for CodeSha256 that is checked against the current code. If there’s a mismatch, the publishing will fail. This allows you to be sure that the published version will have the code you intend to it have. However, this assumes that you are confident in the code already residing in Lambda with that hash.

The first improvement is to allow a value for CodeSha256 to be passed in to the CreateFunction and UpdateFunctionCode API methods. This allows the developer to be positive that the code being uploaded is the code they intend.

While it is important to ensure a function’s code is not modified, the function configuration also needs to be verified. In particular, the IAM role given to the function defines the permissions the Lambda will have.

The second improvement is to provide a CodeAndConfigSha256 property, which hashes together the CodeSha256 property with some hash of the configuration (properly handling future additions to configuration properties is nontrivial but solvable). This property would be available in all the places CodeSha256 is, including CreateFunction, PublishVersion, etc., where it would be used to verify the function contents.

A published version of a Lambda function is an immutable snapshot of code and configuration. Well, sort of: the version itself is immutable, but the name for the version ― either the sequential numeric version number or an alias ― does not immutably point to a snapshot. An alias can be moved between versions. The version number can be modified if the function is deleted and recreated. So the next step is to ensure that there is an immutable version name available.

The third improvement is to provide an automatic alias that is the CodeAndConfigSha256 hash of the version. This alias would exist outside the range of possible developer-defined aliases (e.g., prefixed by “$HASH-”). When invoking a Lambda function using this alias, the caller could be sure of the exact function version they were using, and IAM policies could ensure that given callers are only given permissions to those exact versions.

The fourth improvement is to allow, at the service level, the ability to disable the ability to invoke the “$LATEST” version for any Lambda. This would ensure that only published versions could be invoked (in, say, the production account). While this could be done currently using IAM policies, it would be much easier to implement and monitor (blanket deny for that API call + alerting for it in CloudTrail).

Together, these improvements would reduce the attack surface for Lambda, provide more observability, and enable more targeted least-privilege policies. The concepts involved (hashing code and config, versioning) are not unique to AWS, and should be implementable by any FaaS provider. As serverless systems develop and gain adoption, protections against FaaS exploits are going to be increasingly necessary.

Viewing all articles
Browse latest Browse all 12749