The serverless paradigm offers solutions to application building and deployment without the challenges of infrastructure management. Organizations no longer need to perform capacity planning of any kind, like figuring out the necessary amounts of CPU, memory, disk, and database storage. A serverless offering from a cloud service provider handles these, ensuring rapid time-to-market. Product teams only need to focus on developing applications with the following characteristics:
- Stateless: serverless applications serve every user request from a new application instance. The application must be stateless in all respects. It can’t rely on any disk persistence or previously served in-memory values
- Ephemeral: serverless applications are not long-lived. An incoming request creates an application instance. Post-request handling destroys this
- Event-processing: events from other components in the ecosystem like HTTP requests, database entries, or inbound message notifications trigger serverless workflows. Often this is across the complete enterprise stack
As mentioned, Serverless providers have developed products to support diverse needs from web development to data analysis. They provide computing services like AWS Lambda, Google Cloud Functions, and Azure Functions. They also offer storage services like S3, DynamoDB, and routing services like application programming interface (API) gateways.
Application Security
Since organizations that predominately consume serverless architecture are no longer maintaining infrastructure, they need to adjust their focus from infrastructure security practices. This includes things like patch management, firewalls, and network security. But this doesn’t mean the applications are inherently safe on the serverless platform. Instead, the security focus shifts from infrastructure to application runtime protection.
Research by Cloud Security Alliance found that serverless architectures are prone to application code and configuration security risks. A typical serverless application consists of many deployed functions, with each function supporting a single feature. This is different from a web application having a single service offering many features. So, the surface area of attack on a serverless application is considerably more than a single web application.
Serverless architecture needs a novel approach to handling security. Effective serverless security focuses on the following practices:
- Access control: Cloud best practices use the principle of least privilege for executing serverless applications. This means providing the minimum required permissions to a function for accessing other services. For example, if an AWS Lambda function must access a DynamoDB table, we must make sure it can only perform the specific action the business logic requires.
- Secure coding: OWASP technology uses an agnostic practice of developing secure code.
- Vulnerability scanning: This periodically scans application code and configuration to determine any vulnerabilities in its dependencies or configuration.
- Behavior protection: This determines malicious events using application behavior mapping.
Trend Micro provides runtime application self-protection (RASP) as a solution for application behavior analysis and protection. In this article, we’ll see how to protect serverless applications by using RASP. To follow along, make sure you have access to Amazon Web Services (AWS).
Application Deployment
We are going to deploy the Serverless-Goat application provided by OWASP. The application consists of the following Lambda functions:
- Frontend: This function serves as a static HTML page as an application user interface.
- Convert: This function downloads an HTTP page using the curl command and uploads it to an S3 bucket.
First, log on to the AWS Management Console and access the Lambda dashboard. You can deploy the Lambda function by clicking Create Lambda.
Next, click Create Function. AWS supports Lambda deployment from a source repository. You can either provide your own private repositories, or select applications available from public repositories. The Serverless-Goat public repository is already available in AWS.
There are two applications available, one configured with Node.js 10.x and the other configured with Node.js 12.x. Select the one with Node.js 12.x, as version 10.x is no longer supported.
Now we’re at the review and deploy stage. The dashboard’s view shows the application’s CloudFormation template, permissions, and license details. We create the application by clicking Deploy at the bottom of the page.
AWS takes some time to deploy the application. Post-deployment, AWS opens the corresponding application details dashboard. We can also arrive at this dashboard from Lambda’s Applications list view.
On the details page, the API endpoint provides the access URL of the application. We can click the location to open the application user interface. Or, we can invoke the convert function by using the curl command:
curl -L https://acwi9yo4k3.execute-api.us-east
2.amazonaws.com/Prod/api/convert
document_url=https%3A%2F%2Fwww.trendmicro.com%2Fvinfo%2Fhk
en%2Fsecurity%2Fnews%2Fvirtualization-and-cloud%2Fsecurity-101-protecting
serverless-and-container-applications-with-rasp-runtime-application-self
protection
Command Injection Attack
The Serverless-Goat convert function isn’t based on the practices of secure coding. It substitutes the documentUrl query string for the underlying curl command. An adversary can append OS commands to the documentUrl to perform unwanted actions.
curl -L https://acwi9yo4k3.execute-api.us-east
2.amazonaws.com/Prod/api/convert
document_url=https%3A%2F%2Fwww.trendmicro.com%2Fvinfo%2Fhk
en%2Fsecurity%2Fnews%2Fvirtualization-and-cloud%2Fsecurity-101-protecting
serverless-and-container-applications-with-rasp-runtime-application-self
protection%3Bcat%20%2Fetc%2Fpasswd%23%20
Let’s evaluate what damage can be caused by the vulnerability.
OS commands are seemingly innocuous, but they provide an opportunity to steal AWS credentials by executing the environment command:
curl -L https://acwi9yo4k3.execute-api.us-east
2.amazonaws.com/Prod/api/convert?document_url=http%3A%2F%2Ffoobar%3Benv+%23
Or, the adversary can send a fork-bomb command to keep Lambda busy executing commands. The commands would have financial implications, as each execution of a Lambda function has a cost.
Trend Micro Cloud One™ – Application Security
Open vulnerabilities must be closed with good code fixes. Alternatively, the Trend Micro Cloud One™ platform provides an application security (RASP) solution to guard against these vulnerabilities. It can detect, alert, and prevent exploits in the application.
Let’s walk through how to deploy RASP with minimal changes to your Lambda. You will need to have an account on the Trend Micro Cloud One platform.
After logging on to a Trend Micro Cloud One account, access the Application Security dashboard by clicking Application Security.
The Application Security dashboard enables us to configure security guidelines (also called policies) in logical units called groups. Each group is associated with an API key, and an API secret to enforce security policies attached to an application. We should create a group for the deployed Serverless-Goat application. After group creation, we find the required credentials in the Group Configuration view.
The Policies dashboard lists all enabled policies. Each of these policies is in either of the following two modes:
- Report: detect and alert all policy violations
- Mitigate: detect, alert, and block all policy violations
Each policy starts with a default ruleset. The Policies dashboard provides the capability to update the policy rule sets. To avoid false alerts, we need to update the policy rule set to allow intended invocations of the respective policy.
The deployed Serverless-Goat application executes a curl command, which must be allowed to avoid false alerts. Let’s open the Remote Command Execution Policy Configuration dashboard. The policy rule set does not allow any commands. We must add a new rule to allow commands, as follows:
\./bin/curl \-\-silent \-L \S* \| /lib64/ld\-linux\-x86\-64\.so\.2
\./bin/catdoc \-
The application also loads all node dependencies from the /var/runtime/node_modules/* path. We must enable this path to avoid false file access alerts.
Enable Security
To protect Lambda functions, we must enable Application Security with the group configuration created above. The Serverless-Goat application applies Application Security to the convert function. Select the function from the Lambda dashboard.
Trend Micro Cloud One provides runtimes for Node.js based and Python-based Lambda functions. We can install the runtime by adding a layer from the function dashboard. To do this, click Add a layer.
We need to provide an appropriate runtime Amazon Reference Number (ARN) on the Add layer console. This number is composed of AWS region information, node version, and a release version. Use the runtimes page to determine the appropriate reference number.
For the Serverless-Goat application, if working with the Ohio (us-east-2) region the ARN would be arn:aws:lambda:us-east-2:800880067056:layer:CloudOne-ApplicationSecurity-runtime-nodejs12_x:1. Enter the ARN in the Specify an ARN field and click Add.
Now that we have added the Application Security Runtime, all that’s left is to enable it in the function. We need to make the following changes:
// Step 1: Import Runtime
var trend_app_protect = require('trend_app_protect');
// Step 2: Get Handler Function
var _handler = async (event) => {
// Removed for brevity
};
// Step 3: Apply Runtime to Handler
exports.handler =
trend_app_protect.api.aws_lambda.protectHandler(_handler);
We must also add environment variables on the Configuration tab (on the Environment Variables page) before deploying the updated version:
TREND_AP_KEY: < key from Application Security Dashboard >
TREND_AP_SECRET: < secret from Application Security Dashboard >
TREND_AP_READY_TIMEOUT: 30
TREND_AP_TRANSACTION_FINISH_TIMEOUT: 10
TREND_AP_MIN_REPORT_SIZE: 1
TREND_AP_INITIAL_DELAY_MS: 1
TREND_AP_MAX_DELAY_MS: 100
TREND_AP_HTTP_TIMEOUT: 5
TREND_AP_PREFORK_MODE: False
TREND_AP_CACHE_DIR: /tmp/trend_cache
TREND_AP_LOG_FILE: STDERR
Capture Vulnerabilities
The updated function doesn’t change the application’s behavior. We can access the API to validate the intended use cases. The use cases also verify any false alerts raised by Application Security.
curl -L https://acwi9yo4k3.execute-api.us-east
2.amazonaws.com/Prod/api/convert?document_url=http%3A%2F%2Fexample.com
Next, we can perform command injection by appending the `ls -l / #` command.
curl -L https://acwi9yo4k3.execute-api.us-east
2.amazonaws.com/Prod/api/convert
document_url=http%3A%2F%2Fexample.com+%3B+ls+-l+%2F+%23
The command still succeeds, but Application Security captures the exploit and raises alerts on the Events dashboard. We can select an individual event to see detailed information like the actual command, time, client IP, and so on.
Finally, we can block all attacks by updating the policy configuration to Mitigate mode. As discussed before, we can apply this mode in the Group Configuration view. Then the same command fails with the following response:
OverrideResponse: Response overridden by Trend App Protect
at Transaction.runHook
(/opt/nodejs/node_modules/trend_app_protect/lib/transaction.js:30:11)
at Object.<anonymous
(/opt/nodejs/node_modules/trend_app_protect/lib/plugins/shell_command.
js:31:19)
at Object.wrapped [as execSync]
(/opt/nodejs/node_modules/trend_app_protect/lib/plugins/index.js:282:20)
Next Steps
Serverless platforms provide accelerated delivery to product teams while shifting the onus of security on application developers. The process needs ways to identify and block vulnerabilities until security fixes are delivered. Application Security enables detection, alerts, and blocks all vulnerabilities.
See how Application Security helps catch unexpected security issues with a free, 30-day trial.