Vulnerable Lambda Application

This application is a modified version of our original Hello World application. In this example we will purposely introduce a vulnerability and show how Intrinsic mitigates exploitation of this vulnerability.

Previously we had hardcoded a URL for making outbound requests. Now we will accept the URL from the point of invocation. Of course, this is absolutely insecure and represents an extreme security risk. Production code should never rely on such a feature.

Code for handler.js

const http = require('http');
const credentials = require('./credentials.json');

exports.myfunc = (event, context, callback) => {
  // Warning: Dangerous Anti-Pattern
  http.get(`${event.url}?auth=${credentials}`, res => {
    res.on('error', callback);
    const received = [];

    res.on('data', data => {
      received.push(data);
    });

    res.once('end', () => {
      callback(null, {
        len: Buffer.concat(received).length
      });
    });
  });
};

In this situation we are trusting the data being provided to us when the handler is invoked. We assume that the destination URL will always be a safe one. Unfortunately if an attacker were to make a request to our Lambda function they could then steal our sensitive information (i.e., the credentials data) by sending it to a server they control.

This example is a little contrived, but you can imagine other scenarios where a path segment isn't sanitized properly and contains ../../etc/passwd, or if we are determining arguments for a file to pass to rm -rf and are provided / # normal-file.jpg by an attacker.

Code for intrinsic.js

With the following configuration we are only allowing outbound requests to any URLs located under the trusted api.intrinsic.com domain:

const IntrinsicLambda = require('@intrinsic/lambda');

module.exports = new IntrinsicLambda()
  .configurePolicies(policy => {
    policy.outboundHttp.allowGet('https://api.intrinsic.com/**');
  })
  .setHandlerName('myfunc')
  .setHandlerFile(`${__dirname}/handler.js`)
  .run();

With Intrinsic running, any requests made which would normally send credentials to a foreign server would instead result in an error with the outbound request never being made.

Example Output

If we run our vulnerable Function on Lambda and invoke the function with a url parameter of https://api.intrinsic.com/account, the request will succeed and the application will run as per usual. However, if an attacker were to invoke our Function and specify a url parameter such as http://evil.example.com/, the request would fail and the error event would fire. When this happens you will see the following message in your Amazon CloudWatch Logs.

CloudWatch Logs for Policy Violation