Dissecting the Cloudy Cloudtrail logs

Wei Chea Ang
5 min readOct 15, 2021

The opinions expressed in this post are my own and not necessarily those of my employer

Overview

AWS Cloudtrail is a service that logs AWS activity and provides visibility into activities in AWS environment. It is used when performing security investigations on AWS to piece out activities made by a principal and some organization also uses it to build some of the detections.

I’m going to use CloudGoat, Pacu by Rhino Security Labs, and awscli to look at what are the activities logged by Cloudtrail when attacks happened on CloudGoat to help us better understand how actions on AWS tie into the Cloudtrail logs.

Scenario

I’m not going to cover the details for each scenario as the GitHub repo has documented well for each scenario. Instead, I will go straight into the attacks using the cheat sheet to identify what AWS activities are logged and why they happened.

iam_privesc_by_rollback

Resource Created by scenario:
IAM: raynor-iam_privesc_by_rollback_*
Policies: cg-raynor-policy-iam_privesc_by_rollback_*

Since the scenario is to perform privilege escalation from a limited privileged user, I tried using Pacu module “iam__privesc_scan”. Before the module is executed, multiple prerequisite modules need to be executed to recon the different resources (eg: users/roles/policies) to identify the possible privilege escalation path based on permissions that the identity has.

iam__enum_permissions

Below are the activities when “iam__enum_permissions” is executed using Pacu. The APIs called are Get*/List* events which are used to recon the identity.

GetCallerIdentity
ListGroupsForUser
ListUserPolicies
ListAttachedUserPolicies
GetPolicyVersion
GetPolicy
ListPolicyVersions

iam__enum_permissions

The iam__privesec_scan module has multiple methods (Eg: “CreateAccessKey”, “PassExistingRoleToNewLambdaThenInvoke”, “CreateNewPolicyVersion”) to perform privilege escalation. For this scenario, because the identity has the “SetDefaultPolicyVersion” permission, so it was possible to set the policy to an older version that has “Allow Action and Resource *” permission.

iam__privesec_scan
SetDefaultPolictVersion event

lambda_privesc

Resources created by scenario:
IAM user: chris-lambda_privesc_*
Role: cg-lambdaManager-role-lambda_privesc_*
Role: cg-debug-role-lambda_privesc_*

Similar to the previous scenario, Get*/List*APIs were made to recon the permission the identity has. Besides that, there was also a “ListAttachedRolePolicies” event that was used to obtain policies attached to the “cg-lambdaManager-role” and “cg-debug-role”. The API call will return the managed policies that are attached to the “chris-lambda_privesc” user.

recon events

The next event was “AssumeRole” which was used to assume “cg-lambdaManager-role”. When AssumeRole API is made, it will return temporary accessKey, secreyKey, and session token, which is used to assume the lambdaManager role.

AssumeRole event

After the“AssumeRole” is called, the access key is changed from AKIA* (long-term credential) to the ASIA* key(temporary credential) which was returned from the “AssumeRole” event. For the “Invoke” event, it can be seen that it is using the ASIA* key.

It is important to understand that a temporary access key is generated when the “AssumeRole” event happens and the subsequent events will be using the temporary access key. It is possible that AssumeRole could be made by a temporary access key which then returns another temporary access key. When tracking down the initial identity that is responsible for an event for such a scenario, it is required to pivot through multiple temporary access keys before getting to the initial identity.

AssumeRole accessKey changed

From the Couldtrail event, it showed that the identity type for the “CreateFunction” event is “AssumedRole” and it was requested to be executed by the “cg-debug-role” which has the “AdministratorAccess” policy attached.

CreateFunction event

The “codeSha256” value is not a direct SHA256 hash of the lambda function zip file. In the event you want to confirm the actual hash of the zip file, you could do it via Cyberchef by decoding the hash then use the “To Hex” step.

decoding the hash

The function was then executed which logged the“Invoke” event. The event was executed by the “cg-lambdaManager-role”, however as seen from the CreateFunction event, the function will be executed by the “cg-debug-role”.

The “Invoke” event is the Data event type that is not enabled by default. To have it logged, it needs to be enabled in the trail configuration.

Invoke event

And the last event is “AttachUserPolicy” which is attaching a managed policy (AdministratorAccess)to the IAM user “chris-lambda_privesc”.

Conclusion

For this post, we covered some of the AWS APIs, the concept of AssumeRole, permanent access key and temporary access key. I will cover the other CloudGoat scenarios in the subsequent post.

Reference

https://github.com/RhinoSecurityLabs/cloudgoat
https://github.com/RhinoSecurityLabs/pacu
https://www.authomize.com/blog/solving-the-aws-roles-mystery/
https://stackoverflow.com/questions/50082732/what-is-exactly-assume-a-role-in-aws

--

--