Abusing AWS CloudControl API to stealthily enumerate resources, persist in accounts, and evade detection.
"Identity is the new perimeter" gets thrown around a lot in cloud security discussions, and there's a good reason for it. With the right privileges, almost every cloud resource can be managed through APIs. Each provider has their own way of handling API access through resource-based access control. If your identity has the right permissions for a specific API call, you can execute that action.
The thing is, it's hard to remember every single API call you need to get specific information or access certain resources. AWS recognized this problem and created the AWS CloudControl API, a unified API that groups different resources together so you can create, update, delete, or retrieve them in bulk. This makes managing resources much simpler since you don't need to know which specific service, API call, or parameters to use.
But here's the catch: when something is easy for legitimate users, it's usually easy for attackers too. There are already tools available to use the AWS CloudControl API to pull resource information, and the technique is gaining attention.
But is it actually a good way to do stealthy enumeration? In this article, we examine what the CloudControl API is, how it simplifies resource management, how attackers can weaponize it, its limitations, and detection methods. To illustrate, Exaforce built CloudConqueror, a tool that automates both attack and detection techniques described here.
What is AWS CloudControl API?
AWS CloudControl API is an API offered by AWS to facilitate the management of services and resources inside an account. It supports creation, read, update, deletion, and listing (CRUD-L) operations, without the need to know the service, API call, or input parameters for the API execution.
From the AWS API Documentation for CloudControl API: “Use AWS Cloud Control API to create, read, update, delete, and list (CRUD-L) your cloud resources that belong to a wide range of services, both AWS and third-party. With the Cloud Control API's standardized set of application programming interfaces (APIs), you can perform CRUD-L operations on any supported resources in your AWS account. Using Cloud Control API, you won't have to generate code or scripts specific to each service responsible for those resources.”
It also helps with resource management by grouping resources based on one unifying resource, so that several resources are related to the unifying resource. Under the hood, it uses CloudFormation schemas. For example, when requesting to retrieve an IAM User, the request will return information formatted as follows:
{
"Type" : "AWS::IAM::User",
"Properties" : {
"Groups" : [ String, ... ],
"LoginProfile" : LoginProfile,
"ManagedPolicyArns" : [ String, ... ],
"Path" : String,
"PermissionsBoundary" : String,
"Policies" : [ Policy, ... ],
"Tags" : [ Tag, ... ],
"UserName" : String
}
}
AWS CloudControl allows seven API calls. Five of them are the standard CRUD-L operations. The remaining two are used to list requests and check the status of create, update, or delete operations.
Operation |
API Call |
Required Input Parameters |
List resources of a specific type |
ListResources |
The resource type to list |
Get a specific resource using an identifier |
GetResource |
The resource type and its name as the identifier |
Create a resource on the account |
CreateResources |
The resource type, its name as the identifier, and the resource properties |
Modify a resource’s attributes |
UpdateResource |
The resource type, its name as the identifier, and the resource properties that will be updated |
Delete a resource on the account |
DeleteResource |
The resource type and its name as the identifier |
List create, delete, and update requests being made on the account |
ListResourceRequests |
No input required |
Get the status of a specific resource request |
GetResourceRequestStatus |
The request token is required as input |
AWS maintains a matrix containing all the resource types supported by the AWS CloudControl API, with each resource also including the CRUD-L operation supported. There are currently 1,220 resource types supported, split into 237 services.
The good, the bad, and the ugly of using AWS CloudControl as an attack tool
The good: Accessing Resources using AWS CloudControl
AWS CloudControl API has been used as an attack tool before. It’s mostly used for enumeration, since the API itself can also be used for inventory retrieval of AWS resources. What is less commonly used is AWS CloudControl API’s ability to modify and update resources.
Retrieving resources
AWS CloudControl API makes it simple to retrieve resource names and their configuration. Normally, if the conventional AWS API is used, retrieving all information about a resource might require several API calls.
Typical API call path to retrieve users and relevant dataSince AWS CloudControl API is using CloudFormation schemas, each resource contains several resources, all grouped by one unifying resource. That means, the schema for an AWS IAM User will contain the user information (username, path, permission boundary, tags), login profile, groups, and policies (attached and inline policies).
{
"Type" : "AWS::IAM::User",
"Properties" : {
"Groups" : [ String, ... ],
"LoginProfile" : LoginProfile,
"ManagedPolicyArns" : [ String, ... ],
"Path" : String,
"PermissionsBoundary" : String,
"Policies" : [ Policy, ... ],
"Tags" : [ Tag, ... ],
"UserName" : String
}
}
Two API calls allow resource listing or retrieval. cloudcontrol:ListResources
will list each resource of a type provided.
$ aws cloudcontrol list-resources --type-name AWS::IAM::User
The output returned from cloudcontrol:ListResources
is a JSON list of resource identifiers for the specified resource type.
{
"ResourceDescriptions": [
{
"Identifier": "someUser",
"Properties": "{\\"UserName\\":\\"someUser\\"}"
}
],
"TypeName": "AWS::IAM::User"
}
Those identifiers can later be passed to cloudcontrol:GetResource
to retrieve the information about the resource. The difference is that cloudcontrol:GetResource
can retrieve the information formatted as the CloudFormation Schema.
$ aws cloudcontrol get-resource --type-name AWS::IAM::User --identifier <identifier>
As an enumeration technique, this means we can list all resources on a specific region for a specific resource type using cloudcontrol:ListResources
and then loop to retrieve the information using cloudcontrol:GetResource
.
Process to retrieve a dump of all user information
Finding resource names through brute force
Attackers often find themselves in situations where specific actions are not allowed to be executed due to limited permissions. This might affect the retrieval of some information, such as the identifiers of resources, like names or IDs. That means the attacker will need to find alternative methods to achieve this information before needing to request other information.
Brute force or guessing are good alternatives to this approach. An attacker with a list of potentially existing resources on the account can path them on cloudcontrol:GetResource
to find out if a resource exists. If the attacker has access to execute cloudcontrol:GetResource
and the resource exists, they will receive the information about the target. If they do not have access to execute the API call, they will receive an AccessDenied
error. And if they have access to execute the API call, but the resource does not exist, they will receive a ResourceNotFoundException
. Knowing this helps clarify if the assumed role has the proper permissions and if the resource exists.
Checking permissions and validating brute forced or guessed dataTampering with resources to gain access to them
Aside from listing resources and retrieving information about them, AWS CloudControl API offers 3 more API calls, which create, update, and delete the resources on the Account:
cloudcontrol:CreateResource
cloudcontrol:UpdateResource
cloudcontrol:DeleteResource
The input required for creating and updating resources is the Type
of the resource, the input parameters taken from the CloudFormation Schemas based on the resource type, and to delete and update the resource, the identifier is also required.
AWS CLI command using CloudControl to create a roleWhen a request for a CUD (create, update, delete) operation is sent to the CloudControl API, the request is logged by it. Using cloudcontrol:ListResourceRequests
, we can list the requests and their status (successful or failure), including the error code, in the case of failure. As an enumeration feature, this can be helpful, as it will allow the attacker the ability to retrieve information regarding access a specific identity will have, Organization Level Policies (SCP), and identifier names for resources created and updated.
AWS CLI command using CloudControl to list resource requestsThe bad: You still need to have permission to execute the call
One of our questions was about how the AWS CloudControl API works and what privileges it requires. If the API only needs CloudControl-specific permissions, it could be a highly dangerous API to leave unchecked.
Looking at the events for a request attempting to retrieve an IAM User, we noticed there are several events being executed. When cloudcontrol:GetResource
is executed, on the backend, CloudControl makes seven more API requests:
iam:GetUser
is executed twice, most likely to retrieve Username
, Path
, and Tags
using one request and PermissionBoundary
using the second.iam:ListUserPolicies
to retrieve the user’s inline policiesiam:GetUserPolicy
to retrieve the policy content, and this might be executed more than once, depending on the number of inline policies assigned to the useriam:ListAttachedUserPolicies
to retrieve AWS and custom managed policies attached to the useriam:GetLoginProfile
will let us know if the user has a LoginProfile
assigned, meaning they have access to the Management Consoleiam:ListGroupsForUser
to retrieve a list of IAM Groups the user is part of.
Note that AWS events are not always ordered correctly. If several API calls are executed within a very short time frame, they might take a different order in the event history.
This means the events that provide the necessary information for the inventory will get executed whether the information exists or not. So that creates an issue when it comes to remaining in stealth. This means that attackers will be detected attempting to execute API Calls on the target. This becomes even more of an issue when we try to create and/or update resources, which can lead to the detection tools and teams realizing a potential compromise.
A broken chain
But wait. There was a problem with the calls being executed. AWS, when executing the API calls behind the CloudControl API, should not have access to the credentials of the IAM User. So, how are they executing the calls? Looking at one of the requests being made, we notice several things:
- The values for
sourceIPAddress
and userAgent
are set to cloudformation.amazonaws.com
, meaning the event is triggered by AWS CloudControl API. - The request, though being initiated by an IAM User (as indicated by the ARN), has an Access Key starting with
ASIA
, indicating a temporary credential in AWS. The session seems to be executed right before the event, as indicated by the sessionContext.attributes.creationDate
compared to eventTime
.
{
"eventVersion": "1.11",
"userIdentity": {
"type": "IAMUser",
"principalId": "AIDA****************",
"arn": "arn:aws:iam::0123456789012:user/bleonUser",
"accountId": "0123456789012",
"accessKeyId": "ASIA4MTWIL**********",
"userName": "bleonUser",
"sessionContext": {
"attributes": {
"creationDate": "2025-08-15T14:52:54Z",
"mfaAuthenticated": "false"
}
},
"invokedBy": "cloudformation.amazonaws.com"
},
"eventTime": "2025-08-15T14:52:55Z",
"eventSource": "iam.amazonaws.com",
"eventName": "ListAttachedUserPolicies",
"awsRegion": "us-east-1",
"sourceIPAddress": "cloudformation.amazonaws.com",
"userAgent": "cloudformation.amazonaws.com",
"requestParameters": {
"userName": "bleonUser"
},
"responseElements": null,
"requestID": "00bcc3e5-ed84-4cbb-a8ad-61b252e387bb",
"eventID": "ced62c58-a981-40b8-9e7c-3666a310e908",
"readOnly": true,
"eventType": "AwsApiCall",
"managementEvent": true,
"recipientAccountId": "851725277864",
"eventCategory": "Management"
}
That means AWS generates a set of temporary credentials for the identity and uses those credentials to execute the rest of the calls from an AWS CloudControl API endpoint.
The process AWS uses to create credentials to make CloudControl API callsThere are no events in CloudTrail that show the generation of the new credentials. In fact, even creating a policy that only allows the events that are related to AWS CloudControl API will not prevent any attempts to receive the information, and still no event that generated the temporary credentials will be shown on CloudTrail.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement3",
"Effect": "Allow",
"Action": [
"iam:GetUser",
"iam:ListUserPolicies",
"iam:GetUserPolicy",
"iam:ListAttachedUserPolicies",
"iam:GetLoginProfile",
"iam:ListGroupsForUser",
"cloudformation:GetResource"
],
"Resource": [
"*"
]
}
]
}
The ugly: One permission breaks the whole chain
The last question we had was what happens if a specific API call failed? And what would happen to the request if the resource does not have a specific configuration that one of the API calls will retrieve?
If the requesting identity has the right privileges to execute each necessary API call, but the resource does not have some of the information, the output will not include those fields. For example, in the case below, we see the difference in output between a user being part of an AWS IAM Group vs not being part of a group.
# User is part of bleonTestGroup IAM Group
{
"Path": "/",
"UserName": "bleonUser",
"Groups": [
"bleonTestGroup"
],
"Arn": "arn:aws:iam::0123456789012:user/bleonUser",
"LoginProfile": {
"PasswordResetRequired": false
},
"Tags": [
{
"Value": "Prod",
"Key": "Deployment"
}
]
}
# User is not part of bleonTestGroup IAM Group
{
"Path": "/",
"UserName": "bleonUser",
"Arn": "arn:aws:iam::0123456789012:user/bleonUser",
"LoginProfile": {
"PasswordResetRequired": false
},
"Tags": [
{
"Value": "Prod",
"Key": "Deployment"
}
]
}
This is different than when the requesting user does not have all the privileges. In AWS IAM Cloud Control, if an API call in the whole transaction of execution fails, the entire request will fail.
AWS CLI CloudControl get resource that fails with limited permissionsThis means that if an attacker requests information about a user and they do not have access to list the groups (iam:ListGroupsForUser
), no other information will be returned to the attacker, and they will get an error code indicating a lack of privileges.
Flow of a failed API call with limited permissionsAnd, the events will still get executed and logged. Meaning, the attacker will not retrieve the information or execute the required task, but will still be logged.
CloudTrail logs showing the failed API callsHow effective can AWS CloudControl API be as an attack tool?
AWS CloudControl API has many limitations as an attacker tool: the need for extra privileges, the logging of events, as well as the chain being broken the moment the impersonated identity lacks the appropriate privileges. But those limitations, if used correctly, can also be used to persist in an account with high privileges. The policy below will only allow the identity it is assigned to to execute an API call related to CloudControl directly, while limiting anything else from only being executed through CloudControl (CloudControl API uses CloudFormation operations, which is why the service is CloudFormation instead of CloudControl).
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowViaCloudFormation",
"Effect": "Allow",
"Action": "*",
"Resource": "*",
"Condition": {
"ForAnyValue:StringEquals": {
"aws:CalledVia": "cloudformation.amazonaws.com"
},
"Bool": {
"aws:ViaAWSService": "true"
}
}
},
{
"Sid": "DenyDirectAccess",
"Effect": "Deny",
"NotAction": [
"cloudformation:GetResource",
"cloudformation:GetResourceRequestStatus",
"cloudformation:ListResourceRequests",
"cloudformation:ListResources",
"cloudformation:UpdateResource",
"cloudformation:DeleteResource",
"cloudformation:CreateResource",
"cloudformation:CancelResourceRequest"
],
"Resource": "*",
"Condition": {
"Bool": {
"aws:ViaAWSService": "false"
}
}
},
{
"Sid": "AllowDirectCloudControlAcccess",
"Effect": "Allow",
"Action": [
"cloudformation:GetResource",
"cloudformation:GetResourceRequestStatus",
"cloudformation:ListResourceRequests",
"cloudformation:ListResources",
"cloudformation:UpdateResource",
"cloudformation:DeleteResource",
"cloudformation:CreateResource",
"cloudformation:CancelResourceRequest"
],
"Resource": "*"
}
]
}
Looking at the IAM policy creator, AWS will list CloudControl API as the only service the policy will allow access to, which makes this policy seem like a limited, non-administrative policy.
AWS IAM shows the policy only allows access to the Cloud Control APIThe Policy simulation also lists any event as prevented, making the persistence even stealthier.
Policy simulator showing blocked eventsAttempting to execute any request outside of the ones CloudControl allows will fail, due to the 2nd Statement in the Policy (DenyDirectAccess
).
AWS CLI command blocked due to strict permissionsBut, attempting to execute an API call (any CRUD-L operation) through the CloudControl API will be allowed.
AWS CLI command successfully completed when using the CloudControl APIThe identity this policy is assigned to will have Administrator Access, while looking like a normal, non-administrative identity.
CloudConqueror
This research culminated with the open source tool called CloudConqueror, a four part tool, which provides a simulation of all the techniques specified in this research.
- Resource Listing by utilizing
cloudcontrol:ListResources
and cloudcontrol:GetResource
- Resource Name Bruteforce by utilizing
cloudcontrol:GetResource
- Persistence by creating an IAM User or Role with an inline policy that only allows access through CloudControl
- Listing of CloudControl events on the account
Preview of the CloudConquerer toolCloudConquerer is built on Python, and installation is straightforward, either locally or leveraging Docker. See the repository to try it for yourself.
Installing the tool
Local Installation
CloudConqueror is built in Python 3, and a file containing the required libraries (requirements.txt) is found inside the main folder of the tool. To install the tool locally, either using a Virtual Environment (python-venv) or installing the libraries on the system directly, the only installation needed is to install the libraries inside requirements.txt.
(venv) ~$ python3 -m pip install -r requirements.txt
Requirement already satisfied: boto3 in ./venv/lib/python3.12/site-packages (from -r requirements.txt (line 1)) (1.40.5)
Requirement already satisfied: termcolor in ./venv/lib/python3.12/site-packages (from -r requirements.txt (line 2)) (3.1.0)
Requirement already satisfied: botocore in ./venv/lib/python3.12/site-packages (from -r requirements.txt (line 3)) (1.40.5)
Requirement already satisfied: tabulate in ./venv/lib/python3.12/site-packages (from -r requirements.txt (line 4)) (0.9.0)
Requirement already satisfied: prettytable in ./venv/lib/python3.12/site-packages (from -r requirements.txt (line 5)) (3.16.0)
Requirement already satisfied: jmespath<2.0.0,>=0.7.1 in ./venv/lib/python3.12/site-packages (from boto3->-r requirements.txt (line 1)) (1.0.1)
Requirement already satisfied: s3transfer<0.14.0,>=0.13.0 in ./venv/lib/python3.12/site-packages (from boto3->-r requirements.txt (line 1)) (0.13.1)
Requirement already satisfied: python-dateutil<3.0.0,>=2.1 in ./venv/lib/python3.12/site-packages (from botocore->-r requirements.txt (line 3)) (2.9.0.post0)
Requirement already satisfied: urllib3!=2.2.0,<3,>=1.25.4 in ./venv/lib/python3.12/site-packages (from botocore->-r requirements.txt (line 3)) (2.5.0)
Requirement already satisfied: wcwidth in ./venv/lib/python3.12/site-packages (from prettytable->-r requirements.txt (line 5)) (0.2.13)
Requirement already satisfied: six>=1.5 in ./venv/lib/python3.12/site-packages (from python-dateutil<3.0.0,>=2.1->botocore->-r requirements.txt (line 3)) (1.17.0)
Then, the tool can be executed using Python:
(venv) ~$ python3 CloudConqueror.py -h
---------------------------------------------------------------------------------
_____ _ _ _____
/ ____| | | |/ ____|
| | | | ___ _ _ __| | | ___ _ __ __ _ _ _ ___ _ __ ___ _ __
| | | |/ _ \\| | | |/ _` | | / _ \\| '_ \\ / _` | | | |/ _ \\ '__/ _ \\| '__|
| |____| | (_) | |_| | (_| | |___| (_) | | | | (_| | |_| | __/ | | (_) | |
\\_____|_|\\___/ \\__,_|\\__,_|\\_____\\___/|_| |_|\\__, |\\__,_|\\___|_| \\___/|_|
| |
|_|
---------------------------------------------------------------------------------
by gl4ssesbo1 @ Exaforce
---------------------------------------------------------------------------------
usage: CloudConqueror.py [-h] {LISTRESOURCES,BRUTEFORCERESOURCES,IAMPERSISTENCE,CHECKUSAGE} ...
CloudConqueror
positional arguments:
{LISTRESOURCES,BRUTEFORCERESOURCES,IAMPERSISTENCE,CHECKUSAGE}
Select the attack to execute on the target
LISTRESOURCES Bruteforce AWS Resources by utilizing cloudcontrol:ListResources and cloudcontrol:GetResource
BRUTEFORCERESOURCES
Bruteforce AWS Resources by utilizing cloudcontrol:GetResource
IAMPERSISTENCE Persist on the Account using an IAM User or Role and a Policy which only allows access through CloudControl API.
CHECKUSAGE Search through AWS CloudTrail Logs using cloudtrail:LookupEvents to find occurrences of bruteforce
options:
-h, --help show this help message and exit
Docker Installation
CloudConqueror contains a Dockerfile; using it, a Docker image can be created, and the tool can be executed from there. To install the Docker image, just run docker build in the directory of the tool.
~$ docker build -t cloudconqueror .
Sending build context to Docker daemon 99.07MB
Step 1/7 : FROM python:3.10
3.10: Pulling from library/python
80b7316254b3: Pull complete
36e4db86de6e: Pull complete
8ea45766c644: Pull complete
3cb1455cf185: Pull complete
013acb959c95: Pull complete
ee334269ae4f: Pull complete
3eca4263ed42: Pull complete
Digest: sha256:4585309097d523698d382a2de388340896e021319b327e2d9c028f3b4c316138
Status: Downloaded newer image for python:3.10
---> d565b0a5e178
Step 2/7 : WORKDIR /cloudconqueror
---> Running in e2e79b4829a4
---> Removed intermediate container e2e79b4829a4
---> 6f7ef917c82b
Step 3/7 : COPY . .
--snip--
Successfully built 559c27b10eae
Successfully tagged cloudconqueror:latest
Then, to execute the tool, simply run the container using docker run. It is recommended to mount the local AWS Profile Directory (~/.aws directory) so the tool can retrieve the stored awscli sessions and the folder output from the tool’s base directory.
~$ docker run -v ~/.aws:/root/.aws -v ./output:/cloudconqueor/output -it cloudconqueror -h
---------------------------------------------------------------------------------
_____ _ _ _____
/ ____| | | |/ ____|
| | | | ___ _ _ __| | | ___ _ __ __ _ _ _ ___ _ __ ___ _ __
| | | |/ _ \\| | | |/ _` | | / _ \\| '_ \\ / _` | | | |/ _ \\ '__/ _ \\| '__|
| |____| | (_) | |_| | (_| | |___| (_) | | | | (_| | |_| | __/ | | (_) | |
\\_____|_|\\___/ \\__,_|\\__,_|\\_____\\___/|_| |_|\\__, |\\__,_|\\___|_| \\___/|_|
| |
|_|
---------------------------------------------------------------------------------
by gl4ssesbo1 @ Exaforce
---------------------------------------------------------------------------------
usage: CloudConqueror.py [-h] {LISTRESOURCES,BRUTEFORCERESOURCES,IAMPERSISTENCE,CHECKUSAGE} ...
CloudConqueror
positional arguments:
{LISTRESOURCES,BRUTEFORCERESOURCES,IAMPERSISTENCE,CHECKUSAGE}
Select the attack to execute on the target
LISTRESOURCES Bruteforce AWS Resources by utilizing cloudcontrol:ListResources and cloudcontrol:GetResource
BRUTEFORCERESOURCES
Bruteforce AWS Resources by utilizing cloudcontrol:GetResource
IAMPERSISTENCE Persist on the Account using an IAM User or Role and a Policy which only allows access through CloudControl API.
CHECKUSAGE Search through AWS CloudTrail Logs using cloudtrail:LookupEvents to find occurrences of bruteforce
options:
-h, --help show this help message and exit
Listing Resources
CloudConqueror uses cloudcontrol:ListResources
to list resources of a specific resource type on the account. After listing the resources and getting their identifier, it will attempt to run cloudcontrol:GetResource
for each of them, to get their properties. The only inputs the tool needs are an AWS stored profile in the awscli
directory and the type of resource to list.
Using CloudConquerer to list resourcesAll resource types are listed as choices on the tool’s --resource-type
flag, which filters out resources not managed by the AWS CloudControl API.
Output of the resource type callBrute forcing Resources
One of the techniques discussed in this article was using the cloudcontrol:GetResource
API call on a list of potential resource names to find if one of them exists. So basically, an authenticated name fuzzing of resources on the account.
The BRUTEFORCE
command requires the attacker to provide an AWS profile, the resource type, an AWS region, and a list of resource names, and go through each of them, running cloudcontrol:GetResource
, which returns resources with their properties.
CloudControl brute force looking for existing resourcesPersisting in an AWS Account
An attacker can create an IAM policy that only allows access through the CloudControl API and then attaches it to an IAM user, group, or role, to persist using them as mentioned in the section “How effective can AWS CloudControl API be as an attack tool”.
CloudConqueror’s IAMPERSISTENCE
command will use that technique to create a user or a role (by default named CCUser or CCRole if not defined by the attacker) and assign an Inline Policy called CCInlinePolicy on them with a Policy Definition same as the one on the section “How effective can AWS CloudControl API be as an attack tool”.
CloudConquerer command to create a policy to persist in an accountFinding occurrences of CloudControl abuse
Lastly, CloudConqueror can help with one step of detection. The tool’s CHECKUSAGE
command uses cloudtrail:LookupEvents
to search for the execution of the CloudControl API on the account and output a table and CSV out of them.
CloudConquerer checking for the execution of CloudControl API callsThe output CSV will be stored in the directory path output/<Account ID>/cloudcontrol-events.csv in the tool’s directory.
Creation of a CSV with CloudControl API callsHow Exaforce helps in identifying CloudControl API abuse
Exaforce delivers comprehensive detections to identify CloudControl API abuse, whether through enumeration, resource impersonation, or anomalous usage. Our approach leverages behavioral baselines and anomaly detection to separate legitimate CloudFormation activity from attacker techniques that use CloudControl. Following this research, we’ve enabled new detections to protect customers against CloudControl misuse.
- Exaforce detects abnormal sequences of CloudControl API calls that indicate resource enumeration attempts.
- Exaforce detects misuse of CloudControl to blend in with CloudFormation workflows, flagging suspicious activity designed to bypass standard monitoring or detection.
- Exaforce surfaces impersonation attempts, where an attacker tries to mimic normal provisioning activity to conceal malicious changes.
Example detection of suspicious CloudControl API enumeration patterns and CloudFormation anomalies caused by CloudControl API abuseThe detection overview provides a summary and conclusion from Exabot’s automated triage of the alert, highlighting critical details such as the identity involved and the specific API calls in question. We connect all related API calls into a session, giving analysts full context into how CloudControl was used in the attack sequence and what resources were impacted.
Threat Finding of failed attempts to abuse the CloudControl APIAdditionally, our Identity investigations automatically surface users and roles created through CloudControl, providing visibility into IAM resources that may have been established for persistence.
AWS IAM role created by the CloudControl APIKeeping CloudControl in check
AWS CloudControl API is a powerful feature that enables AWS users to have a clean, easy way of managing and utilizing the overwhelming amount of API calls AWS API has. But, as it often goes, when something is easy for the user to use, it is also easy for an attacker to abuse.
Utilizing AWS CloudControl API as an attack tool, while having limitations, can be a very good way of breaking detection chains, which can lead to an attacker potentially blending in while doing mischievous tasks on the account. As such, it is a feature worth keeping an eye on and making sure no unwanted entity is using it maliciously.
Exaforce provides detections for CloudControl API abuse, ensuring that any malicious use of the AWS CloudControl API is promptly identified and responded to quickly.