The Serverless Framework support numerous plugins—and they are great! They save so much time in deploying our serverless applications. Why reinvent the wheel? This convenience comes with a downside: not all plugins are written securely. We must choose our plugins wisely, which means we should inspect the source code.

What are Serverless Framework plugins?

The Serverless Framework allow us to use plugins (or create one) that hook into the lifecycle events during the deploy process. We can hook into the "before:deploy:deploy" event to setup files and variables before the deploy begins. We can hook into the "deploy:finalize" hook to save some information about the deployment. There are numerous possibilities that plugins enable.

There are plugins that:

  • Create a serverless web site
  • Enabling AWS CloudFormation stack termination protection
  • Configure AWS IAM policies per function

And many more.

To use a plugin, we install the npm package:

npm install --save-dev serverless-iam-roles-per-function

Add the plugin to our Serverless configuration file (serverless.yml):

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

And, follow any instructions and settings the plugin requires.

We have now improved and simplifies our serverless deployment.

Not all plugins have the same level of security

The plugins are built by the Serverless community. Anyone can create a plugin. The Serverless Framework company lists plugins, but only a subset are "approved." This means we should be cognizant of what we are using.

One plugin, allows us to add if-else statements in our serverless.yml file: Serverless Plugin IfElse plugin. This plugin is useful because we can adjust our Serverless configuration depending on the deployment scenario.

For example, we can deploy functions specific to our dev stage, and exclude them from the others.

service: insecure-plugins

provider:
  name: aws
  runtime: nodejs12.x
  stage: ${opt:stage, 'dev'}
  region: us-east-1

functions:
  dev:
    handler: dev.handler

plugins:
  - serverless-plugin-ifelse

custom:
  serverlessIfElse:
    - If: '"${self:provider.stage}" != "dev"'
      Exclude:
        - functions.dev

Our dev stage will deploy the dev function to the dev stage and all other stages will not have it. Nice!

After inspecting the code, I saw something interesting on line 27 for how it evaluate the if statement.

if (eval(item.If)) {

Let's see if this works as we expect.

Launching an exploit using the plugin

I updated my serverless.yml to include some Node code.

service: insecure-plugins

provider:
  name: aws
  runtime: nodejs12.x
  stage: ${opt:stage, 'dev'}
  region: us-east-1

functions:
  dev:
    handler: dev.handler

plugins:
  - serverless-plugin-ifelse

custom:
  serverlessIfElse:
#    - If: '"${self:provider.stage}" != "dev"'
    - If: 'const cp = require("child_process"); cp.execSync("touch hello.txt");'
      Exclude:
        - functions.dev

I deployed the configuration and noticed the following:

  • It deleted the dev function because the if statement does not return a truthy value.
  • I found an empty file named hello.txt in the folder.

This is an example how a plugin can reduce our security posture. Granted, someone would have to insert a rogue command and get it past us in the code review process for this exploit to work. Keep in mind, the plugin code could do something malicious because it has access to the AWS services permitted by the IAM policies used to deploy the Serverless configuration.

Conclusion

Serverless Framework plugins are great, but we need to understand what they do by inspecting the source code. We must be careful to understand whether they can potentially do something malicious.

View the source code at https://github.com/miguel-a-calles-mba/secjuice/tree/master/insecure-plugins.

Before you go

About the author


Originally published on Secjuice.com

Photo by Dmitry Ratushny on Unsplash

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