WeirdAAL (AWS Attack Library) Basics from the Authors

EH-Net - Gates - WeirdAAL - Weird Al Raiders PicThe cloud is everything. Organizations have either moved completely to the cloud, have a hybrid approach, or are actively planning a cloud strategy. Penetration testers have always had to provide their services anywhere the client’s environment takes them. This often leads to finding vital information and credentials for their cloud provider of choice. With Amazon Web Services (AWS) being the number one player, finding AWS keys has become very common. But how does one utilize that recon information to further their attacks? Pivoting into these machines or querying the exposed services would make for a much more thorough assessment, but what type of access is available once there? That’s why we created an AWS Attack Library (WeirdAAL).

WeirdAAL has two goals related to the AWS keys you find, procure, or need to test. First, answer the “what can I do with this AWS key pair” from a blackbox perspective. Secondly, be a repository of useful functions, both offensive and defensive, to interact with AWS Services. This article is meant to be a basic tutorial to get you started.

Background on WeirdAAL

EH-Net - Gates - WeirdAAL - AWS LogoWith fancy web GUIs, APIs and scripting, cloud providers have made it incredibly easy to spin up new virtual machines. So much so that it has allowed for organizations to massively increase their DevOps capabilities, often without the proper controls in place to manage this new attack surface. Ken Johnson and I have given a few talks [1][2][3] around common DevOps mistakes that can be made. Each of these talks contained sections on how AWS keys can become compromised.

The problem with finding yourself with an AWS key pair is that it can be quite difficult to have a full accounting of what AWS services the key pair has access to without privileges for the client’s Identity and Access Management (IAM) system. During a penetration test (especially black box), you’ll most certainly not have this level of access, therefore answering the “what can I do with this key” question becomes important. WeirdAAL is designed to answer this question.

The Basics of WeirdAAL

Boto3, the AWS SDK for Python, currently supports 136 AWS services. WeirdAAL uses python3 and the boto3 library to ask each service the “do I have permissions to interact with this service” question against functions that take no arguments. Of the 136 services, approximately 125 have at least one of these types of functions.

Getting started is fairly straightforward. Clone the repository, create your python3 virtual environment and install the requirements. Once things are installed, copy the env.sample file to .env and populate it with the AWS key pair you’re testing. The file expects the same format as a normal .aws/credentials file.

EH-Net - Gates - WeirdAAL - Figure 1Figure 1: sample AWS key in .env file


WeirdAAL overwrites the local AWS_SHARED_CREDENTIALS_FILE environment variable with the contents of the .env file. By using the .aws/credentials file format and boto3, WeirdAAL also natively supports all types of AWS key pairs including key pairs with STS tokens.

After you have set the key, it’s fairly easy to get going. WeirdAAL has two command line requirements: –m for the module you want to run and –t for the target name. Multiple keys can exist under the same target.

$ python3 
usage: [-h] -m MODULE -t TARGET [-a ARGUMENTS] [-l] [-v] error: the following arguments are required: -m/--module, -t/--target

There are currently 28 modules from which to choose, and all are listed in the Wiki section of the GitHub repo. Some modules take arguments, and those can be passed with the –a flag. The first module you’ll want to run is the recon_all module. This module will attempt to interact with those aforementioned AWS services and attempt to enumerate what services the key has access to.


If the key pair is invalid, WeirdAAL will let you know.

$ python3 -m recon_all -t demo
The AWS Access Keys are not valid/active
Check the above error message and fix to use weirdAAL

If the key is a root key, you’ll have access to everything. If you have IAM access, WeirdAAL will also attempt to check the Multi-Factor Authentication (MFA) status on accounts, whether they have IAM console access, and if it looks like those accounts can be reset or not (if you want to get heavy handed).

