Open MartinEvandt opened 2 years ago
Here is an example from MDE on how to quarantine a file via their API: https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/stop-and-quarantine-file?view=o365-worldwide
"Contain file on this endpoint via this Actuator"
Request:
https://api.securitycenter.microsoft.com/api/machines/{machine_id}/StopAndQuarantineFile
Body:
{
"Sha1": {file.sha1}
}
Where
Here is an example of how to quarantine an endpoint on a specific CBC tenant via their API: https://developer.carbonblack.com/reference/carbon-black-cloud/platform/latest/devices-api/#quarantine
"Contain device on this tenant via this Actuator"
Request:
{cbc-hostname}/appservices/v6/orgs/{org_key}/device_actions
Body:
{
"action_type": "QUARANTINE",
"device_id": ["12131"],
}
Where
To even further complicate things, MDE handles the issue of tenants within the Authentication token itself, meaning you have to include your tenant ID when generating a token: https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/api-hello-world?view=o365-worldwide
How would this work with the way that OpenC2 does authentication? (I think I might have to open a separate issue regarding this, as it feels like quite an edge-case).
Ignoring the issue with MDE specifying tenants in the auth token, we can address the lack of tenant specifiers (such as it is in the CBC example) by adding a tenant_id optional field in the Actuator Specifiers map:
Type: Specifiers (Map)
ID | Name | Type | # | Description |
---|---|---|---|---|
1 | hostname | Hostname | 1 | The hostname of a machine with ER Actuator capabilities. MUST be formatted as an internet host name as specified in [RFC1123] |
2 | tenant_id | string | 0..1 | Unique identifier for an Actuator which resides on a tenant or similar form of logical segment within a host. E.g., a cloud-based EDR solution where multiple tenants share the same hostname. |
When wanting to specify a particular endpoint it becomes trickier, as the endpoint is not an actuator. It is however the target of an Action/Target pair consumed by the Actuator. One solution would then be to add it to the specifier list anyways, and then add some sort of usage requirement to the section explaining the purpose of it being in the specifiers map.
ID | Name | Type | # | Description |
---|---|---|---|---|
1 | hostname | Hostname | 1 | The hostname of a machine with ER Actuator capabilities. MUST be formatted as an internet host name as specified in [RFC1123] |
2 | tenant_id | string | 0..1 | Unique identifier for an Actuator which resides on a tenant or similar form of logical segment within a host. E.g., a cloud-based EDR solution where multiple tenants share the same hostname. |
3 | endpoint_id | string | 0..1 | Unique identifier for a particular device on which the Actuator is to execute a Command. |
Sample command
{
"action": "contain",
"target":{
"file": {
"hashes":"..."
}
},
"actuator": {
"edr": {
"hostname":"edr.organization.tld",
"endpoint_id":"Host123ABC"
}
}
}
Another solution to the endpoint issue would be to add a "target_endpoint" Command Argument.
*_Type: Actuator-target (Map{1..})_**
ID | Name | Type | # | Description |
---|---|---|---|---|
1 | endpoint_id | string | 0..1 | Unique identifier for a particular device on which the Actuator is to execute a Command |
An added benefit here would be that we can denote which Commands this argument can be paired with in the Command Arguments matrix.
Table 2.3-2. Command Arguments Matrix
response_requested | [...] | Actuator-target | |
---|---|---|---|
contain device | valid | [...] | |
contain file | valid | [...] | valid |
restart process | valid | [...] | valid |
[...]
Sample command
{
"action": "contain",
"target":{
"file": {
"hashes":"..."
}
},
"args": {
"edr": {
"actuator_target":{
"endpoint_id":"Host123ABC"
}
}
},
"actuator": {
"edr": {
"hostname":"edr.organization.tld",
}
}
}
Overall, I think you've done a nice job of laying out the problem here. I wish I'd looked at these sooner, but we're now hitting a very similar issue with Posture Attribute Collection so my interest level has definitely increased. :-) And I think as the population of APs grows it seems likely we'll see more cases like this. The PF AP handles at least some aspects of this via the Actuator Specifiers. I'm still learning about the use cases PAC cares about and whether the PF AP approach is sufficient.
Regarding the CBC example:
- Leaving orgs/{org_key} as the part we are missing
For this example I'm still a bit uncertain what information is conveyed by orgs/{org_key}
. Meanwhile, I'm still studying the other examples and concerns.
Looking at the CBC Quarantine example, their API says:
Permission (.notation name) | Operation(s) | Action Type |
---|---|---|
device.quarantine | EXECUTE | QUARANTINE |
device.bypass | EXECUTE | BYPASS |
device.bg-scan | EXECUTE | BACKGROUND_SCAN |
device.policy | UPDATE | UPDATE_POLICY |
org.kits | EXECUTE | UPDATE_SENSOR_VERSION |
device.uninstall | EXECUTE | UNINSTALL_SENSOR |
device.deregistered | DELETE | DELETE_SENSOR |
Request; POST {cbc-hostname}/appservices/v6/orgs/{org_key}/device_actions
Example: POST https://defense-prod05.conferdeploy.net/appservices/v6/orgs/ABCD1234/device_actions
That's a REST endpoint, where hostname is the destination consumer and appservices/.../device_actions is the API route. OpenC2 over HTTP is a single-endpoint API, so the command body has to contain the information from the API route in addition to the JSON body. CBC conveniently has a body schema - I'll give this some more thought and come up with a CBC-only AP that does exactly what their API does. The first weirdness is that their actions include verb and noun {UPDATEPOLICY, or QUARANTINE\<implicit DEVICE>).
Certain Commands require a further level of granularity in order to specify which exact endpoint the Command is to be performed. For example running a "Stop process" action entails that the Target field is already populated with the process in question, and so the endpoint (which would usally be a "device" Target) is not specified.
In other words we need a way to say e.g. "Contain file on this endpoint via this Actuator".
A similar concern is that of tenants/segments on cloud-based EDR solutions such as Carbon Black Cloud (CBC) and Microsoft Defender for Endpoint (MDE). Where an organizations' tenant is denoted using some sort of unique identifier.
Meaning we also need a way to say e.g. "Stop process on this endpoint on this tenant via this Actuator".
Currently, the most pressing part of this is to find a consistent way to tell the Actuator to execute Commands/Action-Target pairs where the Target is something other than "device" to a specific endpoint.
I'll post some examples from the MDE/CBC API as well as some suggestions in this thread.