The AWS Command Line Interface (AWS CLI) can be used to access AWS resources through a command line utility. To setup the AWS CLI environment, notably the configuration of credentials, the aws configure command may be used.
The aws configure will ask for the following information, that will be stored (in clear-text) in the config and credentials files (by default in a .aws folder in the current's user home directory):
The following commands can be used to retrieve basic information about the AWS account:
# Retrieves information about the IAM entity usage (number of users, groups, roles, etc.).awsiamget-credential-report# Lists the IAM users, with their creation date and password last used timestamp.awsiamlist-users# Lists the users'access keys, with their status and creation date.awsiamlist-access-keys# Lists the IAM groups (collection of IAM users that can be associated with specific permissions).awsiamlist-groups# Retrieves the groups associated with a given user.awsiamlist-groups-for-user--user-name"<USERNAME>"# Lists the IAM roles (an IAM identity that can be associated with specific permissions. An IAM role can be assumed can users allowed to do so).
awsiamlist-roles# Lists all the IAM policies (an IAM policy grants IAM identities - users, groups, or roles - to resources. Permissions in the policies determine whether an IAM principal (user or role) request is allowed or denied.)
awsiamlist-policies# Lists all the IAM policy names and ARN.awsiamlist-policies--query'Policies[*].[PolicyName, Arn]'--outputtext# Lists the metadata of the specified IAM policy.awsiamlist-policies--query'Policies[?PolicyName==`<POLICY_NAME>`]'# Retrieves the IAM policies associated with the specified user / group / role.# Inline IAM policies embedded in the specified IAM user.awsiamlist-user-policies--user-name"<USERNAME>"# IAM policies attached to the specified IAM user.awsiamlist-group-policies--group-name"<GROUPNAME>"awsiamlist-role-policies--role-name"<ROLENAME>"# Lists all the IAM users, groups, and roles that the specified policy is attached to.# Example policy ARN: arn:aws:iam::aws:policy/service-role/AWSApplicationMigrationReplicationServerPolicyawsiamlist-entities-for-policy--policy-arn"<POLICY_ARN>"# Lists the version associated with an IAM policy.awsiamlist-policy-versions--policy-arn"<POLICY_ARN>"# Retrieves the permissions associated with an IAM policy (and policy version).awsiamget-policy-version--policy-arn"<POLICY_ARN>"--version-id"<v1 | POLICY_VERSION_ID>"# Lists the S3 buckets in the account.awss3ls# Retrieves more detailed (compared to s3 ls) information on a bucket (and bucket files).awss3apilist-objects--bucket<BUCKET_NAME># Download / upload files from / to a S3 bucket.# Source / destination for s3://<BUCKET> or local path.awss3cp [--recursive] <SOURCE><DEST>
Automated enumeration with ScoutSuite
Scout Suite leverage the API provided by AWS (as well as other possible Cloud providers) to automatically enumerate the configuration of the account. It can be used to quickly gather information on the attack surface of the AWS account across all regions.
A number of log sources are available in AWS that can be useful for incident response purposes:
Name
Description
CloudTrail
Logs of every operation conducted in the AWS account. Essentially logs all API calls made in the account.
For each action / operation, the following information are logged:
- Unique Event ID.
- Event name (such as ListPolicies, AssumeRole, etc.).
- The timestamp of the operation.
- The region the operation was conducted in.
- Information on who realized the action (IAM identity, source IP address, user agent).
- The eventual impacted resource.
- The eventual request parameters.
- ...
CloudWatch
System performance metrics, such as CPU usage, filesystem or network inputs/outputs, etc.
An additional CloudWatch agent can be installed on EC2 hosts to forward OS-level logs to CloudWatch.
Additionally, CloudTrail logs can be forwarded to CloudWatch, for instance to configure automated alerting.
Config
Logs periodically the configuration state of a number of resources (EC2, VPC, security groups, etc.). Can be used to detect change in configuration and retrieve historical data on configuration changes (who and when was a given resource created / modified).
S3 Access Logs
Logs bucket-level activities, i.e access, upload, modification, and deletion of data stored in a S3 bucket (versus operation on the bucket object itself as logged by CloudTrail).
S3 Access Logs i disabled by default and must be enabled on a per bucket basis.
VPC Flow Logs
Logs VPC-level IP network traffic to CloudWatch.
Different version of VPC Flow Logs, 2 to 5 to date, can be enabled. Higher versions record an increased number of fields per record. The version 2, enabled by default, records the following fields (in order):
- version number.
- account id (AWS account ID of the owner of the source network interface for which traffic is recorded).
- interface id (ID of the network interface for which the traffic is recorded).
- source address.
- destination address.
- source port.
- destination port.
- network protocol.
- number of packets transferred during the "flow" log.
- number of bytes transferred during the "flow" log.
- start of the "flow" log.
- end of the flow log.
- whether the traffic was accepted (ACCEPT) or rejected (REJECT).
- status of the flow log.
For more information on VPC Flow Logs, refer to the official AWS documentation.
WAF Logs
Logs requests processed by the AWS WAF service. WAF Logs can notably be forwarded to CloudWatch or stored in a S3 bucket.
Information about the request (source IP, eventual requests headers, eventual parameters, etc.) as well as the rule matched are logged.
AWS logs collection
Multi-regions CloudTrail logs export
The awsCloudTrailDownload.py Python script can be used to download the CloudTrail logs across all regions.
pythonawsCloudTrailDownload.py
Automated logs export with Invictus-AWS
The Invictus-AWS Python script can be used to retrieve information about the environment (service usage and configuration) and export logs from a number of sources (CloudTrail, CloudWatch, S3 Access Logs, ...) to an S3 bucket. Invictus-AWS is region bound.
# Configures the required API access.
aws configure
# Exports the configuration and logs from the specified region (such as "us-east-1").
python3 invictus-aws.py --region=<REGION>
# Downlaods locally the exported / collected elements from invictus-aws.py.
aws s3 cp --recursive s3://<INVICTUS_BUCKET> <EXPORT_FOLDER>
awslogs <get | groups | streams> [--aws-region "<AWS_REGION>"] [--aws-access-key-id "<ACCESS_KEY_ID>"] [--aws-secret-access-key "<ACCESS_KEY_SECRET>"]
# Lists the existing logs groups.awslogsgroups# Lists the streams in the specified log group.awslogsstreams<LOG_GROUP># Retrieves the logs in all or the specified log group / stream.# The start / end filtering support multiple filtering options: DD/MM/YYYY HH:mm, <INT><m | h | d | w>.awslogsget<ALL|LOG_GROUP> <ALL|LOG_GROUP_STREAM> -s<START>-e<END>
CloudTrail logs analysis
CloudTrail key fields
Field name
Description
eventTime
Event timestamp in UTC.
awsRegion
The region the request was made to, such as us-east-1.
eventSource
The service the request was made to.
Such as s3.amazonaws.com for S3 buckets, sts.amazonaws.com for the Security Token Service (STS) for temporary credentials request, etc.
eventName
The request action, matching one of the API for that service.
For example, AssumeRole, ListBuckets, SendCommand, etc.
errorCode
The error code and human-readable error message associated with an event if (and only if) the operation failed.
readOnly
Whether the operation is a read-only operation (true or false).
userIdentity
Information about the user that made the request.
* userIdentity.type: the type of the identity.
Possible types:
- Root: account root user.
- IAMUser: IAM user.
- AssumedRole: temporary security credentials obtained with a role by making a call to the AWS STS's AssumeRole API.
- Role:
- FederatedUser: temporary security credentials for a federated user (Active Directory, AWS Directory Service, etc.), obtained via a call to the AWS STS's GetFederationToken API. - AWSAccount: An account from another tenant / AWS account.
- AWSService: AWS account that belongs to an AWS service.
* [Optional] userIdentity.userName: Human readable name of the identity that made the call.
Generally only available for IAMUser or Root identity.
* [Optional] userIdentity.arn: ARN of the entity (user or role) that made the call.
* [Optional] userIdentity.principalId: Unique identifier for the entity that made the call.
For temporary security credentials, this value includes the session name. For instance, for AssumedRole events, the principalId is the unique identifier that contains the role ID and the role session name returned in the AssumeRole event's responseElements.assumedRoleUser.assumedRoleId.
* [Optional] userIdentity.accountId: The account that owns the entity that granted permissions for the request
* [Optional] userIdentity.accessKeyId: The eventual access key ID that was used to make the request.
Access key IDs beginning with AKIA are long-term credentials (for an IAM user or the AWS account root user) while access key IDs beginning with ASIA are temporary credentials (created using AWS STS operations).
* [Optional] userIdentity.sessionContext: Populated for requests made with temporary security credentials to contain information about the session that was created.
userIdentity.sessionContext.creationDate: when the session was created.
userIdentity.sessionContext.mfaAuthenticated: whether the initial credentials were authenticated MFA.
userIdentity.sessionContext.:
userIdentity.sessionContext.sourceIdentity: the original identity (user or role) making the request (with type, arn, userName sub-fields).
sourceIPAddress
The IP address that the request was made from.
For requests from services within AWS, only the DNS name of the service (for example ec2.amazonaws.com) is displayed.
userAgent
The User-Agent through which the request was made.
sessionCredentialFromConsole
Whether the operation was conducted through the web console (true or false).
resources
A list of resource(s) accessed in the event.
For each resource, the following fields may be available:
- type: resource type identifier (in the format: AWS::<AWS_SERVICE_NAME>::<AWS_DATA_TYPE_NAME>).
- ARN: ARN of the resource.
- accountId: account that owns the resource.
requestParameters
The parameters, if any, that were sent with the request.
For example, requestParameters.bucketName, requestParameters.userName, etc.
responseElements
The response element(s) for actions that make changes (create, update, or delete actions).
For example, responseElements.user.createDate, responseElements.accessKey.accessKeyId, etc.
CloudTrail notable API / events
eventSource
eventName
Type
Description
sts.amazonaws.com
GetCallerIdentity
Reconnaissance
Return details about the IAM user or role whose credentials are used to call the operation.
iam.amazonaws.com
ListUsers
Reconnaissance
Enumerate the IAM users in the AWS account, that match the optional specified path prefix requestParameters.pathPrefix.
iam.amazonaws.com
ListRoles
Reconnaissance
Enumerate the IAM roles in the AWS account, that match the optional specified path prefix requestParameters.pathPrefix.
iam.amazonaws.com
ListGroups
Reconnaissance
Enumerate the IAM groups in the AWS account, that match the optional specified path prefix requestParameters.pathPrefix.
iam.amazonaws.com
ListGroupsForUser
Reconnaissance
List the IAM groups that the specified IAM user (by requestParameters.userName) belongs to.
iam.amazonaws.com
ListPolicies
Reconnaissance
Enumerate the IAM policies in the AWS account, that match the optional specified path prefix requestParameters.pathPrefix.
List the managed policies that are attached to the specified IAM user / group / role.
Notable fields:
ListAttachedUserPolicies: requestParameters.userNameListAttachedGroupPolicies: requestParameters.groupNameListAttachedRolePolicies: requestParameters.roleName
iam.amazonaws.com
ListUserPoliciesListGroupPoliciesListRolePolicies
Reconnaissance
List the names of the inline policies embedded in the specified IAM user / group / role.
Notable fields:
ListUserPolicies: requestParameters.userNameListGroupPolicies: requestParameters.groupNameListRolePolicies: requestParameters.roleName
iam.amazonaws.com
GetPolicy
Reconnaissance
Get information about the specified managed policy (by requestParameters.policyArn), including the policy's default version and the total number of IAM users, groups, and roles to the policy is attached to.
iam.amazonaws.com
GetPolicyVersion
Reconnaissance
Get information about the specified version of the specified managed policy, including the policy document.
Notable fields:
requestParameters.policyArnrequestParameters.versionId
s3.amazonaws.com
ListBuckets
Reconnaissance
List the buckets owned by the authenticated sender of the request.
ec2.amazonaws.com
GetConsoleScreenshot
Reconnaissance
Take a screenshot of a running instance.
Notable fields:
requestParameters.instanceIdrequestParameters.wakeUp: whether a keystroke input should be simulated to wake up an instance in standby.
ec2.amazonaws.com
DescribeInstances
Reconnaissance
Enumerate and retrieve information on all or the specified instances.
Notable fields:
requestParameters.instanceId: optional list of instance id(s) to enumerate.
requestParameters.filter: optional filter(s).
sts.amazonaws.com
AssumeRole
Privilege escalation
Return a set of temporary security credentials that can be used to access AWS resources under the privileges granted by the role. A role is a set of policies.
Can be called by IAM principal (user or role).
Notable fields:
requestParameters.roleArn: The ARN of the role to assume.
requestParameters.roleSessionName: a unique identifier (in the form of i-089eb6ce74072ae1f) to identify the session.
requestParameters.durationSeconds: the validity period of the temporary credentials. Minimum value of 900 seconds up to the maximum session duration set for the role (maximum 43200 seconds).
responseElements.assumedRoleUser.arn: the ARN of the temporary security credentials, that will be logged under userIdentity.arn (for API calls made during the session).
responseElements.assumedRoleUser.assumedRoleId: a unique identifier containing the role ID and the role session name, that will be logged under userIdentity.principalId (for API calls made during the session).
responseElements.credentials.accessKeyId: the access key ID that identifies the temporary security credentials, that will be logged under userIdentity.accessKeyId (for API calls made during the session).
responseElements.credentials.expiration: the date on which the current credentials expire.
sso.amazonaws.com
GetRoleCredentials
Privilege escalation
Return a set of temporary security credentials.
Similar to AssumeRole, but can (and must) be called by AWS SSO users, which are not directly IAM principals. AWS SSO users can have permission to assume IAM roles and must do so through GetRoleCredentials.
Notable fields: requestParameters.roleNameresponseElements.credentials.roleCredentials.accessKeyIdresponseElements.credentials.roleCredentials.expiration
iam.amazonaws.com
AttachUserPolicyAttachGroupPolicyAttachRolePolicy
Privilege escalation
Attach the specified managed policy to the specified IAM user / group / role. A policy is the most atomic level of privileges that can be granted.
As a privilege escalation path, the compromised user may be a member of the impacted group or may be able to assume the impacted role.
Notable fields:
requestParameters.policyArnAttachUserPolicy: requestParameters.userNameAttachGroupPolicyrequestParameters.groupName:
AttachRolePolicy: requestParameters.roleName
iam.amazonaws.com
PutUserPolicyPutGroupPolicyPutRolePolicy
Privilege escalation
Add (or update) an inline policy embedded in the specified IAM user / group / role. A policy is the most atomic level of privileges that can be granted.
Notable fields:
requestParameters.policyNamerequestParameters.policyDocument: policy in JSON format.
PutUserPolicy: requestParameters.userNamePutGroupPolicy: requestParameters.groupNamePutRolePolicy: requestParameters.roleName
iam.amazonaws.com
CreatePolicyVersion
Privilege escalation
Create a new version of the specified managed IAM policy, allowing the definition of new permissions (ultimately granted to IAM users, groups, or Roles the policy is linked to).
Notable fields:
requestParameters.policyArnrequestParameters.policyDocument: policy in JSON format.
requestParameters.setAsDefault: whether the new policy version should be set as default, i.e should become the operative version (true of false).
iam.amazonaws.com
SetDefaultPolicyVersion
Privilege escalation
Set the specified preexisting version of the specified policy as the policy's default (operative) version.
The policy version set will impact the IAM users, groups, or Roles the policy is linked to, potentially opening privilege escalation vectors.
Notable fields:
requestParameters.policyArnrequestParameters.versionId
iam.amazonaws.com
AddUserToGroup
Privilege escalation
Persistence
Add the specified user to the specified group.
Notable fields:
requestParameters.userNamerequestParameters.groupName
iam.amazonaws.com
CreateAccessKey
Privilege escalation
Persistence
Create a new AWS secret access key for the user specified by requestParameters.userName.
Notable fields:
responseElements.accessKey.accessKeyIdresponseElements.accessKey.createDateresponseElements.accessKey.statusresponseElements.accessKey.userName
iam.amazonaws.com
CreateLoginProfile
Privilege escalation
Persistence
Create a password for the user specified by requestParameters.userName (to allow the user to access the AWS Management Console).
As a privilege escalation vector, a user (userIdentity.userName) can create a password for a (more privileged) user (requestParameters.userName) to connect as the user through the management console and elevate privileges.
iam.amazonaws.com
UpdateLoginProfile
Privilege escalation
Persistence
Create a password for the user specified by requestParameters.userName (to allow the user to access the AWS Management Console).
As a privilege escalation vector, a user (userIdentity.userName) can reset the password of a (more privileged) user (requestParameters.userName) to compromise that user and elevate privileges.
ec2.amazonaws.com
RunInstances
Execution
Persistence
Create and run new EC2 instance(s).
Notable fields:
requestParameters.instanceType
The requestParameters.instancesSet.items{} list contains (for each request instance):
imageIdtags{} list with a Key=Name with Value=<INSTANCE_NAME>keyName for the key credentials associated with the instance.
The responseElements.instancesSet.items{} list contains (for each created instance):
instanceIdkeyNamesubnetIdprivateIpAddress
ssm.amazonaws.com
SendCommand
Execution
Run command(s) on one or more instances.
Notable fields:
requestParameters.instanceIds / responseElements.command.instanceIds: list of instance ids for the command execution.
requestParameters.documentName / responseElements.documentName: name of the SSM document to run (such as AWS-RunShellScript or AWS-RunPowerShellScript).
requestParameters.parameters: required and optional parameters specified in the document being run (can be HIDDEN_DUE_TO_SECURITY_REASONS for shell / powershell execution).
ssm.amazonaws.com
StartSession
Execution
Initiate a connection to the target instance.
Notable fields:
requestParameters.target: target instance id.
responseElements.sessionId: identifier of the session.
responseElements.streamUrl: an URL on the target instance SSM Agent used by the Session Manager client to send commands and receive output.
responseElements.tokenValue: a token used to authenticate the connection (hidden in CloudTrail).
ssm.amazonaws.com
ResumeSession
Execution
Reconnect a connection after it has been disconnected (but not terminated).
Notable fields:
requestParameters.sessionId: identifier of the disconnected session.
responseElements.sessionId: identifier of the session.
responseElements.streamUrl: an URL on the target instance SSM Agent used by the Session Manager client to send commands and receive output.
responseElements.tokenValue: a token used to authenticate the connection (hidden in CloudTrail).
ec2.amazonaws.com
GetPasswordData
Execution
Persistence
Retrieves the encrypted administrator password for a running Windows instance. The password is encrypted with the key pair specified when the instance was launched.
Notable fields:
requestParameters.instanceId
ec2.amazonaws.com
ModifyInstanceAttribute
Execution
Persistence
Modify the specified attribute of the specified instance.
A modification of the userData attribute can be used to execute code at boot time, requiring a restart of a running instance (StopInstances then StartInstances).
Does not allow the modification of the long-terme key pair(s) associated with an instance. There is no AWS API to conduct such operation.
Notable fields:
requestParameters.instanceIdrequestParameters.attribute (userData for the user data).
requestParameters.userData (specified user data).
ec2.amazonaws.com
SendSSHPublicKey
Execution
Push a temporary SSH public key to the specified EC2 instance for use by the specified user. The key remains for 60 seconds. Used by the EC2 Instance Connect service for SSH access (directly or through the service web-based interface).
Notable fields:
requestParameters.instanceId
lambda.amazonaws.com
CreateFunction
Execution
Persistence
Create a new Lambda function.
Notable fields:
requestParameters.functionNamerequestParameters.code but doesn't include the ZipFile parameter (that contains the base64-encoded contents of the deployment package).
lambda.amazonaws.com
UpdateFunctionCode
Execution
Persistence
Update an existing Lambda function's code.
Notable fields:
requestParameters.functionNamerequestParameters.code but doesn't include the ZipFile parameter (that contains the base64-encoded contents of the deployment package).
s3.amazonaws.com
PutBucketAcl
Exfiltration
Set the ACL of the specified bucket. Note that the use of ACL for S3 is generally deprecated (in favor of using policy).
Notable fields:
requestParameters.bucketrequestParameters.AccessControlPolicy.AccessControlList.Grant.Grantee.URI array : URIs for the container for the entity being granted permissions.
If the array contains the string http://acs.amazonaws.com/groups/global/AuthenticatedUsers or http://acs.amazonaws.com/groups/global/AllUsers, the specified bucket is made public.
s3.amazonaws.com
GetObject
Data access
AWS CloudTrail supports Amazon S3 Data Events, but is not enabled by default.
Retrieve objects from Amazon S3, via the associated API.
Access through the web interface (or a static website leveraging a S3 bucket) will not be logged under CloudTrail (but can be logged in S3 server access logs).
Obtain information about the email-sending status and capabilities of the Amazon SES account (in the current region).
Return a list containing all of the identities (email addresses and domains) of the Amazon SES account (in the current region).
Add an email address to the list of identities Amazon SES account (in the current region) and attempt to verify it.
Enable (or disables email) sending across the entire Amazon SES account in the current AWS Region.
Usage of these APIs by threat actors have been identified in the wild to conduct phishing campaigns following an identity compromise.
iam.amazonaws.com
CreateUser
Persistence
Create a new AWS user in the account.
Notable fields:
responseElements.user.arnresponseElements.user.createDateresponseElements.user.userIdresponseElements.user.userName
ec2.amazonaws.com
CreateKeyPair
Persistence
Create a key pair with the specified name in the AWS Region.
Notable fields:
requestParameters.keyName / responseElements.keyNameresponseElements.keyFingerprintresponseElements.keyPairId
ec2.amazonaws.com
ImportKeyPair
Persistence
Import the public key (previously created), only providing the public key to AWS.
Notable fields:
requestParameters.keyName / responseElements.keyNameresponseElements.keyFingerprintresponseElements.keyPairId
sts.amazonaws.com
GetSessionToken
Credentials access
Persistence
Return a set of temporary credentials for an AWS account or IAM user.
The temporary security credentials created by GetSessionToken can be used to make API calls to any AWS service with the following exceptions:
- Calls to IAM API operations are prohibited unless MFA authentication information is included in the request.
- Calls to STS API are prohibited (except AssumeRole and GetCallerIdentity).
Notable fields:
responseElements.accessKeyIdresponseElements.expiration
CloudTrail logs manual analysis with jq
The jq utility supports querying JSON formatted data and can be used to select and filter events from CloudTrail exported logs.
The following queries illustrate how jq can be used to select, order, and filter events from CloudTrail JSON logs:
# The following queries assume that the exported events are placed in a top-level "Records" field.# Select the specified fields (eventTime, eventName, awsRegion, sourceIPAddress, and userIdentity).jq'.Records[] | {eventTime, eventName, awsRegion, sourceIPAddress, userIdentity}'<JSON_FILE|*># Sorts events by their timestamp.jq'.Records | sort_by(.eventTime)[]'<JSON_FILE|*># Select events between two timestamps.jq ".Records | sort_by(.eventTime)[] | select(.eventTime | . == null or (fromdateiso8601 > $(TZ=UTC date -d"YYYY-MM-DDTHH:MM" +%s) and fromdateiso8601 < $(TZ=UTC date -d"YYYY-MM-DDTHH:MM" +%s)))" <JSON_FILE | *>
# Select the event that modified the account state.jq'.Records[] | select(.readOnly == false)'<JSON_FILE|*># Select the specified event linked to the specified source IP address.jq'.Records[] | select(.sourceIPAddress == <IP>)'<JSON_FILE|*># Select the events that contains the "Get" or "List" keyword.jq'.Records[] | select(.eventName | match("Get|List"))'# Select the events conducted by a given principal.jq'.Records | sort_by(.eventTime)[] | select(.userIdentity.principalId | match("<USERNAME>")?)'*# Count the occurrence by source IP address in a collection of CloudTrail export files.echo'def counter(stream): reduce stream as $s ({}; .[$s|tostring] += 1);counter(.Records[].sourceIPAddress)| to_entries[]| {sourceIPAddress: (.key), Count: .value, file: input_filename}'>ip_count.jqjq-fip_count.jq*