$ python3 -m recon_all -t demo
Account Id: 54889XXXXXXX
Root Key!!! [or IAM access]
Printing Account Summary
{ 'AccessKeysPerUserQuota': 2,
 'AccountAccessKeysPresent': 1,
 'AccountMFAEnabled': 0,
 'AccountSigningCertificatesPresent': 1,
 'AssumeRolePolicySizeQuota': 2048,
 'AttachedPoliciesPerGroupQuota': 10,
 'AttachedPoliciesPerRoleQuota': 10,
 'AttachedPoliciesPerUserQuota': 10,
 'GroupPolicySizeQuota': 5120,
 'Groups': 1,
 'GroupsPerUserQuota': 10,
 'GroupsQuota': 300,
 'InstanceProfiles': 3,
 'InstanceProfilesQuota': 1000,
 'MFADevices': 0,
 'MFADevicesInUse': 0,
 'Policies': 1,
 'PoliciesQuota': 1500,
 'PolicySizeQuota': 6144,
 'PolicyVersionsInUse': 20,
 'PolicyVersionsInUseQuota': 10000,
 'Providers': 0,
 'RolePolicySizeQuota': 10240,
 'Roles': 12,
 'RolesQuota': 1000,
 'ServerCertificates': 0,
 'ServerCertificatesQuota': 20,
 'SigningCertificatesPerUserQuota': 2,
 'UserPolicySizeQuota': 2048,
 'Users': 5,
 'UsersQuota': 5000,
 'VersionsPerPolicyQuota': 5}
Printing Users
[ { 'Arn': 'arn:aws:iam::5488XXXXXXXX:user/bin',
 'CreateDate': datetime.datetime(2018, 5, 27, 19, 43, 53, tzinfo=tzutc()),
 'PasswordLastUsed': datetime.datetime(2018, 5, 27, 19, 44, 48, tzinfo=tzutc()),
 'Path': '/',
 'UserId': 'AIDA-REMOVED',
 'UserName': 'bin'},
 { 'Arn': 'arn:aws:iam::54889XXXXXXX:user/s3',
 'CreateDate': datetime.datetime(2018, 2, 3, 1, 5, 26, tzinfo=tzutc()),
 'PasswordLastUsed': datetime.datetime(2018, 6, 2, 3, 46, 8, tzinfo=tzutc()),
 'Path': '/',
 'UserId': 'AIDA-REMOVED',
 'UserName': 's3'}]
Checking for console access
User bin likely has console access and the password can be reset :-)
Checking for MFA on account
User s3 likely has console access and the password can be reset :-)
Checking for MFA on account
### Enumerating ACM Permissions ###
ListCertificates IS allowed

[+] acm Actions allowed are [+]

### Enumerating AWS Certificate Manager Private Certificate Authority (ACM-PCA) Permissions ###
ListCertificateAuthorities IS allowed

[+] acm-pca Actions allowed are [+]


Generally you’ll find accounts that have access to a handful of services like this one:

$ python3 -m recon_all -t demo
Account Id: 1928XXXXXXXXX
AKIAIG7-REMOVED : Is NOT a root key
### Enumerating ACM Permissions ###
An error occurred (AccessDeniedException) when calling the ListCertificates operation: User: arn:aws:iam::1928XXXXXXXXX:user/python is not authorized to perform: acm:ListCertificates

[-] No acm actions allowed [-]

### Enumerating AWS Certificate Manager Private Certificate Authority (ACM-PCA) Permissions ###
An error occurred (AccessDeniedException) when calling the ListCertificateAuthorities operation: User: arn:aws:iam::1928XXXXXXXXX:user/python is not authorized to perform: acm-pca:ListCertificateAuthorities

[-] No acm-pca actions allowed [-]
… SNIP …
### Enumerating Autoscaling Permissions ###
DescribeAccountLimits IS allowed
DescribeAdjustmentTypes IS allowed
DescribeAutoScalingInstances IS allowed
DescribeAutoScalingGroups IS allowed
DescribeLaunchConfigurations IS allowed
DescribeScheduledActions IS allowed
DescribeTags IS allowed
DescribeTerminationPolicyTypes IS allowed
DescribePolicies IS allowed

[+] autoscaling Actions allowed are [+]
['DescribeAccountLimits', 'DescribeAdjustmentTypes', 'DescribeAutoScalingInstances', 'DescribeAutoScalingGroups', 'DescribeLaunchConfigurations', 'DescribeScheduledActions', 'DescribeTags', 'DescribeTerminationPolicyTypes', 'DescribePolicies']


### Enumerating DynamoDB Permissions ###
ListTables IS allowed
DescribeLimits IS allowed
ListBackups IS allowed
ListGlobalTables IS allowed

[+] dynamodb Actions allowed are [+]
['ListTables', 'DescribeLimits', 'ListBackups', 'ListGlobalTables']

### Enumerating DynamoDBStreamsPermissions ###
ListStreams IS allowed

[+] dynamodbstreams Actions allowed are [+]
### Enumerating Amazon WorkMail Permissions ###
An error occurred (AccessDeniedException) when calling the ListOrganizations operation: User: arn:aws:iam::1928XXXXXXXXX:user/python is not authorized to perform: workmail:ListOrganizations

[-] No workmail actions allowed [-]

Once recon_all is complete, you can list the identified services with the list_services_by_key module.

$ python3 -m list_services_by_key -t demo

Services enumerated for AKIAIG7-REMOVED

Getting Creative

At this point, you can start to pivot and enumerate more services using the additional WeirdAAL modules. In this case the account has EC2 privileges, DynamoDB, RDS, S3, etc. permissions, and you’d want to start running those additional modules against the various services to see what data or access those services can provide to you. For example we might check out the S3 portion of the wiki to see what functionality exists.

Listing buckets seems like a good place to start:

$ python3 -m s3_list_buckets –t demo
 #### Trying to list s3 bucketsfor AKIAIG7-REMOVED ####


Further peeking into one of the buckets:

$ python3 -m s3_list_bucket_contents -a "subdomain-takeover-poc" -t demo

#### Attempting to list s3 bucket contents for subdomain-takeover-poc ####

We might even want to download a file:

$ python3 -m s3_download_file -a 'subdomain-takeover-poc','upload.txt' -t demo
 file downloaded to: /Users/CG/Documents/pentest/weirdAAL-updated/loot/upload.txt

lookupfailed-2:weirdAAL-updated CG$ more loot/upload.txt
 hello from the internet

At this point, you might be thinking why is this better than the AWS CLI? Excellent question! Because WeirdAAL uses python and boto3, doing things across multiple regions or multiple instances becomes much easier than piping awscli output to other things.

To back up this claim, I’d suggest you check out the ec2_get_console_output_all and ec2_get_console_output_all_region modules to get an idea of what you can do when you need to run a command against all instances in a region or all instances against all regions.

Example output is below:

EH-Net - Gates - WeirdAAL - Figure 2
Figure 2: Running the get_console_output_all_region module against all instances in a specific region


If you are unsure what modules exist you can check out the WeirdAAL Wiki.

All the modules are documented to include sample command line usage including the potential arguments required. Similar to the following screenshots:

EH-Net - Gates - WeirdAAL - Figure 3

Figure 3: EC2 module documentation


EH-Net - Gates - WeirdAAL - Figure 4

Figure 4: EC2 module documentation showing modules that require arguments

Use It

After consuming the content of this new article, hopefully it was enough to pique your interest. Once again, you can check out WeirdAAL at the carnal0wnage GitHub Repository. Issues, comments and suggestions are welcome.

The most recent presentation on WeirdAAL that shows many more examples and awesome Weird Al memes can be found on SlideShare.

We’d also love to hear your feedback on the article and ways in which WeirdAAL has helped you during your own pen tests. Please add your comments below and also consider contributing to the project.


Author Bio

EH-Net - Gates - WeirdAAL - Author PicChris Gates, Sr Security Engineer, has been breaking things professionally for over a decade via Network & Web Application Penetration Testing, Red Teaming & Adversarial Simulation.  These days Chris splits his time being both a breaker and fixer. Chris is the author of Metta, a tool for adversarial simulation and contributes to other open source projects. In the past he has spoken at the United States Military Academy, BlackHat, DefCon, Wild West Hacking Fest, Toorcon, Brucon, Troopers, SOURCE Boston, Derbycon, LasCon, HashDays, HackCon, Bsides ATL, IT Defense, OWASP AppSec DC, and Devops Days. Chris is also a cofounder of NoVAHackers.  Blog: Twitter: @carnal0wnage Talks:

All Articles by Chris Gates

*** This is a Security Bloggers Network syndicated blog from The Ethical Hacker Network authored by Chris Gates. Read the original post at: