Microsoft Defender Advanced Threat Protection
Microsoft Defender for Endpoint (previously Microsoft Defender Advanced Threat Protection (ATP)) is a unified platform for preventative protection, post-breach detection, automated investigation, and response.
Endpoint · Microsoft Defender for Endpoint
Details
| ID | Microsoft Defender Advanced Threat Protection |
|---|---|
| Provider | Microsoft |
| Category | Endpoint |
| From Version | 5.0.0 |
| Docker Image | demisto/crypto:1.0.0.11658507 |
| Supported Modules | Agentix XSIAM EDR Cortex Cloud Cloud Runtime Security |
README
Overview
Use the Microsoft Defender for Endpoint (previously Microsoft Defender Advanced Threat Protection (ATP)) integration for preventative protection, post-breach detection, automated investigation, and response.
Deprecation Announcement
Note: Following this announcement by Microsoft about migrating from the deprecated SIEM API to the Graph API, we are deprecating the following:
- 14 commands
- Fetch-incidents functionality
Replacement Options
- Some commands have direct replacements in the Microsoft Graph Security integration.
- Others do not have exact replacements but offer alternatives that return similar data.
- A few commands have no available replacements.
See Deprecation Details to find details on the deprecated commands and their replacements or alternatives.
Microsoft Defender Advanced Threat Protection Playbook
Microsoft Defender Advanced Threat Protection Get Machine Action Status
Use Cases
- Fetching incidents.
- Managing machines and performing actions on them.
- Blocking files and applications.
- Uploading and digesting threat indicators for the actions of allow, block, or alert.
Authentication
Microsoft integrations (Graph and Azure) in Cortex use Entra ID applications to authenticate with Microsoft APIs. These integrations use OAuth 2.0 and OpenID Connect standard-compliant authentication services, which use an Application to sign-in or delegate authentication. For more information, see the Microsoft identity platform overview.
Two application authentication methods are available:
For more details about the authentication used in this integration, see Microsoft Integrations - Authentication.
Note: When using the Authorization Code flow (either via the Cortex XSOAR application or by choosing delegated permissions for a self-deployed app), ensure the authenticated user has the required role permissions. This can be done via the Microsoft Defender Portal:
- If you are using the new unified RBAC permissions model, navigate to Defender Portal > Permissions and select Roles under Microsoft Defender XDR.
- If you are using the legacy permissions model, navigate to Defender Portal > Settings > Endpoints > Roles.
For a detailed comparison between the new and legacy permission models, refer to the permission mapping table.
Cortex XSOAR Application
To configure Cortex XSOAR application access to Microsoft Defender for Endpoint:
- Navigate to the Cortex Authorization page for Microsoft Defender for Endpoint.
- Select the user account with sufficient role permissions.
- After authorizing the application, copy the ID, Token, and Key values and insert them in integration instance settings corresponding fields.
- Ensure Authentication Type field is set to the Authorization Code option.
- Save the instance.
- Run the
!microsoft-atp-testcommand in the War Room to verify correct configuration.
Self-deployed Azure Application
- Navigate to the Azure portal and search for Microsoft Entra ID.
- On the App registrations page, click New registration.
- Click API Permissions > Add permission > APIs my organization uses, and type WindowsDefenderATP.
- Choose the type of permissions:
- Delegated Permissions - used by applications that act on behalf of a signed-in user. The application will have access to the resources that the user has access to, limited by the permissions granted to the application. Choose this option if you prefer the Authorization Code flow.
- Application Permissions - used by applications that run without a signed-in user. The application acts as its own identity and is granted direct access to data or resources. This is common for background services or daemons. Choose this option if you prefer the the Client Credentials flow.
- Select the permissions required by the integration (based on the chosen permission type), click Add permissions and Grant consent.
- To add a secret to the application, select Certificates & secrets, add a meaningful description, and click Add.
- In the integration instance settings, select the Use a self-deployed Azure Application checkbox and copy the application details based on the chosen permissions type:
- For Delegated Permissions:
- In the ID field, enter the application (client) ID.
- In the Token field, enter the directory (tenant) ID.
- In the Key field, enter the client secret.
- In the Authentication Type field, select the Authorization Code option.
- In the Application Redirect URI field, enter the Application redirect URI.
- Save the instance.
- Run the
!microsoft-atp-generate-login-urlcommand in the War Room and follow the instructions.
- For Application Permissions:
- In the ID field, enter the application (client) ID.
- In the Token field, enter the directory (tenant) ID.
- In the Key field, enter the client secret.
- In the Authentication Type field, select the Client Credentials option.
- Click Test to verify correct configuration.
- Save the instance.
- For Delegated Permissions:
Note: If you previously configured the Windows Defender ATP integration, you need to perform the authentication flow again for this integration and enter the authentication parameters you receive when configuring the integration instance.
Required Permissions
Add the following WindowsDefenderATP API permissions during app registration.
Choose Application Permissions for the Client Credentials flow, or Delegated Permissions for the Authorization Code flow.
- AdvancedQuery.Read.All - Application / AdvancedQuery.Read - Delegated
- Alert.ReadWrite.All - Application / Alert.ReadWrite - Delegated
- File.Read.All - Application / Delegated
- Ip.Read.All - Application / Delegated
- Machine.CollectForensics - Application / Delegated
- Machine.Isolate - Application / Delegated
- Machine.ReadWrite.All - Application / Machine.ReadWrite - Delegated
- Machine.RestrictExecution - Application / Delegated
- Machine.Scan - Application / Delegated
- Machine.StopAndQuarantine - Application / Delegated
- ThreatIndicators.ReadWrite.OwnedBy - Application / Delegated.
Note: This permission is only used for the deprecated!microsoft-atp-indicator-listcommand. If you are not using this command, it is not required. - Url.Read.All - Application / Delegated
- User.Read.All - Application / Delegated
- Ti.ReadWrite (Read and write IOCs belonging to the app) - Application / Delegated
- Vulnerability.Read.All - Application / Vulnerability.Read - Delegated
- Software.Read.All - Application / Software.Read - Delegated
- Machine.LiveResponse - Application / Delegated
- Machine.Read.All - Application / Machine.Read - Delegated
Note: Access permissions can be verified by running the !microsoft-atp-list-auth-permissions command after configuring the integration instance.
Configure Microsoft Defender for Endpoint in Cortex
| Parameter | Description | Example |
|---|---|---|
| Name | A meaningful name for the integration instance. | XXXXX Instance Alpha |
| Endpoint Type | The endpoint for accessing Microsoft Defender for Endpoint, see table below. | Worldwide |
| Fetches Incidents | Whether to fetch the incidents. | False |
| Incident Type | The type of incident to select. | Phishing |
| ID | The ID used to gain access to the integration. Your Client/Application ID. | |
| Token | A piece of data that servers use to verify for authenticity. This is your Tenant ID. | eea810f5-a6f6 |
| Key | Your client secret. | |
| Certificate Thumbprint | Used for certificate authentication. As appears in the “Certificates & secrets” page of the app. | A97BF50B7BB6D909CE8CAAF9FA8109A571134C33 |
| Private Key | Used for certificate authentication. The private key of the registered certificate. | eea810f5-a6f6 |
| Authentication Type | Type of authentication - either Authorization Code (recommended) or Client Credentials. | |
| Application redirect URI (for authorization code mode) | False | |
| Authorization code | for user-auth mode - received from the authorization step. see Detailed Instructions section | False |
| Azure Managed Identities Client ID | The Managed Identities client ID for authentication - relevant only if the integration is running on Azure VM. | UUID |
| Status for fetching alerts as incidents | The property values are, “New”, “InProgress” or “Resolved”. Comma-separated lists are supported, e.g., New,Resolved. | New,In Progress,Resolved |
| DetecitonSource to filter out alters for fetching as incidents. | The property values are, “Antivirus”, “CustomDetection”, “CustomTI”, “EDR” and “MDO”. Comma-separated lists are supported, e.g., Antivirus,EDR. | CustomDetection,EDR |
| Severity for fetching alerts as incidents | The property values are, “Informational”, “Low”, “Medium” and “High”. Comma-separated lists are supported, e.g., Medium,High. | Medium,High |
| Maximum number of incidents to fetch | The maximum number of incidents to retrieve per fetch. | 50 |
| Trust any Certificate (Not Secure) | When selected, certificates are not checked. | |
| Fetch alert evidence | When selected, fetches alerts in Microsoft Defender. | |
| Use system proxy settings | Runs the integration instance using the proxy server (HTTP or HTTPS) that you defined in the server configuration. | https://proxyserver.com |
| Use a self-deployed Azure Application | For authorization code flow, mark this as true. | |
| First Fetch Timestamp | The first timestamp to be fetched in the format <number> <time unit>. | 12 hours, 7 days |
| Server URL | The URL to the Microsoft Defender for Endpoint server, including the scheme, see note below. | https://api.securitycenter.windows.com |
Endpoint Type options
| Endpoint Type | Description |
|---|---|
| Worldwide | The publicly accessible Microsoft Defender for Endpoint |
| EU Geo Proximity | Microsoft Defender for Endpoint Geo proximity end point for the UK customers. |
| UK Geo Proximity | Microsoft Defender for Endpoint Geo proximity end point for the UK customers. |
| US Geo Proximity | Microsoft Defender for Endpoint Geo proximity end point for the US customers. |
| US GCC | Microsoft Defender for Endpoint for the USA Government Cloud Community (GCC) |
| US GCC-High | Microsoft Defender for Endpoint for the USA Government Cloud Community High (GCC-High) |
| DoD | Microsoft Defender for Endpoint for the USA Department of Defence (DoD) |
| Custom | Custom endpoint configuration to the Microsoft Defender for Endpoint, please see note below. |
Note: In most cases, setting the Endpoint type is preferred over setting the Server URL. Only set the Server URL when a custom URL is required for accessing a national cloud, or for self-deployment.
Fetched Incidents Data
- id
- incidentId
- investigationId
- assignedTo
- severity
- status
- classification
- determination
- investigationState
- detectionSource
- category
- threatFamilyName
- title
- description
- alertCreationTime
- firstEventTime
- lastEventTime
- lastUpdateTime
- resolvedTime
- machineId
- computerDnsName
- aadTenantId
- relatedUser
- comments
- evidence
Commands
You can execute these commands from the Cortex XSOAR CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
- microsoft-atp-isolate-machine
- microsoft-atp-unisolate-machine
- microsoft-atp-get-machines
- microsoft-atp-get-file-related-machines
- microsoft-atp-get-machine-details
- microsoft-atp-run-antivirus-scan
- microsoft-atp-list-alerts (Deprecated)
- microsoft-atp-update-alert (Deprecated)
- microsoft-atp-advanced-hunting (Deprecated)
- microsoft-atp-create-alert (Deprecated)
- microsoft-atp-get-alert-related-user (Deprecated)
- microsoft-atp-get-alert-related-files (Deprecated)
- microsoft-atp-get-alert-related-ips (Deprecated)
- microsoft-atp-get-alert-related-domains (Deprecated)
- microsoft-atp-list-machine-actions-details
- microsoft-atp-collect-investigation-package
- microsoft-atp-get-investigation-package-sas-uri
- microsoft-atp-restrict-app-execution
- microsoft-atp-remove-app-restriction
- microsoft-atp-stop-and-quarantine-file
- microsoft-atp-list-investigations
- microsoft-atp-start-investigation
- microsoft-atp-get-domain-statistics
- microsoft-atp-get-domain-alerts (Deprecated)
- microsoft-atp-get-domain-machines
- microsoft-atp-get-file-statistics
- microsoft-atp-get-file-alerts (Deprecated)
- microsoft-atp-get-ip-statistics
- microsoft-atp-get-ip-alerts (Deprecated)
- microsoft-atp-get-user-alerts (Deprecated)
- microsoft-atp-get-user-machines
- microsoft-atp-add-remove-machine-tag
- microsoft-atp-indicator-list (Deprecated)
- microsoft-atp-indicator-get-by-id (Deprecated)
- microsoft-atp-indicator-create-network (Deprecated)
- microsoft-atp-indicator-create-file (Deprecated)
- microsoft-atp-indicator-update (Deprecated)
- microsoft-atp-indicator-delete (Deprecated)
- microsoft-atp-sc-indicator-list
- microsoft-atp-sc-indicator-get-by-id
- microsoft-atp-sc-indicator-create
- microsoft-atp-sc-indicator-update
- microsoft-atp-sc-indicator-delete
- microsoft-atp-list-machines-by-vulnerability
- microsoft-atp-get-file-info
- endpoint
- microsoft-atp-indicator-batch-update
- microsoft-atp-get-alert-by-id (Deprecated)
- microsoft-atp-request-and-download-investigation-package
- microsoft-atp-offboard-machine
- microsoft-atp-list-software
- microsoft-atp-list-software-version-distribution
- microsoft-atp-list-machines-by-software
- microsoft-atp-list-vulnerabilities-by-software
- microsoft-atp-list-vulnerabilities-by-machine
- microsoft-atp-list-vulnerabilities
- microsoft-atp-list-missing-kb-by-software
- microsoft-atp-get-machine-vulnerabilities
- microsoft-atp-get-machine-software
- microsoft-atp-get-machine-missing-kbs
1. microsoft-atp-isolate-machine
Isolates a machine from accessing external network.
Required Permissions
Machine.Isolate
Note: When using the Authorization Code flow (either via the Cortex XSOAR application or by choosing delegated permissions for a self-deployed app), ensure the authenticated user has the “Active Remediation Actions” role assigned. Refer to the Microsoft documentation on creating and managing roles.
Base Command
microsoft-atp-isolate-machine
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | A comma-separated list of machine IDs to be used for isolation. e.g., 0a3250e0693a109f1affc9217be9459028aa8426,0a3250e0693a109f1affc9217be9459028aa8424. | Required |
| comment | A comment to associate with the action. | Required |
| isolation_type | Full isolation or selective isolation. (Restrict only limited set of applications from accessing the network). Possible values are: Full, Selective. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.MachineAction.ID | String | The machine action ID. |
| MicrosoftATP.MachineAction.Type | String | Type of the machine action. |
| MicrosoftATP.MachineAction.Scope | Unknown | Scope of the action. |
| MicrosoftATP.MachineAction.Requestor | String | The ID of the user that executed the action. |
| MicrosoftATP.MachineAction.RequestorComment | String | Comment that was written when issuing the action. |
| MicrosoftATP.MachineAction.Status | String | The current status of the command. |
| MicrosoftATP.MachineAction.MachineID | String | The machine ID on which the action was executed. |
| MicrosoftATP.MachineAction.ComputerDNSName | String | The machine DNS name on which the action was executed. |
| MicrosoftATP.MachineAction.CreationDateTimeUtc | Date | The date and time when the action was created. |
| MicrosoftATP.MachineAction.LastUpdateTimeUtc | Date | The last date and time when the action status was updated. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifier | String | The file identifier. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifierType | String | The type of the file identifier. Possible values: “SHA1” ,”SHA256”, and “MD5”. |
Command example
!microsoft-atp-isolate-machine comment=isolate_test_3 isolation_type=Full machine_id="12342c13fef,12342c13fef8f06606"
Context Example
{
"MicrosoftATP": {
"MachineAction": [
{
"ComputerDNSName": "desktop-s2455r8",
"CreationDateTimeUtc": "2022-01-25T14:25:52.6227941Z",
"ID": "1f3098e20464",
"LastUpdateTimeUtc": null,
"MachineID": "12342c13fef",
"RelatedFileInfo": {
"FileIdentifier": null,
"FileIdentifierType": null
},
"Requestor": "2f48b784-5da5-4e61-9957-012d2630f1e4",
"RequestorComment": "isolate_test_3",
"Scope": "Full",
"Status": "Pending",
"Type": "Isolate"
},
{
"ComputerDNSName": "desktop-s2455r9",
"CreationDateTimeUtc": "2022-01-25T14:25:53.2395007Z",
"ID": "6d39a3da0744",
"LastUpdateTimeUtc": null,
"MachineID": "12342c13fef8f06606",
"RelatedFileInfo": {
"FileIdentifier": null,
"FileIdentifierType": null
},
"Requestor": "2f48b784-5da5-4e61-9957-012d2630f1e4",
"RequestorComment": "isolate_test_3",
"Scope": "Full",
"Status": "Pending",
"Type": "Isolate"
}
]
}
}
Human Readable Output
The isolation request has been submitted successfully
ID Type Requestor RequestorComment Status MachineID ComputerDNSName 1f3098e20464 Isolate 2f48b784-5da5-4e61-9957-012d2630f1e4 isolate_test_3 Pending 12342c13fef desktop-s2455r8 6d39a3da0744 Isolate 2f48b784-5da5-4e61-9957-012d2630f1e4 isolate_test_3 Pending 12342c13fef8f06606 desktop-s2455r9
2. microsoft-atp-unisolate-machine
Remove a machine from isolation.
Required Permissions
Machine.Isolate
Base Command
microsoft-atp-unisolate-machine
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | A comma-separated list of machine IDs to be used to stop the isolation. e.g., 0a3250e0693a109f1affc9217be9459028aa8426,0a3250e0693a109f1affc9217be9459028aa8424. | Required |
| comment | Comment to associate with the action. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.MachineAction.ID | String | The machine action ID. |
| MicrosoftATP.MachineAction.Type | String | Type of the action. |
| MicrosoftATP.MachineAction.Scope | Unknown | Scope of the action. |
| MicrosoftATP.MachineAction.Requestor | String | The ID of the user that executed the action. |
| MicrosoftATP.MachineAction.RequestorComment | String | The comment that was written when issuing the action. |
| MicrosoftATP.MachineAction.Status | String | The current status of the command. |
| MicrosoftATP.MachineAction.MachineID | String | The machine ID on which the action was executed. |
| MicrosoftATP.MachineAction.ComputerDNSName | String | The machine DNS name on which the action was executed |
| MicrosoftATP.MachineAction.CreationDateTimeUtc | Date | The date and time when the action was created. |
| MicrosoftATP.MachineAction.LastUpdateTimeUtc | Date | The last date and time when the action status was updated. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifier | String | The fileIdentifier. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifierType | String | The type of the file identifier. Possible values: “SHA1” ,”SHA256”, and “MD5”. |
Command example
!microsoft-atp-unisolate-machine comment=unisolate_test machine_id="4899036531e3,f70f9fe6b29"
Context Example
{
"MicrosoftATP": {
"MachineAction": [
{
"ComputerDNSName": "desktop-s2455r8",
"CreationDateTimeUtc": "2022-01-25T14:23:01.3053556Z",
"ID": "488176cc",
"LastUpdateTimeUtc": null,
"MachineID": "4899036531e3",
"RelatedFileInfo": {
"FileIdentifier": null,
"FileIdentifierType": null
},
"Requestor": "2f48b784-5da5-4e61-9957-012d2630f1e4",
"RequestorComment": "unisolate_test",
"Scope": null,
"Status": "Pending",
"Type": "Unisolate"
},
{
"ComputerDNSName": "desktop-s2455r9",
"CreationDateTimeUtc": "2022-01-25T14:23:01.8421701Z",
"ID": "a6422c40",
"LastUpdateTimeUtc": null,
"MachineID": "f70f9fe6b29",
"RelatedFileInfo": {
"FileIdentifier": null,
"FileIdentifierType": null
},
"Requestor": "2f48b784-5da5-4e61-9957-012d2630f1e4",
"RequestorComment": "unisolate_test",
"Scope": null,
"Status": "Pending",
"Type": "Unisolate"
}
]
}
}
Human Readable Output
The request to stop the isolation has been submitted successfully
ID Type Requestor RequestorComment Status MachineID ComputerDNSName 488176cc Unisolate 2f48b784-5da5-4e61-9957-012d2630f1e4 unisolate_test Pending 4899036531e3 devicename_2 a6422c40 Unisolate 2f48b784-5da5-4e61-9957-012d2630f1e4 unisolate_test Pending f70f9fe6b29 devicename_1
3. microsoft-atp-get-machines
Retrieves a collection of machines that have communicated with WDATP cloud in the last 30 days. Note, only ip or hostname can be a comma-separated list. If both are given as lists, an error will appear.
Base Command
microsoft-atp-get-machines
Input
| Argument Name | Description | Required |
|---|---|---|
| hostname | A comma-separated list of computer DNS name. | Optional |
| ip | A comma-separated list of the last machine IPs to access the internet. | Optional |
| risk_score | The machine risk score. Possible values are: Low, Medium, High. | Optional |
| health_status | The machine health status. Possible values are: Active, Inactive. | Optional |
| os_platform | The machine’s OS platform. Only a single platform can be added. | Optional |
| page_size | Number of machines to return in a page - must be lower or equal to 10,000. | Optional |
| page_num | The page number to retrieve. Default is 1. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Machine.ID | String | The machine ID. |
| MicrosoftATP.Machine.ComputerDNSName | String | The machine DNS name. |
| MicrosoftATP.Machine.FirstSeen | Date | The first date and time the machine was observed by Microsoft Defender ATP. |
| MicrosoftATP.Machine.LastSeen | Date | The last date and time the machine was observed by Microsoft Defender ATP. |
| MicrosoftATP.Machine.OSPlatform | String | The operating system platform. |
| MicrosoftATP.Machine.OSVersion | String | The operating system version. |
| MicrosoftATP.Machine.OSProcessor | String | The operating system processor. |
| MicrosoftATP.Machine.LastIPAddress | String | The last IP on the machine. |
| MicrosoftATP.Machine.LastExternalIPAddress | String | The last machine IP to access the internet. |
| MicrosoftATP.Machine.OSBuild | Number | The operating system build number. |
| MicrosoftATP.Machine.HealthStatus | String | The machine health status. |
| MicrosoftATP.Machine.RBACGroupID | Number | The machine RBAC group ID. |
| MicrosoftATP.Machine.RBACGroupName | String | The machine RBAC group name. |
| MicrosoftATP.Machine.RiskScore | String | The machine risk score. |
| MicrosoftATP.Machine.ExposureLevel | String | The machine exposure score. |
| MicrosoftATP.Machine.IsAADJoined | Boolean | True if machine is AAD joined, False otherwise. |
| MicrosoftATP.Machine.AADDeviceID | String | The AAD Device ID. |
| MicrosoftATP.Machine.MachineTags | String | Set of machine tags. |
Command example
!microsoft-atp-get-machines hostname=desktop-s health_status=Active os_platform=Windows10 ip=1.2.3.4,1.2.3.5
Context Example
{
"MicrosoftATP": {
"Machine": {
"AgentVersion": "10.8040.19041.1466",
"ComputerDNSName": "desktop-s",
"ExposureLevel": "Medium",
"FirstSeen": "2020-02-20T14:44:11.4627779Z",
"HealthStatus": "Active",
"ID": "f70f9fe6b29",
"IPAddresses": [
{
"ipAddress": "1.2.3.4",
"macAddress": "1213123",
"operationalStatus": "Up",
"type": "Ethernet"
},
{
"ipAddress": "1234::1234:1234:1234:1234",
"macAddress": "1213123",
"operationalStatus": "Up",
"type": "Ethernet"
},
{
"ipAddress": "127.0.0.1",
"macAddress": "",
"operationalStatus": "Up",
"type": "SoftwareLoopback"
},
{
"ipAddress": "::1",
"macAddress": "",
"operationalStatus": "Up",
"type": "SoftwareLoopback"
}
],
"IsAADJoined": true,
"LastExternalIPAddress": "127.0.0.1",
"LastIPAddress": "1.2.3.4",
"LastSeen": "2022-01-26T11:14:22.9649216Z",
"MachineTags": [
"new test",
"test add tag",
"testing123"
],
"OSBuild": 19042,
"OSPlatform": "Windows10",
"OSProcessor": "x64",
"OSVersion": "20H2",
"RBACGroupID": 0,
"RiskScore": "Medium"
}
}
}
Human Readable Output
Microsoft Defender ATP Machines
ID ComputerDNSName OSPlatform LastIPAddress LastExternalIPAddress HealthStatus RiskScore ExposureLevel f70f9fe6b29 desktop-s Windows10 1.2.3.4 127.0.0.1 Active Medium Medium
4. microsoft-atp-get-file-related-machines
Gets a collection of machines related to a given file’s SHA1 hash.
Required Permissions
Machine.ReadWrite.All
Base Command
microsoft-atp-get-file-related-machines
Input
| Argument Name | Description | Required |
|---|---|---|
| file_hash | A comma-separated list of file SHA1 hash to get the related machines. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.FileMachine.Machines.ID | String | The machine ID. |
| MicrosoftATP.FileMachine.Machines.ComputerDNSName | String | The machine DNS name. |
| MicrosoftATP.FileMachine.Machines.FirstSeen | Date | The first date and time where the machine was observed by Microsoft Defender ATP. |
| MicrosoftATP.FileMachine.Machines.LastSeen | Date | The last date and time where the machine was observed by Microsoft Defender ATP. |
| MicrosoftATP.FileMachine.Machines.OSPlatform | String | The operating system platform. |
| MicrosoftATP.FileMachine.Machines.OSVersion | String | The operating system version. |
| MicrosoftATP.Machine.OSProcessor | String | The operating system processor. |
| MicrosoftATP.FileMachine.Machines.OSBuild | Number | Operating system build number. |
| MicrosoftATP.FileMachine.Machines.LastIPAddress | String | The last IP on the machine. |
| MicrosoftATP.FileMachine.Machines.LastExternalIPAddress | String | The last machine IP to access the internet. |
| MicrosoftATP.FileMachine.Machines.HelathStatus | String | The machine health status. |
| MicrosoftATP.FileMachine.Machines.RBACGroupID | Number | The machine RBAC group ID. |
| MicrosoftATP.FileMachine.Machines.RBACGroupName | String | The machine RBAC group name. |
| MicrosoftATP.FileMachine.Machines.RiskScore | String | The machine risk score. |
| MicrosoftATP.FileMachine.Machines.ExposureLevel | String | The machine exposure score. |
| MicrosoftATP.FileMachine.Machines.IsAADJoined | Boolean | True if machine is AAD joined, False otherwise. |
| MicrosoftATP.FileMachine.Machines.AADDeviceID | string | The AAD Device ID. |
| MicrosoftATP.FileMachine.Machines.MachineTags | String | Set of machine tags. |
| MicrosoftATP.FileMachine.File | String | The machine related file hash. |
Command example
!microsoft-atp-get-file-related-machines file_hash=1234567891acvgfdertukthgfdertyjhgfdset54,1234567891acvgfdertukthgfdertyjhgfdset53
Context Example
{
"MicrosoftATP": {
"FileMachine": [
{
"File": "1234567891acvgfdertukthgfdertyjhgfdset54",
"Machines": [
{
"AgentVersion": "10.8040.19041.1466",
"ComputerDNSName": "desktop-s9",
"ExposureLevel": "Medium",
"FirstSeen": "2020-02-20T14:44:11.4627779Z",
"HealthStatus": "Active",
"ID": "f70f9fe6",
"IPAddresses": [
{
"ipAddress": "1.2.3.4",
"macAddress": "123456789121",
"operationalStatus": "Up",
"type": "Ethernet"
},
{
"ipAddress": "1234::1234:1234:3177:11dc",
"macAddress": "123456789121",
"operationalStatus": "Up",
"type": "Ethernet"
},
{
"ipAddress": "127.0.0.1",
"macAddress": "",
"operationalStatus": "Up",
"type": "SoftwareLoopback"
},
{
"ipAddress": "::1",
"macAddress": "",
"operationalStatus": "Up",
"type": "SoftwareLoopback"
}
],
"IsAADJoined": true,
"LastExternalIPAddress": "127.0.0.1",
"LastIPAddress": "1.2.3.4",
"LastSeen": "2022-01-25T11:14:39.7435843Z",
"MachineTags": [
"new test",
"test add tag",
"testing123"
],
"OSBuild": 19042,
"OSPlatform": "Windows10",
"OSProcessor": "x64",
"OSVersion": "20H2",
"RBACGroupID": 0,
"RiskScore": "Medium"
}
]
},
{
"File": "1234567891acvgfdertukthgfdertyjhgfdset53",
"Machines": [
{
"AADDeviceID": "cfcf4177-227e-4cdb-ac8e-f9a3da1ca30c",
"AgentVersion": "10.8040.19041.1466",
"ComputerDNSName": "desktop-s8",
"ExposureLevel": "Medium",
"FirstSeen": "2020-02-17T08:30:07.2415577Z",
"HealthStatus": "Active",
"ID": "48990365",
"IPAddresses": [
{
"ipAddress": "1.2.3.5",
"macAddress": "005056941386",
"operationalStatus": "Up",
"type": "Ethernet"
},
{
"ipAddress": "123::1234:dd40:bc6e:23e1",
"macAddress": "123456789123",
"operationalStatus": "Up",
"type": "Ethernet"
},
{
"ipAddress": "127.0.0.1",
"macAddress": "",
"operationalStatus": "Up",
"type": "SoftwareLoopback"
},
{
"ipAddress": "::1",
"macAddress": "",
"operationalStatus": "Up",
"type": "SoftwareLoopback"
}
],
"IsAADJoined": true,
"LastExternalIPAddress": "127.0.0.1",
"LastIPAddress": "1.2.3.5",
"LastSeen": "2022-01-25T11:19:44.718919Z",
"MachineTags": [
"test Tag 2",
"test Tag 5"
],
"OSBuild": 19043,
"OSPlatform": "Windows10",
"OSProcessor": "x64",
"OSVersion": "21H1",
"RBACGroupID": 0,
"RiskScore": "Low"
}
]
}
]
}
}
Human Readable Output
Microsoft Defender ATP machines related to files [‘1234567891acvgfdertukthgfdertyjhgfdset54’, ‘1234567891acvgfdertukthgfdertyjhgfdset53’]
ID ComputerDNSName OSPlatform LastIPAddress LastExternalIPAddress HealthStatus RiskScore ExposureLevel f70f9fe6 desktop-s9 Windows10 1.2.3.4 127.0.0.1 Active Medium Medium 48990365 desktop-s8 Windows10 1.2.3.5 127.0.0.1 Active Low Medium
5. microsoft-atp-get-machine-details
Gets a machine’s details by its identity.
Required Permissions
Machine.ReadWrite.All
Base Command
microsoft-atp-get-machine-details
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | A comma-separated list of machine IDs used to get the machine details, e.g., 0a3250e0693a109f1affc9217be9459028aa8426,0a3250e0693a109f1affc9217be9459028aa8424. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Machine.ID | String | The machine ID. |
| MicrosoftATP.Machine.ComputerDNSName | String | The machine DNS name. |
| MicrosoftATP.Machine.FirstSeen | Date | The first date and time where the machine was observed by Microsoft Defender ATP. |
| MicrosoftATP.Machine.LastSeen | Date | The last date and time where the machine was observed by Microsoft Defender ATP. |
| MicrosoftATP.Machine.OSPlatform | String | The operating system platform. |
| MicrosoftATP.Machine.OSVersion | String | The operating system version. |
| MicrosoftATP.Machine.OSProcessor | String | The operating system processor. |
| MicrosoftATP.Machine.LastIPAddress | String | The last IP on the machine. |
| MicrosoftATP.Machine.LastExternalIPAddress | String | The last machine IP to access the internet. |
| MicrosoftATP.Machine.OSBuild | Number | The operating system build number. |
| MicrosoftATP.Machine.HealthStatus | String | The machine health status. |
| MicrosoftATP.Machine.RBACGroupID | Number | The machine RBAC group ID. |
| MicrosoftATP.Machine.RBACGroupName | String | The machine RBAC group name. |
| MicrosoftATP.Machine.RiskScore | String | The machine risk score. |
| MicrosoftATP.Machine.ExposureLevel | String | The machine exposure level. |
| MicrosoftATP.Machine.IsAADJoined | Boolean | True if machine is AAD joined, False otherwise. |
| MicrosoftATP.Machine.AADDeviceID | String | The AAD Device ID. |
| MicrosoftATP.Machine.MachineTags | String | Set of machine tags. |
| MicrosoftATP.Machine.NetworkInterfaces.MACAddress | String | MAC Address for the Network interface. |
| MicrosoftATP.Machine.NetworkInterfaces.IPAddresses | String | IP Address(es) for the Network interface. |
| MicrosoftATP.Machine.NetworkInterfaces.Type | String | Type of the Network interface (e.g. Ethernet). |
| MicrosoftATP.Machine.NetworkInterfaces.Status | String | Status for the Network interface (e.g. Up, Down). |
Command example
!microsoft-atp-get-machine-details machine_id=f70f9fe6b29,4899036531e
Context Example
{
"MicrosoftATP": {
"Machine": [
{
"AgentVersion": "10.8040.19041.1466",
"ComputerDNSName": "desktop-s9",
"ExposureLevel": "Medium",
"FirstSeen": "2020-02-20T14:44:11.4627779Z",
"HealthStatus": "Active",
"ID": "f70f9fe6",
"IPAddresses": [
{
"ipAddress": "1.2.3.4",
"macAddress": "1234645645",
"operationalStatus": "Up",
"type": "Ethernet"
},
{
"ipAddress": "1234::1234:1234:3177:11dc",
"macAddress": "1234645645",
"operationalStatus": "Up",
"type": "Ethernet"
},
{
"ipAddress": "127.0.0.1",
"macAddress": "",
"operationalStatus": "Up",
"type": "SoftwareLoopback"
},
{
"ipAddress": "::1",
"macAddress": "",
"operationalStatus": "Up",
"type": "SoftwareLoopback"
}
],
"IsAADJoined": true,
"LastExternalIPAddress": "127.0.0.1",
"LastIPAddress": "1.2.3.4",
"LastSeen": "2022-01-25T11:14:39.7435843Z",
"MachineTags": [
"new test",
"test add tag",
"testing123"
],
"OSBuild": 19042,
"OSPlatform": "Windows10",
"OSProcessor": "x64",
"OSVersion": "20H2",
"RBACGroupID": 0,
"RiskScore": "Medium"
},
{
"AADDeviceID": "cfcf4177-227e-4cdb-ac8e-f9a3da1ca30c",
"AgentVersion": "10.8040.19041.1466",
"ComputerDNSName": "desktop-s8",
"ExposureLevel": "Medium",
"FirstSeen": "2020-02-17T08:30:07.2415577Z",
"HealthStatus": "Active",
"ID": "48990365",
"IPAddresses": [
{
"ipAddress": "1.2.3.5",
"macAddress": "1234645645",
"operationalStatus": "Up",
"type": "Ethernet"
},
{
"ipAddress": "1234::1234:1234:bc6e:23e1",
"macAddress": "1234645645",
"operationalStatus": "Up",
"type": "Ethernet"
},
{
"ipAddress": "127.0.0.1",
"macAddress": "",
"operationalStatus": "Up",
"type": "SoftwareLoopback"
},
{
"ipAddress": "::1",
"macAddress": "",
"operationalStatus": "Up",
"type": "SoftwareLoopback"
}
],
"IsAADJoined": true,
"LastExternalIPAddress": "127.0.0.1",
"LastIPAddress": "1.2.3.5",
"LastSeen": "2022-01-25T11:19:44.718919Z",
"MachineTags": [
"test Tag 2",
"test Tag 5"
],
"OSBuild": 19043,
"OSPlatform": "Windows10",
"OSProcessor": "x64",
"OSVersion": "21H1",
"RBACGroupID": 0,
"RiskScore": "Low"
}
]
}
}
Human Readable Output
Microsoft Defender ATP machines [‘f70f9fe6b29’,’4899036531e’] details
ID ComputerDNSName OSPlatform LastIPAddress LastExternalIPAddress HealthStatus RiskScore ExposureLevel IPAddresses f70f9fe6 desktop-s9 Windows10 1.2.3.4 127.0.0.1 Active Medium Medium 1. | MAC : 1234645645 | IP Addresses : 1.2.3.4,1234::1234:1234:3177:11dc | Type : Ethernet | Status : Up
2. | MAC : | IP Addresses : 127.0.0.1,::1 | Type : SoftwareLoopback | Status : Up48990365 desktop-s8 Windows10 1.2.3.5 127.0.0.1 Active Low Medium 1. | MAC : 1234645645 | IP Addresses : 1.2.3.5,1234::1234:1234:bc6e:23e1 | Type : Ethernet | Status : Up
2. | MAC : | IP Addresses : 127.0.0.1,::1 | Type : SoftwareLoopback | Status : Up
6. microsoft-atp-run-antivirus-scan
Initiates Microsoft Defender Antivirus scan on a machine.
Required Permissions
Machine.Scan
Note: When using the Authorization Code flow (either via the Cortex XSOAR application or by choosing delegated permissions for a self-deployed app), ensure the authenticated user has the “Active Remediation Actions” role assigned. Refer to the Microsoft documentation on creating and managing roles.
Base Command
microsoft-atp-run-antivirus-scan
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | A comma-separated list of machine IDs to run the scan on. | Required |
| comment | A comment to associate with the action. | Required |
| scan_type | Defines the type of the scan. Possible values are: Quick, Full. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.MachineAction.ID | String | The machine action ID. |
| MicrosoftATP.MachineAction.Type | String | The type of the action. |
| MicrosoftATP.MachineAction.Scope | Unknown | The scope of the action. |
| MicrosoftATP.MachineAction.Requestor | String | The ID of the user that executed the action. |
| MicrosoftATP.MachineAction.RequestorComment | String | The comment that was written when issuing the action. |
| MicrosoftATP.MachineAction.Status | String | The current status of the command. |
| MicrosoftATP.MachineAction.MachineID | String | The machine ID on which the action was executed. |
| MicrosoftATP.MachineAction.ComputerDNSName | String | The machine DNS name on which the action was executed. |
| MicrosoftATP.MachineAction.CreationDateTimeUtc | Date | The date and time when the action was created. |
| MicrosoftATP.MachineAction.LastUpdateTimeUtc | Date | The last date and time when the action status was updated. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifier | String | The file identifier. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifierType | String | The type of the file identifier. Possible values: “SHA1” ,”SHA256”, and “MD5”. |
Command example
!microsoft-atp-run-antivirus-scan machine_id=f70f9fe6,48990365 comment=test3 scan_type=Quick
Context Example
{
"MicrosoftATP": {
"MachineAction": [
{
"ComputerDNSName": "desktop-s9",
"CreationDateTimeUtc": "2022-01-25T17:57:18.7944822Z",
"ID": "98cf0adc",
"LastUpdateTimeUtc": null,
"MachineID": "f70f9fe6",
"RelatedFileInfo": {
"FileIdentifier": null,
"FileIdentifierType": null
},
"Requestor": "2f48b784-5da5-4e61-9957-012d2630f1e4",
"RequestorComment": "test3",
"Scope": "Quick",
"Status": "Pending",
"Type": "RunAntiVirusScan"
},
{
"ComputerDNSName": "desktop-s8",
"CreationDateTimeUtc": "2022-01-25T17:57:20.0458595Z",
"ID": "ecee8124",
"LastUpdateTimeUtc": null,
"MachineID": "48990365",
"RelatedFileInfo": {
"FileIdentifier": null,
"FileIdentifierType": null
},
"Requestor": "2f48b784-5da5-4e61-9957-012d2630f1e4",
"RequestorComment": "test3",
"Scope": "Quick",
"Status": "Pending",
"Type": "RunAntiVirusScan"
}
]
}
}
Human Readable Output
Antivirus scan successfully triggered
ID Type Requestor RequestorComment Status MachineID ComputerDNSName 98cf0adc RunAntiVirusScan 2f48b784-5da5-4e61-9957-012d2630f1e4 test3 Pending f70f9fe6 desktop-s9 ecee8124 RunAntiVirusScan 2f48b784-5da5-4e61-9957-012d2630f1e4 test3 Pending 48990365 desktop-s8
7. microsoft-atp-list-alerts (Deprecated)
This command has been deprecated. Use the ‘msg-search-alerts’ command in the ‘Microsoft Graph Security’ integration instead.
Gets a list of alerts that are present on the system. Filtering can be done on a single argument only.
Required Permissions
Alert.ReadWrite.All
Base Command
microsoft-atp-list-alerts
Input
| Argument Name | Description | Required |
|---|---|---|
| severity | Alert severity. Possible values are: High, Medium, Low, Informational. | Optional |
| status | Alert status. Possible values are: New, InProgress, Resolved. | Optional |
| category | Alert category; only one can be added. | Optional |
| limit | The maximum number of files to display. Default is 50. | Optional |
| creation_time | The creation timestamp from which to get alerts (<number> <time unit>, e.g., 12 hours, 7 days). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Alert.ID | String | The alert ID. |
| MicrosoftATP.Alert.IncidentID | Number | The Incident ID of the alert. |
| MicrosoftATP.Alert.InvestigationID | Number | The Investigation ID related to the alert. |
| MicrosoftATP.Alert.InvestigationState | String | The current state of the Investigation. |
| MicrosoftATP.Alert.AssignedTo | String | The owner of the alert. |
| MicrosoftATP.Alert.Severity | String | The severity of the alert. |
| MicrosoftATP.Alert.Status | String | The current status of the alert. |
| MicrosoftATP.Alert.Classification | String | The alert Classification. |
| MicrosoftATP.Alert.Determination | String | The determination of the alert. |
| MicrosoftATP.Alert.DetectionSource | String | The detection source. |
| MicrosoftATP.Alert.Category | String | The category of the alert. |
| MicrosoftATP.Alert.ThreatFamilyName | String | The threat family. |
| MicrosoftATP.Alert.Title | String | The alert title. |
| MicrosoftATP.Alert.Description | String | The alert description. |
| MicrosoftATP.Alert.AlertCreationTime | Date | The date and time the alert was created. |
| MicrosoftATP.Alert.FirstEventTime | Date | The first event time that triggered the alert on that machine. |
| MicrosoftATP.Alert.LastEventTime | Date | The last event time that triggered the alert on that machine. |
| MicrosoftATP.Alert.LastUpdateTime | Date | The UTC time of the last update. |
| MicrosoftATP.Alert.ResolvedTime | Date | The date and time in which the status of the alert was changed to ‘Resolved’. |
| MicrosoftATP.Alert.MachineID | String | The machine ID that is associated with the alert. |
| MicrosoftATP.Alert.ComputerDNSName | String | The machine DNS name. |
| MicrosoftATP.Alert.AADTenantID | String | The AAD tenant ID. |
| MicrosoftATP.Alert.Comments.Comment | String | The alert comment string. |
| MicrosoftATP.Alert.Comments.CreatedBy | String | The alert comment created by string. |
| MicrosoftATP.Alert.Comments.CreatedTime | Date | The alert comment created time date. |
| MicrosoftATP.Alert.Evidence | Unknown | Evidence related to the alert. |
| MicrosoftATP.Alert.DetectorID | String | The ID of the detector that triggered the alert. |
| MicrosoftATP.Alert.ThreatName | String | The threat name. |
| MicrosoftATP.Alert.RelatedUser | String | Details of the user related to a specific alert. |
| MicrosoftATP.Alert.MitreTechniques | String | MITRE Enterprise technique ID. |
| MicrosoftATP.Alert.RBACGroupName | String | The device RBAC group name. |
Command example
!microsoft-atp-list-alerts category=Malware severity=Informational status=Resolved creation_time="3 days" limit=1
Context Example
{
"MicrosoftATP": {
"Alert": {
"AADTenantID": "ebac1a16-81bf-449b-8d43-5732c3c1d999",
"AlertCreationTime": "2022-02-07T10:26:40.05748Z",
"AssignedTo": "Automation",
"Category": "Malware",
"Classification": null,
"Comments": [
{
"Comment": null,
"CreatedBy": null,
"CreatedTime": null
}
],
"ComputerDNSName": "win2016-msde-agent.msde.lab.demisto",
"Description": "Malware and unwanted software are undesirable applications that perform annoying, disruptive, or harmful actions on affected machines. Some of these undesirable applications can replicate and spread from one machine to another. Others are able to receive commands from remote attackers and perform activities associated with cyber attacks.\n\nThis detection might indicate that the malware was stopped from delivering its payload. However, it is prudent to check the machine for signs of infection.",
"DetectionSource": "WindowsDefenderAv",
"DetectorID": "d60f5b90-ecd8-4d77-8186-a801597ec762",
"Determination": null,
"Evidence": [
{
"aadUserId": null,
"accountName": null,
"detectionStatus": "Prevented",
"domainName": null,
"entityType": "File",
"evidenceCreationTime": "2022-02-07T10:26:40.24Z",
"fileName": "example.com",
"filePath": "C:\\Users\\admin\\Downloads",
"ipAddress": null,
"parentProcessCreationTime": null,
"parentProcessFileName": null,
"parentProcessFilePath": null,
"parentProcessId": null,
"processCommandLine": null,
"processCreationTime": null,
"processId": null,
"registryHive": null,
"registryKey": null,
"registryValue": null,
"registryValueType": null,
"sha1": "3395856ce81f2b7382dee72602f798b642f14140",
"sha256": "275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f",
"url": null,
"userPrincipalName": null,
"userSid": null
}
],
"FirstEventTime": "2022-02-07T10:20:52.2188896Z",
"ID": "da637798264000574516_1915313662",
"IncidentID": 648,
"InvestigationID": 675,
"InvestigationState": "SuccessfullyRemediated",
"LastEventTime": "2022-02-07T10:20:52.2571395Z",
"LastUpdateTime": "2022-02-07T10:57:13.93Z",
"MachineID": "4cceb3c642212014e0e9553aa8b59e999ea515ff",
"MitreTechniques": [],
"RBACGroupName": null,
"RelatedUser": null,
"ResolvedTime": "2022-02-07T10:57:13.773683Z",
"Severity": "Informational",
"Status": "Resolved",
"ThreatFamilyName": "Test_File",
"ThreatName": "Test_File",
"Title": "'Test_File' malware was prevented"
}
}
}
Human Readable Output
Microsoft Defender ATP alerts with limit of 1
ID Title Description IncidentID Severity Status Category ThreatFamilyName MachineID da637798264000574516_1915313662 ‘Test_File’ malware was prevented Malware and unwanted software are undesirable applications that perform annoying, disruptive, or harmful actions on affected machines. Some of these undesirable applications can replicate and spread from one machine to another. Others are able to receive commands from remote attackers and perform activities associated with cyber attacks.
This detection might indicate that the malware was stopped from delivering its payload. However, it is prudent to check the machine for signs of infection.648 Informational Resolved Malware Test_File 4cceb3c642212014e0e9553aa8b59e999ea515ff
8. microsoft-atp-update-alert (Deprecated)
This command has been deprecated. Use the ‘msg-update-alert’ command in the ‘Microsoft Graph Security’ integration instead.
Updates the properties of an alert entity.
Required Permissions
Alert.ReadWrite.All
Base Command
microsoft-atp-update-alert
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_id | The alert ID to update. | Required |
| status | The alert status to update. Possible values: “New”, “InProgress”, and “Resolved”. | Optional |
| assigned_to | The owner of the alert. | Optional |
| classification | The specification of the alert. Possible values: “Unknown”, “FalsePositive”, “TruePositive”, “InformationalExpectedActivity”. | Optional |
| determination | The determination of the alert. Possible values: “NotAvailable”, “Malware”, “SecurityTesting”, “UnwantedSoftware”, and “Other”. | Optional |
| comment | The comment to be added to the alert. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Alert.ID | String | The ID of the alert. |
| MicrosoftATP.Alert.IncidentID | Number | The incident ID of the alert. |
| MicrosoftATP.Alert.InvestigationID | Number | The investigation ID related to the alert. |
| MicrosoftATP.Alert.InvestigationState | String | The current state of the investigation. |
| MicrosoftATP.Alert.AssignedTo | String | The owner of the alert. |
| MicrosoftATP.Alert.Severity | String | The severity of the alert. |
| MicrosoftATP.Alert.Status | String | The current status of the alert. |
| MicrosoftATP.Alert.Classification | String | The alert classification. |
| MicrosoftATP.Alert.Determination | String | The determination of the alert. |
| MicrosoftATP.Alert.DetectionSource | String | The detection source. |
| MicrosoftATP.Alert.Category | String | The category of the alert. |
| MicrosoftATP.Alert.ThreatFamilyName | String | The threat family of the alert. |
| MicrosoftATP.Alert.Title | String | The title of the alert. |
| MicrosoftATP.Alert.Description | String | The description of the alert. |
| MicrosoftATP.Alert.AlertCreationTime | Date | The date and time the alert was created. |
| MicrosoftATP.Alert.FirstEventTime | Date | The first event time that triggered the alert on that machine. |
| MicrosoftATP.Alert.LastEventTime | Date | The last event time that triggered the alert on that machine. |
| MicrosoftATP.Alert.LastUpdateTime | Date | The UTC time of the last update. |
| MicrosoftATP.Alert.ResolvedTime | Date | The date and time in which the status of the alert was changed to “Resolved”. |
| MicrosoftATP.Alert.MachineID | String | The ID of the machine that is associated with the alert. |
| MicrosoftATP.Alert.ComputerDNSName | String | The DNS name of the machine. |
| MicrosoftATP.Alert.AADTenantID | String | The AAD tenant ID. |
| MicrosoftATP.Alert.Comments.Comment | String | The comment string of the alert. |
| MicrosoftATP.Alert.Comments.CreatedBy | String | The alert’s comment created by the string. |
| MicrosoftATP.Alert.Comments.CreatedTime | Date | The time and date the alert’s comment was created. |
Command Example
!microsoft-atp-update-alert alert_id=da637200417169017725_183736971 status=InProgress
Context Example
{
"MicrosoftATP.Alert": {
"Status": "InProgress",
"ID": "da637200417169017725_183736971"
}
}
Human Readable Output
The alert da637200417169017725_183736971 has been updated successfully
9. microsoft-atp-advanced-hunting (Deprecated)
This command has been deprecated. Use the ‘msg-advanced-hunting’ command in the ‘Microsoft Graph Security’ integration instead.
Runs programmatic queries in Microsoft Defender ATP Portal (https://securitycenter.windows.com/hunting).
- You can only run a query on data from the last 30 days.
- The maximum number of rows is 10,000.
- The number of executions is limited to 15 calls per minute, and 15 minutes of running time every hour, and 4 hours of running time a day.
- This API can only query tables belonging to Microsoft Defender for Endpoint.
The following reference - Data Schema,
lists all the tables in the schema. Each table name links to a page describing the column names for that table and which service it applies to.
Required Permissions
AdvancedQuery.Read.All
Base Command
microsoft-atp-advanced-hunting
Input
| Argument Name | Description | Required |
|---|---|---|
| query | The query to run. Must be passed if query_batch argument is empty. | Optional |
| timeout | The amount of time (in seconds) that a request waits for the query response before a timeout occurs. If specified with query_batch, will be applied to all queries in the array. Default is 10. | Optional |
| time_range | Time range to look back. The expected syntax is a human-readable time range, e.g., 60 minutes, 6 hours, 1 day, etc. If specified with query_batch, applies to all queries in the array. | Optional |
| query_batch | A JSON array of queries, limited to 10 queries. Cannot be provided with the query argument. Example for input: [ { “query”: “query #1”, “name”: “name #1”, “timeout”: “timeout #1” “time_range”: “2 days ago” // Non-mandatory, will override the {time_range} argument }, { “query”: “query #2”, “name”: “name #2”, “timeout”: “timeout #2” “time_range”: “6 days ago”t } ] . The query and name fields are mandatory. If timeout and time_range are specified, they will override the {timeout} and {time_range} argument. |
Optional |
| name | If stated along with query, the response will be saved in context under the Result.name path. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Hunt.Result | String | The query results. |
Command example
```!microsoft-atp-advanced-hunting query_batch={"queries": [{"query": "DeviceInfo | where OnboardingStatus == 'Onboarded' | limit 10 | distinct DeviceName", "name": "name", "timeout": "20"}]}12
Context Example
{
"MicrosoftATP": {
"Hunt": {
"Result": [
{
"name": [
{
"DeviceName": "msde-agent-host-centos7.c.dmst-integrations.internal"
},
{
"DeviceName": "desktop-s2455r8"
}
]
}
]
}
}
}
Human Readable Output
Hunt results for name query
DeviceName msde-agent-host-centos7.c.dmst-integrations.internal desktop-s2455r8
Command Example
!microsoft-atp-advanced-hunting query="DeviceLogonEvents | take 1 | project DeviceId, ReportId, tostring(Timestamp)"
Context Example
{
"MicrosoftATP.Hunt.Result": [
{
"DeviceId": "4899036531e374137f63289c3267bad772c13fef",
"Timestamp": "2020-02-23T07:14:42.1599815Z",
"ReportId": "35275"
}
]
}
Human Readable Output
Hunt results
| Timestamp | DeviceId | ReportId |
|---|---|---|
| 2020-02-23T07:14:42.1599815Z | 4899036531e374137f63289c3267bad772c13fef | 35275 |
10. microsoft-atp-create-alert (Deprecated)
This command has been deprecated. No available replacement.
Creates a new alert entity using event data, as obtained from the Advanced Hunting.
Required Permissions
Alert.ReadWrite.All
Base Command
microsoft-atp-create-alert
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | The ID of the machine on which the event was identified. | Required |
| severity | The severity of the alert. Severity of the alert. Possible values: “Low”, “Medium”, and “High”. | Required |
| title | The title of the alert. | Required |
| description | The description of the alert. | Required |
| recommended_action | Recommended action for the security officer to take when analyzing the alert. | Required |
| event_time | The time of the event, as obtained from the advanced query. | Required |
| report_id | The report ID, as obtained from the advanced query. | Required |
| category | The category of the alert. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Alert.ID | String | The ID of the alert. |
| MicrosoftATP.Alert.IncidentID | Number | The incident ID of the alert. |
| MicrosoftATP.Alert.InvestigationID | Number | The investigation ID related to the alert. |
| MicrosoftATP.Alert.InvestigationState | String | The current state of the investigation. |
| MicrosoftATP.Alert.AssignedTo | String | The owner of the alert. |
| MicrosoftATP.Alert.Severity | String | The severity of the alert. |
| MicrosoftATP.Alert.Status | String | The current status of the alert. |
| MicrosoftATP.Alert.Classification | String | The classification of the alert. |
| MicrosoftATP.Alert.Determination | String | The determination of the alert. |
| MicrosoftATP.Alert.DetectionSource | String | The detection source. |
| MicrosoftATP.Alert.Category | String | The category of the alert. |
| MicrosoftATP.Alert.ThreatFamilyName | String | The threat family of the alert. |
| MicrosoftATP.Alert.Title | String | The title of the alert. |
| MicrosoftATP.Alert.Description | String | The description of the alert. |
| MicrosoftATP.Alert.AlertCreationTime | Date | The date and time the alert was created. |
| MicrosoftATP.Alert.FirstEventTime | Date | The first event time that triggered the alert on that machine. |
| MicrosoftATP.Alert.LastEventTime | Date | The last event time that triggered the alert on that machine. |
| MicrosoftATP.Alert.LastUpdateTime | Date | The UTC time of the last update. |
| MicrosoftATP.Alert.ResolvedTime | Date | The date and time in which the status of the alert was changed to “Resolved”. |
| MicrosoftATP.Alert.MachineID | String | The machine ID that is associated with the alert. |
| MicrosoftATP.Alert.ComputerDNSName | String | The DNS name of the machine. |
| MicrosoftATP.Alert.AADTenantID | String | The AAD tenant ID. |
| MicrosoftATP.Alert.Comments.Comment | String | The comment string of the alert. |
| MicrosoftATP.Alert.Comments.CreatedBy | String | The alert’s comment created by the string. |
| MicrosoftATP.Alert.Comments.CreatedTime | Date | The time and date the alert comment was created. |
Command Example
!microsoft-atp-create-alert category=Backdoor description="test" report_id=20279 event_time=2020-02-23T07:22:07.1532018Z machine_id=deviceid_2 recommended_action="runAntiVirusScan" severity=Low title="testing alert"
Context Example
{
"MicrosoftATP.Alert": {
"Category": "Backdoor",
"ThreatFamilyName": null,
"Severity": "Low",
"LastEventTime": "2020-02-23T07:22:07.1532018Z",
"FirstEventTime": "2020-02-23T07:22:07.1532018Z",
"Comments": [
{
"Comment": null,
"CreatedTime": null,
"CreatedBy": null
}
],
"AADTenantID": "TENANT-ID",
"AlertCreationTime": "2020-03-22T15:44:23.5446957Z",
"Status": "New",
"Description": "test",
"InvestigationState": "PendingApproval",
"MachineID": "4899036531e374137f63289c3267bad772c13fef",
"Title": "testing alert",
"InvestigationID": 10,
"Determination": null,
"IncidentID": 18,
"AssignedTo": null,
"DetectionSource": "CustomerTI",
"ResolvedTime": null,
"ID": "da637204886635759335_1480542752",
"LastUpdateTime": "2020-03-22T15:44:24.6533333Z",
"Classification": null,
"ComputerDNSName": "desktop-s2455r8",
"Evidence": []
}
}
Human Readable Output
Alert created
| ID | Title | Description | IncidentID | Severity | Status | Category | MachineID |
|---|---|---|---|---|---|---|---|
| da637204886635759335_1480542752 | testing alert | test | 18 | Low | New | Backdoor | 4899036531e374137f63289c3267bad772c13fef |
11. microsoft-atp-get-alert-related-user (Deprecated)
This command has been deprecated. An alternative is to use the ‘msg-get-alert-details’ command in the ‘Microsoft Graph Security’ integration, which can retrieve userAccount information as part of the alert details.
Retrieves the user associated with a specific alert.
Required Permissions
User.Read.All
Base Command
microsoft-atp-get-alert-related-user
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The ID of the alert. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.AlertUser.User.ID | String | The ID of the user. |
| MicrosoftATP.AlertUser.User.AccountName | String | The account name. |
| MicrosoftATP.AlertUser.User.AccountDomain | String | The account domain. |
| MicrosoftATP.AlertUser.User.AccountSID | String | The account SID. |
| MicrosoftATP.AlertUser.User.FirstSeen | Date | The user first seen date and time. |
| MicrosoftATP.AlertUser.User.LastSeen | Date | The user last seen date and time. |
| MicrosoftATP.AlertUser.User.MostPrevalentMachineID | String | The most prevalent machine ID. |
| MicrosoftATP.AlertUser.User.LeastPrevalentMachineID | String | The least prevalent machine ID. |
| MicrosoftATP.AlertUser.User.LogonTypes | String | The user logon types. |
| MicrosoftATP.AlertUser.User.LogonCount | Number | The user logon count. |
| MicrosoftATP.AlertUser.User.DomainAdmin | Number | The domain admin. |
| MicrosoftATP.AlertUser.User.NetworkUser | Number | The network admin. |
| MicrosoftATP.AlertUser.AlertID | String | The ID of the alert. |
Command Example
!microsoft-atp-get-alert-related-user id=da637175364995825348_1865170845
Context Example
{
"MicrosoftATP.AlertUser": {
"User": {
"LeastPrevalentMachineID": "4899036531e374137f63289c3267bad772c13fef",
"MostPrevalentMachineID": "4899036531e374137f63289c3267bad772c13fef",
"LogonCount": 1,
"NetworkUser": false,
"DomainAdmin": false,
"LogonTypes": null,
"AccountName": "demisto",
"LastSeen": "2020-03-03T12:32:51Z",
"AccountSID": "S-1-5-21-4197691174-1403503641-4006700887-1001",
"AccountDomain": "desktop-s2455r8",
"ID": "desktop-s2455r8\\demisto",
"FirstSeen": "2020-02-23T07:14:42Z"
},
"AlertID": "da637175364995825348_1865170845"
}
}
Human Readable Output
Alert Related User
| AccountDomain | AccountName | AccountSID | DomainAdmin | FirstSeen | ID | LastSeen | LeastPrevalentMachineID | LogonCount | MostPrevalentMachineID | NetworkUser |
|---|---|---|---|---|---|---|---|---|---|---|
| desktop-s2455r8 | demisto | S-1-5-21-4197691174-1403503641-4006700887-1001 | false | 2020-02-23T07:14:42Z | desktop-s2455r8\demisto | 2020-03-03T12:32:51Z | 4899036531e374137f63289c3267bad772c13fef | 1 | 4899036531e374137f63289c3267bad772c13fef | false |
12. microsoft-atp-get-alert-related-files (Deprecated)
This command has been deprecated. An alternative is to use the ‘msg-get-alert-details’ command in the ‘Microsoft Graph Security’ integration, which can retrieve fileDetails as part of the alert details.
Retrieves the files associated to a specific alert.
Required Permissions
File.Read.All
Base Command
microsoft-atp-get-alert-related-files
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The ID of the alert. | Required |
| limit | The limit of files to display. | Optional |
| offset | The page from which to get the related files. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.AlertFile.Files.FilePublisher | String | The file’s publisher. |
| MicrosoftATP.AlertFile.Files.Size | Number | The size of the file. |
| MicrosoftATP.AlertFile.Files.GlobalLastObserved | Date | The last time the file was observed. |
| MicrosoftATP.AlertFile.Files.Sha1 | String | The SHA1 hash of the file. |
| MicrosoftATP.AlertFile.Files.IsValidCertificate | Number | Whether the signing of the certificate was successfully verified by the Microsoft Defender ATP agent. |
| MicrosoftATP.AlertFile.Files.Sha256 | String | The SHA256 hash of the file. |
| MicrosoftATP.AlertFile.Files.Signer | String | The file signer. |
| MicrosoftATP.AlertFile.Files.GlobalPrevalence | Number | The file prevalence across the organization. |
| MicrosoftATP.AlertFile.Files.DeterminationValue | String | The determination of the file’s value. |
| MicrosoftATP.AlertFile.Files.GlobalFirstObserved | Date | The first time the file was observed. |
| MicrosoftATP.AlertFile.Files.FileType | String | The type of the file. |
| MicrosoftATP.AlertFile.Files.SignerHash | String | The hash of the signing certificate. |
| MicrosoftATP.AlertFile.Files.Issuer | String | The file issuer. |
| MicrosoftATP.AlertFile.Files.IsPeFile | Number | Wether the file is portable executable. |
| MicrosoftATP.AlertFile.Files.DeterminationType | String | The determination type of the file. |
| MicrosoftATP.AlertFile.Files.FileProductName | Unknown | The product name of the file. |
| MicrosoftATP.AlertFile.Files.Md5 | String | The MD5 hash of the file. |
Command Example
!microsoft-atp-get-alert-related-files id=da637175364995825348_1865170845
Context Example
{
"MicrosoftATP.AlertFile": {
"Files": [
{
"DeterminationType": "Unknown",
"SignerHash": "84ec67b9ac9d7789bab500503a7862173f432adb",
"Sha1": "d487580502354c61808c7180d1a336beb7ad4624",
"IsPeFile": true,
"GlobalPrevalence": 45004,
"SizeInBytes": 181248,
"Signer": "Microsoft Windows",
"GlobalFirstObserved": "2019-03-21T22:37:42.7608151Z",
"IsValidCertificate": true,
"GlobalLastObserved": "2020-03-22T22:48:20.608421Z",
"Sha256": "f1d62648ef915d85cb4fc140359e925395d315c70f3566b63bb3e21151cb2ce3",
"Md5": "f1139811bbf61362915958806ad30211",
"Issuer": "Microsoft Windows Production PCA 2011"
},
{
"DeterminationType": "Unknown",
"SignerHash": "84ec67b9ac9d7789bab500503a7862173f432adb",
"Sha1": "36c5d12033b2eaf251bae61c00690ffb17fddc87",
"IsPeFile": true,
"GlobalPrevalence": 1316463,
"SizeInBytes": 451584,
"Signer": "Microsoft Windows",
"GlobalFirstObserved": "2019-03-21T08:31:08.1952647Z",
"IsValidCertificate": true,
"GlobalLastObserved": "2020-03-23T09:24:49.9664767Z",
"Sha256": "908b64b1971a979c7e3e8ce4621945cba84854cb98d76367b791a6e22b5f6d53",
"Md5": "cda48fc75952ad12d99e526d0b6bf70a",
"Issuer": "Microsoft Windows Production PCA 2011"
}
],
"AlertID": "da637175364995825348_1865170845"
}
}
Human Readable Output
Alert da637175364995825348_1865170845 Related Files
| Sha1 | Sha256 | SizeInBytes |
|---|---|---|
| d487580502354c61808c7180d1a336beb7ad4624 | f1d62648ef915d85cb4fc140359e925395d315c70f3566b63bb3e21151cb2ce3 | 181248 |
| 36c5d12033b2eaf251bae61c00690ffb17fddc87 | 908b64b1971a979c7e3e8ce4621945cba84854cb98d76367b791a6e22b5f6d53 | 451584 |
13. microsoft-atp-get-alert-related-ips (Deprecated)
This command has been deprecated. An alternative is to use the ‘msg-get-alert-details’ command in the ‘Microsoft Graph Security’ integration, which can retrieve IpAddress as part of the alert details
Retrieves the IP addresses associated to a specific alert.
Required Permissions
Ip.Read.All
Base Command
microsoft-atp-get-alert-related-ips
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The ID of the alert. | Required |
| limit | The limit of IP addresses to display. | Optional |
| offset | The page from which to get the related IP addresses. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.AlertIP.IPs.IpAddress | String | The address of the IP address. |
| MicrosoftATP.AlertIP.AlertID | String | The ID of the alert. |
Command Example
!microsoft-atp-get-alert-related-ips id=da637200417169017725_183736971 limit=3 offset=0
Context Example
{
"MicrosoftATP.AlertIP": {
"IPs": [],
"AlertID": "da637200417169017725_183736971"
}
}
Human Readable Output
Alert da637200417169017725_183736971 Related IPs: []
14. microsoft-atp-get-alert-related-domains (Deprecated)
This command has been deprecated. An alternative is to use the ‘msg-get-alert-details’ command in the ‘Microsoft Graph Security’ integration to retrieve DomainName as part of the alert details.
Retrieves the domains associated with a specific alert.
Required Permissions
URL.Read.All
Base Command
microsoft-atp-get-alert-related-domains
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The ID of the alert. | Required |
| limit | The limit of domains to display. | Optional |
| offset | The page from which to get the related domains. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.AlertDomain.Domains.Domain | String | The domain address. |
| MicrosoftATP.AlertDomain.AlertID | Unknown | The ID of the alert. |
Command Example
!microsoft-atp-get-alert-related-domains id=da637175364995825348_1865170845 limit=2 offset=0
Context Example
{
"MicrosoftATP.AlertDomain": {
"Domains": [],
"AlertID": "da637175364995825348_1865170845"
}
}
Human Readable Output
Alert da637175364995825348_1865170845 Related Domains: []
15. microsoft-atp-list-machine-actions-details
Returns the machine’s actions. If an action ID is set it returns the information on the specific action.
Filtering can only be done on a single argument.
Required Permissions
Machine.ReadWrite.All
Base Command
microsoft-atp-list-machine-actions-details
Input
| Argument Name | Description | Required |
|---|---|---|
| id | ID of the action. | Optional |
| status | The machine action status. Possible values are: Pending, InProgress, Succeeded, Failed, TimeOut, Cancelled. | Optional |
| machine_id | A comma-separated list of machine IDs on which the action was executed. | Optional |
| type | The machine action type. Possible values are: RunAntiVirusScan, Offboard, CollectInvestigationPackage, Isolate, Unisolate, StopAndQuarantineFile, RestrictCodeExecution, UnrestrictCodeExecution. | Optional |
| requestor | The ID of the user that executed the action, only one can be added. | Optional |
| limit | The maximum number of machines to return. Default is 50. | Optional |
| filters | String representation of filters (Override every other filters). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.MachineAction.ID | String | The machine action ID. |
| MicrosoftATP.MachineAction.Type | String | The type of the action. |
| MicrosoftATP.MachineAction.Scope | String | The scope of the action. |
| MicrosoftATP.MachineAction.Requestor | String | The ID of the user that executed the action. |
| MicrosoftATP.MachineAction.RequestorComment | String | The comment that was written when issuing the action. |
| MicrosoftATP.MachineAction.Status | String | The current status of the command. |
| MicrosoftATP.MachineAction.MachineID | String | The machine ID on which the action was executed. |
| MicrosoftATP.MachineAction.ComputerDNSName | String | The machine DNS name on which the action was executed. |
| MicrosoftATP.MachineAction.CreationDateTimeUtc | Date | The date and time when the action was created. |
| MicrosoftATP.MachineAction.LastUpdateTimeUtc | Date | The last date and time when the action status was updated. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifier | String | The file identifier. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifierType | String | The type of the file identifier. Possible values: “SHA1” ,”SHA256”, and “MD5”. |
Command example
!microsoft-atp-list-machine-actions-details machine_id="f70f9fe6,48990365" type=RunAntiVirusScan status=Succeeded
Context Example
{
"MicrosoftATP": {
"MachineAction": [
{
"ComputerDNSName": "desktop-s9",
"CreationDateTimeUtc": "2022-01-25T17:57:18.7944822Z",
"ID": "98cf0adc",
"LastUpdateTimeUtc": null,
"MachineID": "f70f9fe6",
"RelatedFileInfo": {
"FileIdentifier": null,
"FileIdentifierType": null
},
"Requestor": "2f48b784-5da5-4e61-9957-012d2630f1e4",
"RequestorComment": "test3",
"Scope": "Quick",
"Status": "Succeeded",
"Type": "RunAntiVirusScan"
},
{
"ComputerDNSName": "desktop-s8",
"CreationDateTimeUtc": "2022-01-25T17:56:04.3073008Z",
"ID": "99a29fc5",
"LastUpdateTimeUtc": null,
"MachineID": "48990365",
"RelatedFileInfo": {
"FileIdentifier": null,
"FileIdentifierType": null
},
"Requestor": "2f48b784-5da5-4e61-9957-012d2630f1e4",
"RequestorComment": "test2",
"Scope": "Quick",
"Status": "Succeeded",
"Type": "RunAntiVirusScan"
}
]
}
}
Human Readable Output
Machine actions Info
ID Type Requestor RequestorComment Status MachineID ComputerDNSName 98cf0adc RunAntiVirusScan 2f48b784-5da5-4e61-9957-012d2630f1e4 test3 Succeeded f70f9fe6 desktop-s9 99a29fc5 RunAntiVirusScan 2f48b784-5da5-4e61-9957-012d2630f1e4 test2 Succeeded 48990365 desktop-s8
16. microsoft-atp-collect-investigation-package
Collects an investigation package from a machine.
Required Permissions
Machine.CollectForensics
Note: When using the Authorization Code flow (either via the Cortex XSOAR application or by choosing delegated permissions for a self-deployed app), ensure the authenticated user has the “Active Remediation Actions” role assigned. Refer to the Microsoft documentation on creating and managing roles.
Base Command
microsoft-atp-collect-investigation-package
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | The ID of the machine. | Required |
| comment | The comment to associate with the action. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.MachineAction.ID | String | The action ID of the machine. |
| MicrosoftATP.MachineAction.Type | String | The type of the action. |
| MicrosoftATP.MachineAction.Scope | String | The scope of the action. |
| MicrosoftATP.MachineAction.Requestor | String | The ID of the user that executed the action. |
| MicrosoftATP.MachineAction.RequestorComment | String | The comment that was written when issuing the action. |
| MicrosoftATP.MachineAction.Status | String | The current status of the command. |
| MicrosoftATP.MachineAction.MachineID | String | The machine ID on which the action was executed. |
| MicrosoftATP.MachineAction.ComputerDNSName | String | The machine DNS name the action was executed on. |
| MicrosoftATP.MachineAction.CreationDateTimeUtc | Date | The date and time when the action was created. |
| MicrosoftATP.MachineAction.LastUpdateTimeUtc | Date | The last date and time when the action status was updated. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifier | String | The file identifier. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifierType | String | The type of the file identifier. Possible values: “SHA1”, “SHA256”, and “MD5”. |
Command Example
!microsoft-atp-collect-investigation-package comment="testing" machine_id=f70f9fe6b29cd9511652434919c6530618f06606
Context Example
{
"MicrosoftATP.MachineAction": {
"Status": "Pending",
"CreationDateTimeUtc": "2020-03-23T10:08:05.8010798Z",
"MachineID": "f70f9fe6b29cd9511652434919c6530618f06606",
"LastUpdateTimeUtc": null,
"ComputerDNSName": null,
"Requestor": "2f48b784-5da5-4e61-9957-012d2630f1e4",
"RelatedFileInfo": {
"FileIdentifier": null,
"FileIdentifierType": null
},
"Scope": null,
"Type": "CollectInvestigationPackage",
"ID": "fa952f94-d672-47a6-a637-70b91339c079",
"RequestorComment": "testing"
}
}
Human Readable Output
Initiating collect investigation package from f70f9fe6b29cd9511652434919c6530618f06606 machine
| ID | Type | Requestor | RequestorComment | Status | MachineID |
|---|---|---|---|---|---|
| fa952f94-d672-47a6-a637-70b91339c079 | CollectInvestigationPackage | 2f48b784-5da5-4e61-9957-012d2630f1e4 | testing | Pending | f70f9fe6b29cd9511652434919c6530618f06606 |
17. microsoft-atp-get-investigation-package-sas-uri
Gets a URI that allows downloading of an investigation package.
Required Permissions
Machine.CollectForensics
Note: When using the Authorization Code flow (either via the Cortex XSOAR application or by choosing delegated permissions for a self-deployed app), ensure the authenticated user has the “Active Remediation Actions” role assigned. Refer to the Microsoft documentation on creating and managing roles.
Base Command
microsoft-atp-get-investigation-package-sas-uri
Input
| Argument Name | Description | Required |
|---|---|---|
| action_id | The action ID of the machine. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.InvestigationURI.Link | String | The investigation package URI. |
Command Example
!microsoft-atp-get-investigation-package-sas-uri action_id=6ae51f8f-68e6-4259-abae-0018fdf2e418
Context Example
{
"MicrosoftATP.InvestigationURI": {
"Link": "https://userrequests-us.securitycenter.windows.com:443/safedownload/WDATP_Investigation_Package.zip?token=MIICYwYJKoZIhvcNAQcCoIICV"
}
}
Human Readable Output
Success. This link is valid for a very short time and should be used immediately for downloading the package to a local storage: https:
//userrequests-us.securitycenter.windows.com:443/safedownload/WDATP_Investigation_Package.zip?token=MIICYwYJKoZIhvcNAQcCoIICV
18. microsoft-atp-restrict-app-execution
Restricts the execution of all applications on the machine except a predefined set.
Required Permissions
Machine.RestrictExecution
Note: When using the Authorization Code flow (either via the Cortex XSOAR application or by choosing delegated permissions for a self-deployed app), ensure the authenticated user has the “Active Remediation Actions” role assigned. Refer to the Microsoft documentation on creating and managing roles.
Base Command
microsoft-atp-restrict-app-execution
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | The ID of the machine. | Required |
| comment | The comment to associate with the action. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.MachineAction.ID | String | The action ID of the machine. |
| MicrosoftATP.MachineAction.Type | String | The type of the action. |
| MicrosoftATP.MachineAction.Scope | String | The scope of the action. |
| MicrosoftATP.MachineAction.Requestor | String | The ID of the user that executed the action. |
| MicrosoftATP.MachineAction.RequestorComment | String | The comment that was written when issuing the action. |
| MicrosoftATP.MachineAction.Status | String | The current status of the command. |
| MicrosoftATP.MachineAction.MachineID | String | The machine ID the action was executed on. |
| MicrosoftATP.MachineAction.ComputerDNSName | String | The machine DNS name the action was executed on. |
| MicrosoftATP.MachineAction.CreationDateTimeUtc | Date | The date and time when the action was created. |
| MicrosoftATP.MachineAction.LastUpdateTimeUtc | Date | The last date and time when the action status was updated. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifier | String | The file identifier. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifierType | String | The type of the file identifier. Possible values: “SHA1”, “SHA256”, and “MD5”. |
Command Example
!microsoft-atp-restrict-app-execution machine_id=f70f9fe6b29cd9511652434919c6530618f06606 comment="test restrict app"
Context Example
{
"MicrosoftATP.MachineAction": {
"Status": "Pending",
"CreationDateTimeUtc": "2020-03-23T10:08:07.7643812Z",
"MachineID": "f70f9fe6b29cd9511652434919c6530618f06606",
"LastUpdateTimeUtc": null,
"ComputerDNSName": null,
"Requestor": "2f48b784-5da5-4e61-9957-012d2630f1e4",
"RelatedFileInfo": {
"FileIdentifier": null,
"FileIdentifierType": null
},
"Scope": null,
"Type": "RestrictCodeExecution",
"ID": "264c80f0-1452-43fb-92d0-5515dd0b821e",
"RequestorComment": "test restrict app"
}
}
Human Readable Output
Initiating Restrict execution of all applications on the machine f70f9fe6b29cd9511652434919c6530618f06606 except a predefined set
| ID | Type | Requestor | RequestorComment | Status | MachineID |
|---|---|---|---|---|---|
| 264c80f0-1452-43fb-92d0-5515dd0b821e | RestrictCodeExecution | 2f48b784-5da5-4e61-9957-012d2630f1e4 | test restrict app | Pending | f70f9fe6b29cd9511652434919c6530618f06606 |
19. microsoft-atp-remove-app-restriction
Enables the execution of any application on the machine.
Required Permissions
Machine.RestrictExecution
Note: When using the Authorization Code flow (either via the Cortex XSOAR application or by choosing delegated permissions for a self-deployed app), ensure the authenticated user has the “Active Remediation Actions” role assigned. Refer to the Microsoft documentation on creating and managing roles.
Base Command
microsoft-atp-remove-app-restriction
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | The ID of the machine. | Required |
| comment | The comment to associate with the action. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.MachineAction.ID | String | The action ID of the machine. |
| MicrosoftATP.MachineAction.Type | String | The type of the action. |
| MicrosoftATP.MachineAction.Scope | String | The scope of the action. |
| MicrosoftATP.MachineAction.Requestor | String | The ID of the user that executed the action. |
| MicrosoftATP.MachineAction.RequestorComment | String | The comment that was written when issuing the action. |
| MicrosoftATP.MachineAction.Status | String | The current status of the command. |
| MicrosoftATP.MachineAction.MachineID | String | The machine ID the action was executed on. |
| MicrosoftATP.MachineAction.ComputerDNSName | String | The machine DNS name the action was executed on. |
| MicrosoftATP.MachineAction.CreationDateTimeUtc | Date | The date and time when the action was created. |
| MicrosoftATP.MachineAction.LastUpdateTimeUtc | Date | The last date and time when the action status was updated. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifier | String | The file identifier. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifierType | String | The type of the file identifier. Possible values: “SHA1”, “SHA256”, and “MD5”. |
Command Example
!microsoft-atp-remove-app-restriction machine_id=f70f9fe6b29cd9511652434919c6530618f06606 comment="testing remove restriction"
Context Example
{
"MicrosoftATP.MachineAction": {
"Status": "Pending",
"CreationDateTimeUtc": "2020-03-23T10:08:08.5355244Z",
"MachineID": "f70f9fe6b29cd9511652434919c6530618f06606",
"LastUpdateTimeUtc": null,
"ComputerDNSName": null,
"Requestor": "2f48b784-5da5-4e61-9957-012d2630f1e4",
"RelatedFileInfo": {
"FileIdentifier": null,
"FileIdentifierType": null
},
"Scope": null,
"Type": "UnrestrictCodeExecution",
"ID": "5e3cc0b8-b1a1-4a07-92bf-4d63ecec1b18",
"RequestorComment": "testing remove restriction"
}
}
Human Readable Output
Removing applications restriction on the machine f70f9fe6b29cd9511652434919c6530618f06606
| ID | Type | Requestor | RequestorComment | Status | MachineID |
|---|---|---|---|---|---|
| 5e3cc0b8-b1a1-4a07-92bf-4d63ecec1b18 | UnrestrictCodeExecution | 2f48b784-5da5-4e61-9957-012d2630f1e4 | testing remove restriction | Pending | f70f9fe6b29cd9511652434919c6530618f06606 |
20. microsoft-atp-stop-and-quarantine-file
Stops the execution of a file on a machine and deletes it.
Required Permissions
Machine.StopAndQuarantine
Note: When using the Authorization Code flow (either via the Cortex XSOAR application or by choosing delegated permissions for a self-deployed app), ensure the authenticated user has the “Active Remediation Actions” role assigned. Refer to the Microsoft documentation on creating and managing roles.
Base Command
microsoft-atp-stop-and-quarantine-file
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | The ID of the machine. When providing multiple values, each value is checked for the same hash. | Required |
| file_hash | The file SHA1 hash to stop and quarantine on the machine. When providing multiple values, each value is checked for the same machine_id. | Required |
| comment | The comment to associate with the action. | Required |
| polling | Whether to poll for the action status. | Optional |
| timeout_in_seconds | The timeout in seconds for the polling. | Optional |
| interval_in_seconds | The interval in seconds between polling. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.MachineAction.ID | String | The action ID of the machine. |
| MicrosoftATP.MachineAction.Type | String | The type of the action. |
| MicrosoftATP.MachineAction.Scope | String | The scope of the action. |
| MicrosoftATP.MachineAction.Requestor | String | The ID of the user that executed the action. |
| MicrosoftATP.MachineAction.RequestorComment | String | The comment that was written when issuing the action. |
| MicrosoftATP.MachineAction.Status | String | The current status of the command. |
| MicrosoftATP.MachineAction.MachineID | String | The machine ID on which the action was executed. |
| MicrosoftATP.MachineAction.ComputerDNSName | String | The machine DNS name on which the action was executed. |
| MicrosoftATP.MachineAction.CreationDateTimeUtc | Date | The date and time when the action was created. |
| MicrosoftATP.MachineAction.LastUpdateTimeUtc | Date | The last date and time when the action status was updated. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifier | String | The file identifier. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifierType | String | The type of the file identifier. Possible values: “SHA1”, “SHA256”, and “MD5”. |
Command Example
!microsoft-atp-stop-and-quarantine-file comment="testing" file_hash=abe3ba25e5660c23dfe478d577cfacde5795870c machine_id=12345678
Context Example
{
"ID": "123",
"Type": "StopAndQuarantineFile",
"Scope": null,
"Requestor": "123abc",
"RequestorComment": "Test",
"Status": "Pending",
"MachineID": "12345678",
"ComputerDNSName": null,
"CreationDateTimeUtc": "2020-03-20T14:21:49.9097785Z",
"LastUpdateTimeUtc": "2020-02-27T12:21:00.4568741Z",
"RelatedFileInfo": {
"fileIdentifier": "87654321", "fileIdentifierType": "Sha1"
}
}
Human Readable Output
Stopping the execution of a file on 12345678 machine and deleting it
| ID | Type | Requestor | RequestorComment | Status | MachineID |
|---|---|---|---|---|---|
| 123 | StopAndQuarantineFile | 123abc | Test | Pending | 12345678 |
21. microsoft-atp-list-investigations
Retrieves a collection of investigations or retrieves a specific investigation by its ID.
Required Permissions
Alert.ReadWrite.All
Base Command
microsoft-atp-list-investigations
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The ID can be the investigation ID or the investigation triggering an alert ID. | Optional |
| limit | The limit of investigations to display. | Optional |
| offset | The page from which to get the investigations. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Investigation.ID | String | The ID of the investigation. |
| MicrosoftATP.Investigation.StartTime | Date | The date and time when the investigation was created. |
| MicrosoftATP.Investigation.EndTime | Date | The date and time when the investigation was completed. |
| MicrosoftATP.Investigation.State | String | The state of the investigation. |
| MicrosoftATP.Investigation.CancelledBy | Unknown | The ID of the user or application that cancelled that investigation. |
| MicrosoftATP.Investigation.StatusDetails | Unknown | The details of the state of the investigation. |
| MicrosoftATP.Investigation.MachineID | String | The machine ID the investigation is executed on. |
| MicrosoftATP.Investigation.ComputerDNSName | String | The machine DNS name the investigation is executed on. |
| MicrosoftATP.Investigation.TriggeringAlertID | String | The alert ID that triggered the investigation. |
Command Example
!microsoft-atp-list-investigations limit=3 offset=0
Context Example
{
"MicrosoftATP.Investigation": [
{
"CancelledBy": null,
"InvestigationState": "PendingApproval",
"MachineID": "4899036531e374137f63289c3267bad772c13fef",
"TriggeringAlertID": "da637200417169017725_183736971",
"ComputerDNSName": "desktop-s2455r8",
"StatusDetails": null,
"StartTime": "2020-03-17T11:35:17Z",
"EndTime": null,
"ID": "10"
},
{
"CancelledBy": null,
"InvestigationState": "PendingApproval",
"MachineID": "f70f9fe6b29cd9511652434919c6530618f06606",
"TriggeringAlertID": "da637200385941308230_1832866941",
"ComputerDNSName": "desktop-s2455r9",
"StatusDetails": null,
"StartTime": "2020-03-17T10:43:15Z",
"EndTime": null,
"ID": "9"
},
{
"CancelledBy": null,
"InvestigationState": "TerminatedBySystem",
"MachineID": "f70f9fe6b29cd9511652434919c6530618f06606",
"TriggeringAlertID": "da637189366671550108_395377714",
"ComputerDNSName": "desktop-s2455r9",
"StatusDetails": null,
"StartTime": "2020-03-04T16:37:50Z",
"EndTime": "2020-03-11T18:13:42Z",
"ID": "8"
}
]
}
Human Readable Output
Investigations Info
| ID | StartTime | EndTime | InvestigationState | MachineID | ComputerDNSName | TriggeringAlertID |
|---|---|---|---|---|---|---|
| 10 | 2020-03-17T11:35:17Z | PendingApproval | 4899036531e374137f63289c3267bad772c13fef | desktop-s2455r8 | da637200417169017725_183736971 | |
| 9 | 2020-03-17T10:43:15Z | PendingApproval | f70f9fe6b29cd9511652434919c6530618f06606 | desktop-s2455r9 | da637200385941308230_1832866941 | |
| 8 | 2020-03-04T16:37:50Z | 2020-03-11T18:13:42Z | TerminatedBySystem | f70f9fe6b29cd9511652434919c6530618f06606 | desktop-s2455r9 | da637189366671550108_395377714 |
22. microsoft-atp-start-investigation
Starts an automated investigation on a machine.
Required Permissions
Alert.ReadWrite.All
Base Command
microsoft-atp-start-investigation
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | The ID of the machine. | Required |
| comment | The comment to associate with the action. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Investigation.ID | String | The ID of the investigation. |
| MicrosoftATP.Investigation.StartTime | Date | The date and time when the investigation was created. |
| MicrosoftATP.Investigation.EndTime | Date | The date and time when the investigation was completed. |
| MicrosoftATP.Investigation.State | String | The state of the investigation. |
| MicrosoftATP.Investigation.CancelledBy | Unknown | The ID of the user or application that cancelled that investigation. |
| MicrosoftATP.Investigation.StatusDetails | Unknown | The details of the state of the investigation. |
| MicrosoftATP.Investigation.MachineID | String | The machine ID the investigation is executed on. |
| MicrosoftATP.Investigation.ComputerDNSName | String | The machine DNS name the investigation is executed on. |
| MicrosoftATP.Investigation.TriggeringAlertID | String | The alert ID that triggered the investigation. |
Command Example
!microsoft-atp-start-investigation comment="testing" machine_id=f70f9fe6b29cd9511652434919c6530618f06606
Context Example
{
"MicrosoftATP.Investigation": {
"CancelledBy": null,
"InvestigationState": "PendingApproval",
"MachineID": null,
"TriggeringAlertID": "da637205548921456173_375980286",
"ComputerDNSName": null,
"StatusDetails": null,
"StartTime": null,
"EndTime": null,
"ID": "da637205548921456173_375980286"
}
}
Human Readable Output
Starting investigation da637205548921456173_375980286 on f70f9fe6b29cd9511652434919c6530618f06606 machine
| ID | InvestigationState | TriggeringAlertID |
|---|---|---|
| da637205548921456173_375980286 | PendingApproval | da637205548921456173_375980286 |
23. microsoft-atp-get-domain-statistics
Retrieves statistics on the given domain.
Required Permissions
URL.Read.All
Base Command
microsoft-atp-get-domain-statistics
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | The domain address. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.DomainStatistics.Statistics.Host | String | The domain host. |
| MicrosoftATP.DomainStatistics.Statistics.OrgPrevalence | String | The prevalence of the domain in the organization. |
| MicrosoftATP.DomainStatistics.Statistics.OrgFirstSeen | Date | The first date and time the domain was seen in the organization. |
| MicrosoftATP.DomainStatistics.Statistics.OrgLastSeen | Date | The last date and time the domain was seen in the organization. |
Command Example
!microsoft-atp-get-domain-statistics domain=google.com
Context Example
{
"MicrosoftATP.DomainStatistics": {
"Domain": "google.com",
"Statistics": {
"OrgLastSeen": "2020-02-24T13:14:54Z",
"Host": "google.com",
"OrgFirstSeen": "2020-02-24T12:50:04Z",
"OrgPrevalence": "1"
}
}
}
Human Readable Output
Statistics on google.com domain
| Host | OrgFirstSeen | OrgLastSeen | OrgPrevalence |
|---|---|---|---|
| google.com | 2020-02-24T12:50:04Z | 2020-02-24T13:14:54Z | 1 |
24. microsoft-atp-get-domain-alerts (Deprecated)
This command has been deprecated. No available replacement
Retrieves a collection of alerts related to a given domain address.
Required Permissions
Alert.ReadWrite.All
Base Command
microsoft-atp-get-domain-alerts
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | The domain address. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.DomainAlert.Domain | String | The domain address. |
| MicrosoftATP.DomainAlert.Alerts.ID | String | The ID of the alert. |
| MicrosoftATP.DomainAlert.Alerts.IncidentID | Number | The incident ID of the alert. |
| MicrosoftATP.DomainAlert.Alerts.InvestigationID | Number | The investigation ID related to the alert. |
| MicrosoftATP.DomainAlert.Alerts.InvestigationState | String | The current state of the investigation. |
| MicrosoftATP.DomainAlert.Alerts.AssignedTo | String | The owner of the alert. |
| MicrosoftATP.DomainAlert.Alerts.Severity | String | The severity of the alert. |
| MicrosoftATP.DomainAlert.Alerts.Status | String | The current status of the alert. |
| MicrosoftATP.DomainAlert.Alerts.Classification | String | The alert classification. |
| MicrosoftATP.DomainAlert.Alerts.Determination | String | The determination of the alert. |
| MicrosoftATP.DomainAlert.Alerts.DetectionSource | String | The detection source. |
| MicrosoftATP.DomainAlert.Alerts.Category | String | The category of the alert. |
| MicrosoftATP.DomainAlert.Alerts.ThreatFamilyName | String | The family name of the threat. |
| MicrosoftATP.DomainAlert.Alerts.Title | String | The title of the alert. |
| MicrosoftATP.DomainAlert.Alerts.Description | String | The description of the alert. |
| MicrosoftATP.DomainAlert.Alerts.AlertCreationTime | Date | The date and time the alert was created. |
| MicrosoftATP.DomainAlert.Alerts.FirstEventTime | Date | The first event time that triggered the alert on that machine. |
| MicrosoftATP.DomainAlert.Alerts.LastEventTime | Date | The last event time that triggered the alert on that machine. |
| MicrosoftATP.DomainAlert.Alerts.LastUpdateTime | Date | The UTC time of the last update. |
| MicrosoftATP.DomainAlert.Alerts.ResolvedTime | Date | The date and time in which the status of the alert was changed to “Resolved”. |
| MicrosoftATP.DomainAlert.Alerts.MachineID | String | The machine ID that is associated with the alert. |
| MicrosoftATP.DomainAlert.Alerts.ComputerDNSName | String | The machine DNS name. |
| MicrosoftATP.DomainAlert.Alerts.AADTenantID | String | The AAD tenant ID. |
| MicrosoftATP.DomainAlert.Alerts.Comments.Comment | String | The alert comment string. |
| MicrosoftATP.DomainAlert.Alerts.Comments.CreatedBy | String | The alert comment created by the string. |
| MicrosoftATP.DomainAlert.Alerts.Comments.CreatedTime | Date | The alert comment create time and date. |
Command Example
!microsoft-atp-get-domain-alerts domain=google.com
Context Example
{
"MicrosoftATP.DomainAlert": {
"Domain": "google.com",
"Alerts": []
}
}
Human Readable Output
Domain google.com related alerts Info
No entries.
25. microsoft-atp-get-domain-machines
Retrieves a collection of machines that have communicated with a given domain address.
Required Permissions
Machine.ReadWrite.All
Base Command
microsoft-atp-get-domain-machines
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | The domain address. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.DomainMachine.Domain | String | The domain address. |
| MicrosoftATP.DomainMachine.Machines.ID | String | The ID of the machine. |
| MicrosoftATP.DomainMachine.Machines.ComputerDNSName | String | The DNS name of the machine. |
| MicrosoftATP.DomainMachine.Machines.FirstSeen | Date | The first date and time when the machine was observed by Microsoft Defender ATP. |
| MicrosoftATP.DomainMachine.Machines.LastSeen | Date | The last date and time where the machine was observed by Microsoft Defender ATP. |
| MicrosoftATP.DomainMachine.Machines.OSPlatform | String | The operating system platform. |
| MicrosoftATP.DomainMachine.Machines.OSVersion | String | The operating system version. |
| MicrosoftATP.DomainMachine.Machines.OSProcessor | String | The operating system processor. |
| MicrosoftATP.DomainMachine.Machines.LastIPAddress | String | The last IP address on the machine. |
| MicrosoftATP.DomainMachine.Machines.LastExternalIPAddress | String | The last IP address the machine accessed. |
| MicrosoftATP.DomainMachine.Machines.OSBuild | Number | The operating system build number. |
| MicrosoftATP.DomainMachine.Machines.HealthStatus | String | The health status of the machine. |
| MicrosoftATP.DomainMachine.Machines.RBACGroupID | Number | The RBAC group ID of the machine. |
| MicrosoftATP.DomainMachine.Machines.RBACGroupName | String | The RBAC group name of the machine. |
| MicrosoftATP.DomainMachine.Machines.RiskScore | String | The risk score of the machine. |
| MicrosoftATP.DomainMachine.Machines.ExposureLevel | String | The exposure level of the machine. |
| MicrosoftATP.DomainMachine.Machines.IsAADJoined | Boolean | Whether the machine is AAD joined. |
| MicrosoftATP.DomainMachine.Machines.AADDeviceID | String | The AAD device ID. |
| MicrosoftATP.DomainMachine.Machines.MachineTags | String | The set of machine tags. |
Command Example
!microsoft-atp-get-domain-machines domain=google.com
Context Example
{
"MicrosoftATP.DomainMachine": {
"Domain": "google.com",
"Machines": [
{
"OSBuild": 18363,
"ExposureLevel": "Medium",
"OSPlatform": "Windows10",
"MachineTags": [
"test Tag 2",
"test Tag 5"
],
"AADDeviceID": "cfcf4177-227e-4cdb-ac8e-f9a3da1ca30c",
"ComputerDNSName": "desktop-s2455r8",
"RBACGroupID": 0,
"OSProcessor": "x64",
"HealthStatus": "Active",
"AgentVersion": "10.6940.18362.693",
"LastExternalIPAddress": "81.166.99.236",
"LastIPAddress": "192.168.1.71",
"OSVersion": "1909",
"RiskScore": "High",
"ID": "4899036531e374137f63289c3267bad772c13fef",
"FirstSeen": "2020-02-17T08:30:07.2415577Z",
"LastSeen": "2020-03-23T08:10:41.473428Z"
}
]
}
}
Human Readable Output
Machines that have communicated with google.com domain
| ID | ComputerDNSName | OSPlatform | LastIPAddress | LastExternalIPAddress | HealthStatus | RiskScore | ExposureLevel |
|---|---|---|---|---|---|---|---|
| 4899036531e374137f63289c3267bad772c13fef | desktop-s2455r8 | Windows10 | 192.168.1.71 | 81.166.99.236 | Active | High | Medium |
26. microsoft-atp-get-file-statistics
Retrieves statistics for the given file.
Required Permissions
File.Read.All
Base Command
microsoft-atp-get-file-statistics
Input
| Argument Name | Description | Required |
|---|---|---|
| file_hash | The file SHA1 hash to get statistics on. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.FileStatistics.Sha1 | String | The file SHA1 hash. |
| MicrosoftATP.FileStatistics.Statistics.OrgPrevalence | String | The number of times the file is detected in the organization. |
| MicrosoftATP.FileStatistics.Statistics.OrganizationPrevalence | Number | The number of times the file is detected in the organization. |
| MicrosoftATP.FileStatistics.Statistics.OrgFirstSeen | Date | The first date and time the file was seen in the organization. |
| MicrosoftATP.FileStatistics.Statistics.OrgLastSeen | Date | The last date and time the file was seen in the organization. |
| MicrosoftATP.FileStatistics.Statistics.GlobalPrevalence | String | The number of times the file is detected across all organizations by Microsoft Defender ATP. |
| MicrosoftATP.FileStatistics.Statistics.GloballyPrevalence | Number | The number of times the file is detected across all organizations by Microsoft Defender ATP. |
| MicrosoftATP.FileStatistics.Statistics.GlobalFirstObserved | Date | The first global observation date and time of the file. |
| MicrosoftATP.FileStatistics.Statistics.GlobalLastObserved | Date | The last global observation date and time of the file. |
| MicrosoftATP.FileStatistics.Statistics.TopFileNames | String | The top names of the file. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.OrganizationPrevalence | Number | The number of times the indicator is detected in the organization. |
| File.GlobalPrevalence | Number | The number of times the indicator is detected across all organizations by Microsoft Defender ATP. |
| File.OrganizationFirstSeen | Date | The date and time when the indicator was first seen in the organization. |
| File.OrganizationLastSeen | Date | The date and time when the indicator was last seen in the organization. |
| File.FirstSeenBySource | Date | The date and time when the indicator was first seen by Microsoft Defender ATP. |
| File.LastSeenBySource | Date | The date and time when the indicator was last seen by Microsoft Defender ATP. |
Command Example
!microsoft-atp-get-file-statistics file_hash=9fe3ba25e5660c23dfe478d577cfacde5795870c
Context Example
{
"File": {
"SHA1": "9fe3ba25e5660c23dfe478d577cfacde5795870c",
"FirstSeenBySource": "2019-04-03T04:10:18.1001071Z",
"LastSeenBySource": "2020-03-23T09:24:54.169574Z",
"GlobalPrevalence": 1355899,
"Hashes":[
{
"type" :"SHA1",
"value": "9fe3ba25e5660c23dfe478d577cfacde5795870c"
}
],
"OrganizationPrevalence": 0
},
"MicrosoftATP": {
"FileStatistics": {
"Sha1": "9fe3ba25e5660c23dfe478d577cfacde5795870c",
"Statistics": {
"TopFileNames": [
"lsass.exe"
],
"GlobalFirstObserved": "2019-04-03T04:10:18.1001071Z",
"GlobalPrevalence": "1355899",
"GloballyPrevalence": 1355899,
"OrgPrevalence": "0",
"OrganizationPrevalence": 0,
"GlobalLastObserved": "2020-03-23T09:24:54.169574Z"
}
}
}
}
Human Readable Output
Statistics on 9fe3ba25e5660c23dfe478d577cfacde5795870c file
| Global First Observed | Global Last Observed | Global Prevalence | Organization Prevalence | Top File Names |
|---|---|---|---|---|
| 2019-04-03T04:10:18.1001071Z | 2020-03-23T09:24:54.169574Z | 1355899 | 0 | lsass.exe |
File Indicator Example
| Type | Value | Verdict | Related Incidents | Expiration | Global Prevalence | Organization Prevalence | First Seen By Source | Last Seen By Source | Organization First Seen | Organization Last Seen |
|---|---|---|---|---|---|---|---|---|---|---|
| File | 50ef7c645fd5cbb95d50fbaddf6213800f9296ec | Benign | 2 | Never | 195803 | 0 | April 03, 2019 4:10 AM | March 23, 2020 9:24 AM | N/A | N/A |
27. microsoft-atp-get-file-alerts (Deprecated)
This command has been deprecated. No available replacement.
Retrieves a collection of alerts related to a given file hash.
Required Permissions
Alert.ReadWrite.All
Base Command
microsoft-atp-get-file-alerts
Input
| Argument Name | Description | Required |
|---|---|---|
| file_hash | The file SHA1 hash to get statistics on. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.FileAlert.Sha1 | String | The file SHA1 hash. |
| MicrosoftATP.FileAlert.Alerts.ID | String | The ID of the alert. |
| MicrosoftATP.FileAlert.Alerts.IncidentID | Number | The incident ID of the alert. |
| MicrosoftATP.FileAlert.Alerts.InvestigationID | Number | The investigation ID related to the alert. |
| MicrosoftATP.FileAlert.Alerts.InvestigationState | String | The current state of the investigation. |
| MicrosoftATP.FileAlert.Alerts.AssignedTo | String | The owner of the alert. |
| MicrosoftATP.FileAlert.Alerts.Severity | String | The severity of the alert. |
| MicrosoftATP.FileAlert.Alerts.Status | String | The current status of the alert. |
| MicrosoftATP.FileAlert.Alerts.Classification | String | The alert classification. |
| MicrosoftATP.FileAlert.Alerts.Determination | String | The determination of the alert. |
| MicrosoftATP.FileAlert.Alerts.DetectionSource | String | The detection source. |
| MicrosoftATP.FileAlert.Alerts.Category | String | The category of the alert. |
| MicrosoftATP.FileAlert.Alerts.ThreatFamilyName | String | The family name of the threat. |
| MicrosoftATP.FileAlert.Alerts.Title | String | The title of the alert. |
| MicrosoftATP.FileAlert.Alerts.Description | String | The description of the alert. |
| MicrosoftATP.FileAlert.Alerts.AlertCreationTime | Date | The date and time the alert was created. |
| MicrosoftATP.FileAlert.Alerts.FirstEventTime | Date | The first event time that triggered the alert on that machine. |
| MicrosoftATP.FileAlert.Alerts.LastEventTime | Date | The last event time that triggered the alert on that machine. |
| MicrosoftATP.FileAlert.Alerts.LastUpdateTime | Date | The UTC time of the last update. |
| MicrosoftATP.FileAlert.Alerts.ResolvedTime | Date | The date and time in which the status of the alert was changed to “Resolved”. |
| MicrosoftATP.FileAlert.Alerts.MachineID | String | The machine ID that is associated with the alert. |
| MicrosoftATP.FileAlert.Alerts.ComputerDNSName | String | The DNS name of the machine. |
| MicrosoftATP.FileAlert.Alerts.AADTenantID | String | The AAD tenant ID. |
| MicrosoftATP.FileAlert.Alerts.Comments.Comment | String | The alert comment string. |
| MicrosoftATP.FileAlert.Alerts.Comments.CreatedBy | String | The alert comment created by the string. |
| MicrosoftATP.FileAlert.Alerts.Comments.CreatedTime | Date | The time and date the alert comment was created. |
Command Example
!microsoft-atp-get-file-alerts file_hash=9fe3ba25e5660c23dfe478d577cfacde5795870c
Context Example
{
"MicrosoftATP.FileAlert": {
"Sha1": "9fe3ba25e5660c23dfe478d577cfacde5795870c",
"Alerts": [
{
"Category": "None",
"ThreatFamilyName": null,
"Severity": "Medium",
"LastEventTime": "2020-03-15T13:59:14.2438912Z",
"FirstEventTime": "2020-03-15T13:59:14.2438912Z",
"Comments": [
{
"Comment": null,
"CreatedTime": null,
"CreatedBy": null
}
],
"AADTenantID": "TENANT-ID",
"AlertCreationTime": "2020-03-17T11:55:31.890247Z",
"Status": "New",
"Description": "Created for test",
"InvestigationState": "PendingApproval",
"MachineID": "4899036531e374137f63289c3267bad772c13fef",
"Title": "test alert",
"InvestigationID": 10,
"Determination": null,
"IncidentID": 15,
"AssignedTo": null,
"DetectionSource": "CustomerTI",
"ResolvedTime": null,
"ID": "da637200429318902470_-1583197054",
"LastUpdateTime": "2020-03-17T11:55:33.0233333Z",
"Classification": null,
"ComputerDNSName": "desktop-s2455r8",
"Evidence": [
{
"userPrincipalName": null,
"processId": 656,
"sha1": "9fe3ba25e5660c23dfe478d577cfacde5795870c",
"parentProcessCreationTime": null,
"domainName": null,
"url": null,
"processCommandLine": "lsass.exe",
"entityType": "Process",
"processCreationTime": "2020-03-13T16:58:59Z",
"aadUserId": null,
"fileName": "lsass.exe",
"sha256": null,
"parentProcessId": 512,
"userSid": null,
"filePath": "c:\\windows\\system32\\lsass.exe",
"accountName": null,
"ipAddress": null
}
]
}
]
}
}
Human Readable Output
File 9fe3ba25e5660c23dfe478d577cfacde5795870c related alerts Info
| ID | Title | Description | IncidentID | Severity | Status | Category | MachineID |
|---|---|---|---|---|---|---|---|
| da637200429318902470_-1583197054 | test alert | Created for test | 15 | Medium | New | None | 4899036531e374137f63289c3267bad772c13fef |
28. microsoft-atp-get-ip-statistics
Retrieves statistics for the given IP address.
Required Permissions
Ip.Read.All
Base Command
microsoft-atp-get-ip-statistics
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | The IP address. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.IPStatistics.Statistics.IPAddress | String | The IP address. |
| MicrosoftATP.IPStatistics.Statistics.OrgPrevalence | String | The prevalence of the IP address in the organization. |
| MicrosoftATP.IPStatistics.Statistics.OrgFirstSeen | Date | The first date and time the IP address was seen in the organization. |
| MicrosoftATP.IPStatistics.Statistics.OrgLastSeen | Date | The last date and time the IP address was seen in the organization. |
Command Example
!microsoft-atp-get-ip-statistics ip=8.8.8.8
Context Example
{
"MicrosoftATP.IPStatistics": {
"Statistics": {
"OrgLastSeen": "2020-03-01T15:19:40Z",
"OrgPrevalence": "1",
"OrgFirstSeen": "2020-02-22T12:52:35Z"
},
"IPAddress": "8.8.8.8"
}
}
Human Readable Output
Statistics on 8.8.8.8 IP
| OrgFirstSeen | OrgLastSeen | OrgPrevalence |
|---|---|---|
| 2020-02-22T12:52:35Z | 2020-03-01T15:19:40Z | 1 |
29. microsoft-atp-get-ip-alerts (Deprecated)
This command has been deprecated. No available replacement.
Retrieves a collection of alerts related to a given IP address.
Required Permissions
Alert.ReadWrite.All
Base Command
microsoft-atp-get-ip-alerts
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | The Ip address. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.IPAlert.IPAddress | String | The IP address. |
| MicrosoftATP.IPAlert.Alerts.ID | String | The alert ID. |
| MicrosoftATP.IPAlert.Alerts.IncidentID | Number | The incident ID of the alert. |
| MicrosoftATP.IPAlert.Alerts.InvestigationID | Number | The investigation ID related to the alert. |
| MicrosoftATP.IPAlert.Alerts.InvestigationState | String | The current state of the investigation. |
| MicrosoftATP.IPAlert.Alerts.AssignedTo | String | The owner of the alert. |
| MicrosoftATP.IPAlert.Alerts.Severity | String | The severity of the alert. |
| MicrosoftATP.IPAlert.Alerts.Status | String | The current status of the alert. |
| MicrosoftATP.IPAlert.Alerts.Classification | String | The alert classification. |
| MicrosoftATP.IPAlert.Alerts.Determination | String | The determination of the alert. |
| MicrosoftATP.IPAlert.Alerts.DetectionSource | String | The detection source. |
| MicrosoftATP.IPAlert.Alerts.Category | String | The category of the alert. |
| MicrosoftATP.IPAlert.Alerts.ThreatFamilyName | String | The family name of the threat. |
| MicrosoftATP.IPAlert.Alerts.Title | String | The title of the alert. |
| MicrosoftATP.IPAlert.Alerts.Description | String | The description of the alert. |
| MicrosoftATP.IPAlert.Alerts.AlertCreationTime | Date | The date and time the alert was created. |
| MicrosoftATP.IPAlert.Alerts.FirstEventTime | Date | The first event time that triggered the alert on that machine. |
| MicrosoftATP.IPAlert.Alerts.LastEventTime | Date | The last event time that triggered the alert on that machine. |
| MicrosoftATP.IPAlert.Alerts.LastUpdateTime | Date | The UTC time of the last update. |
| MicrosoftATP.IPAlert.Alerts.ResolvedTime | Date | The date and time in which the status of the alert was changed to “Resolved”. |
| MicrosoftATP.IPAlert.Alerts.MachineID | String | The machine ID that is associated with the alert. |
| MicrosoftATP.IPAlert.Alerts.ComputerDNSName | String | The DNS name of the machine. |
| MicrosoftATP.IPAlert.Alerts.AADTenantID | String | The AAD tenant ID. |
| MicrosoftATP.IPAlert.Alerts.Comments.Comment | String | The alert’s comment string. |
| MicrosoftATP.IPAlert.Alerts.Comments.CreatedBy | String | The alert comment created by the string. |
| MicrosoftATP.IPAlert.Alerts.Comments.CreatedTime | Date | The time and date the alert comment was created. |
Command Example
!microsoft-atp-get-ip-alerts ip=8.8.8.8
Context Example
{
"MicrosoftATP.IPAlert": {
"Alerts": [],
"IPAddress": "8.8.8.8"
}
}
Human Readable Output
IP 8.8.8.8 related alerts Info
No entries.
30. microsoft-atp-get-user-alerts (Deprecated)
This command has been deprecated. No available replacement.
Retrieves a collection of alerts related to a given user ID.
Required Permissions
Alert.ReadWrite.All
Base Command
microsoft-atp-get-user-alerts
Input
| Argument Name | Description | Required |
|---|---|---|
| username | The user ID. The ID is not the full UPN, but only the username. For example, to retrieve alerts for “user1@test.com” use “user1”. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.UserAlert.Username | String | The name of the user. |
| MicrosoftATP.UserAlert.Alerts.ID | String | The ID of the alert. |
| MicrosoftATP.UserAlert.Alerts.IncidentID | Number | The incident ID of the alert. |
| MicrosoftATP.UserAlert.Alerts.InvestigationID | Number | The investigation ID related to the alert. |
| MicrosoftATP.UserAlert.Alerts.InvestigationState | String | The current state of the investigation. |
| MicrosoftATP.UserAlert.Alerts.AssignedTo | String | The owner of the alert. |
| MicrosoftATP.UserAlert.Alerts.Severity | String | The severity of the alert. |
| MicrosoftATP.UserAlert.Alerts.Status | String | The current status of the alert. |
| MicrosoftATP.UserAlert.Alerts.Classification | String | The alert classification. |
| MicrosoftATP.UserAlert.Alerts.Determination | String | The determination of the alert. |
| MicrosoftATP.UserAlert.Alerts.DetectionSource | String | The detection source. |
| MicrosoftATP.UserAlert.Alerts.Category | String | The category of the alert. |
| MicrosoftATP.UserAlert.Alerts.ThreatFamilyName | String | The family name of the threat. |
| MicrosoftATP.UserAlert.Alerts.Title | String | The title of the alert. |
| MicrosoftATP.UserAlert.Alerts.Description | String | The description of the alert. |
| MicrosoftATP.UserAlert.Alerts.AlertCreationTime | Date | The date and time the alert was created. |
| MicrosoftATP.UserAlert.Alerts.FirstEventTime | Date | The first event time that triggered the alert on that machine. |
| MicrosoftATP.UserAlert.Alerts.LastEventTime | Date | The last event time that triggered the alert on that machine. |
| MicrosoftATP.UserAlert.Alerts.LastUpdateTime | Date | The UTC time of the last update. |
| MicrosoftATP.UserAlert.Alerts.ResolvedTime | Date | The date and time when the status of the alert was changed to “Resolved”. |
| MicrosoftATP.UserAlert.Alerts.MachineID | String | The machine ID that is associated with the alert. |
| MicrosoftATP.UserAlert.Alerts.ComputerDNSName | String | The DNS name of the machine. |
| MicrosoftATP.UserAlert.Alerts.AADTenantID | String | The AAD tenant ID. |
| MicrosoftATP.UserAlert.Alerts.Comments.Comment | String | The comment string of the alert. |
| MicrosoftATP.UserAlert.Alerts.Comments.CreatedBy | String | The alert comment created by the string. |
| MicrosoftATP.UserAlert.Alerts.Comments.CreatedTime | Date | The time and date the alert comment was created. |
Command Example
!microsoft-atp-get-user-alerts username=demisto
Context Example
{
"MicrosoftATP.UserAlert": {
"Username": "demisto",
"Alerts": [
{
"Category": "DefenseEvasion",
"ThreatFamilyName": null,
"Severity": "Medium",
"LastEventTime": "2020-02-17T11:39:09.9948632Z",
"FirstEventTime": "2020-02-17T11:37:11.4901408Z",
"Comments": [
{
"Comment": null,
"CreatedTime": null,
"CreatedBy": null
}
],
"AADTenantID": "TENANT-ID",
"AlertCreationTime": "2020-02-17T11:40:33.5724218Z",
"Status": "InProgress",
"Description": "A process abnormally injected code into another process, As a result, unexpected code may be running in the target process memory. Injection is often used to hide malicious code execution within a trusted process. \nAs a result, the target process may exhibit abnormal behaviors such as opening a listening port or connecting to a command and control server.",
"InvestigationState": "Benign",
"MachineID": "4899036531e374137f63289c3267bad772c13fef",
"Title": "Suspicious process injection observed",
"InvestigationID": 1,
"Determination": null,
"IncidentID": 7,
"AssignedTo": "Automation",
"DetectionSource": "WindowsDefenderAtp",
"ResolvedTime": null,
"ID": "da637175364336494657_410871946",
"LastUpdateTime": "2020-03-17T11:29:55.0066667Z",
"Classification": null,
"ComputerDNSName": "desktop-s2455r8",
"Evidence": [
{
"userPrincipalName": null,
"processId": 11192,
"sha1": "36c5d12033b2eaf251bae61c00690ffb17fddc87",
"parentProcessCreationTime": "2020-02-17T08:03:34.9841426Z",
"domainName": null,
"url": null,
"processCommandLine": "\"powershell.exe\" ",
"entityType": "Process",
"processCreationTime": "2020-02-17T12:38:47.6521977Z",
"aadUserId": null,
"fileName": "powershell.exe",
"sha256": "908b64b1971a979c7e3e8ce4621945cba84854cb98d76367b791a6e22b5f6d53",
"parentProcessId": 9008,
"userSid": null,
"filePath": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0",
"accountName": null,
"ipAddress": null
},
{
"userPrincipalName": null,
"processId": 12508,
"sha1": "d487580502354c61808c7180d1a336beb7ad4624",
"parentProcessCreationTime": "2020-02-17T12:38:47.6521977Z",
"domainName": null,
"url": null,
"processCommandLine": "\"notepad.exe\"",
"entityType": "Process",
"processCreationTime": "2020-02-17T12:41:04.9040946Z",
"aadUserId": null,
"fileName": "notepad.exe",
"sha256": "f1d62648ef915d85cb4fc140359e925395d315c70f3566b63bb3e21151cb2ce3",
"parentProcessId": 11192,
"userSid": null,
"filePath": "C:\\Windows\\System32",
"accountName": null,
"ipAddress": null
},
{
"userPrincipalName": null,
"processId": null,
"sha1": null,
"parentProcessCreationTime": null,
"domainName": "DESKTOP-S2455R8",
"url": null,
"processCommandLine": null,
"entityType": "User",
"processCreationTime": null,
"aadUserId": null,
"fileName": null,
"sha256": null,
"parentProcessId": null,
"userSid": "S-1-5-21-4197691174-1403503641-4006700887-1001",
"filePath": null,
"accountName": "demisto",
"ipAddress": null
},
{
"userPrincipalName": null,
"processId": 8936,
"sha1": "d487580502354c61808c7180d1a336beb7ad4624",
"parentProcessCreationTime": "2020-02-17T12:38:47.6521977Z",
"domainName": null,
"url": null,
"processCommandLine": "\"notepad.exe\"",
"entityType": "Process",
"processCreationTime": "2020-02-17T12:39:16.3783602Z",
"aadUserId": null,
"fileName": "notepad.exe",
"sha256": "f1d62648ef915d85cb4fc140359e925395d315c70f3566b63bb3e21151cb2ce3",
"parentProcessId": 11192,
"userSid": null,
"filePath": "C:\\Windows\\System32",
"accountName": null,
"ipAddress": null
}
]
}
]
}
]
}
}
Human Readable Output
User XSOAR related alerts Info
| ID | Title | Description | IncidentID | Severity | Status | Category | MachineID |
|---|---|---|---|---|---|---|---|
| da637175364336494657_410871946 | Suspicious process injection observed | A process abnormally injected code into another process, As a result, unexpected code may be running in the target process memory. Injection is often used to hide malicious code execution within a trusted process. As a result, the target process may exhibit abnormal behaviors such as opening a listening port or connecting to a command and control server. | 7 | Medium | InProgress | DefenseEvasion | 4899036531e374137f63289c3267bad772c13fef |
31. microsoft-atp-get-user-machines
Retrieves a collection of machines related to a given user ID.
Required Permissions
Machine.ReadWrite.All
Base Command
microsoft-atp-get-user-machines
Input
| Argument Name | Description | Required |
|---|---|---|
| username | The user ID. The ID is not the full UPN, but only the user name. For example, to retrieve machines for “user1@test.com” use “user1”. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.UserMachine.Username | String | The name of the user. |
| MicrosoftATP.UserMachine.Machines.ID | String | The ID of the machine. |
| MicrosoftATP.UserMachine.Machines.ComputerDNSName | String | The DNS name of the machine. |
| MicrosoftATP.UserMachine.Machines.FirstSeen | Date | The first date and time where the machine was observed by Microsoft Defender ATP. |
| MicrosoftATP.UserMachine.Machines.LastSeen | Date | The last date and time where the machine was observed by Microsoft Defender ATP. |
| MicrosoftATP.UserMachine.Machines.OSPlatform | String | The operating system platform. |
| MicrosoftATP.UserMachine.Machines.OSVersion | String | The operating system version. |
| MicrosoftATP.UserMachine.Machines.OSProcessor | String | The operating system processor. |
| MicrosoftATP.v.Machines.LastIPAddress | String | The last IP address on the machine. |
| MicrosoftATP.UserMachine.Machines.LastExternalIPAddress | String | The last IP address through which the machine accessed the internet. |
| MicrosoftATP.UserMachine.Machines.OSBuild | Number | The operating system build number. |
| MicrosoftATP.UserMachine.Machines.HealthStatus | String | The health status of the machine. |
| MicrosoftATP.UserMachine.Machines.RBACGroupID | Number | The RBAC group ID of the machine. |
| MicrosoftATP.UserMachine.Machines.RBACGroupName | String | The RBAC group name of the machine. |
| MicrosoftATP.UserMachine.Machines.RiskScore | String | The risk score of the machine. |
| MicrosoftATP.UserMachine.Machines.ExposureLevel | String | The exposure level of the machine. |
| MicrosoftATP.UserMachine.Machines.IsAADJoined | Boolean | Whether the machine is AAD joined. |
| MicrosoftATP.UserMachine.Machines.AADDeviceID | String | The AAD device ID. |
| MicrosoftATP.UserMachine.Machines.MachineTags | String | The set of machine tags. |
Command Example
!microsoft-atp-get-user-machines username=demisto
Context Example
{
"MicrosoftATP.UserMachine": {
"Username": "demisto",
"Machines": [
{
"OSBuild": 18363,
"ExposureLevel": "Medium",
"OSPlatform": "Windows10",
"MachineTags": [
"test Tag 2",
"test Tag 5"
],
"AADDeviceID": "cfcf4177-227e-4cdb-ac8e-f9a3da1ca30c",
"ComputerDNSName": "desktop-s2455r8",
"RBACGroupID": 0,
"OSProcessor": "x64",
"HealthStatus": "Active",
"AgentVersion": "10.6940.18362.693",
"LastExternalIPAddress": "81.166.99.236",
"LastIPAddress": "192.168.1.71",
"OSVersion": "1909",
"RiskScore": "High",
"ID": "4899036531e374137f63289c3267bad772c13fef",
"FirstSeen": "2020-02-17T08:30:07.2415577Z",
"LastSeen": "2020-03-23T08:10:41.473428Z"
},
{
"OSBuild": 18363,
"ExposureLevel": "Medium",
"OSPlatform": "Windows10",
"MachineTags": [
"test add tag",
"testing123"
],
"ComputerDNSName": "desktop-s2455r9",
"RBACGroupID": 0,
"OSProcessor": "x64",
"HealthStatus": "Active",
"AgentVersion": "10.6940.18362.693",
"LastExternalIPAddress": "81.166.99.236",
"LastIPAddress": "192.168.1.73",
"OSVersion": "1909",
"RiskScore": "Medium",
"ID": "f70f9fe6b29cd9511652434919c6530618f06606",
"FirstSeen": "2020-02-20T14:44:11.4627779Z",
"LastSeen": "2020-03-23T07:55:50.9986715Z"
}
]
}
}
Human Readable Output
Machines that are related to user XSOAR
| ID | ComputerDNSName | OSPlatform | LastIPAddress | LastExternalIPAddress | HealthStatus | RiskScore | ExposureLevel |
|---|---|---|---|---|---|---|---|
| 4899036531e374137f63289c3267bad772c13fef | desktop-s2455r8 | Windows10 | 192.168.1.71 | 81.166.99.236 | Active | High | Medium |
| f70f9fe6b29cd9511652434919c6530618f06606 | desktop-s2455r9 | Windows10 | 192.168.1.73 | 81.166.99.236 | Active | Medium | Medium |
32. microsoft-atp-add-remove-machine-tag
Adds or removes a tag on a specific machine.
Required Permissions
Machine.ReadWrite.All
Base Command
microsoft-atp-add-remove-machine-tag
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | The ID of the machine. | Required |
| action | The action to use for the tag. | Required |
| tag | The name of the tag. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Machine.ID | String | The ID of the machine. |
| MicrosoftATP.Machine.ComputerDNSName | String | The DNS name of the machine. |
| MicrosoftATP.Machine.FirstSeen | Date | The first date and time where the machine was observed by Microsoft Defender ATP. |
| MicrosoftATP.Machine.LastSeen | Date | The last date and time where the machine was observed by Microsoft Defender ATP. |
| MicrosoftATP.Machine.OSPlatform | String | The operating system platform. |
| MicrosoftATP.Machine.OSVersion | String | The operating system version. |
| MicrosoftATP.Machine.OSProcessor | String | The operating system processor. |
| MicrosoftATP.Machine.LastIPAddress | String | The last IP address on the machine. |
| MicrosoftATP.Machine.LastExternalIPAddress | String | The last IP address through which the machine accessed the internet. |
| MicrosoftATP.Machine.OSBuild | Number | The operating system build number. |
| MicrosoftATP.Machine.HealthStatus | String | The health status of the machine. |
| MicrosoftATP.Machine.RBACGroupID | Number | The RBAC group ID of the machine. |
| MicrosoftATP.Machine.RBACGroupName | String | The RBAC group name of the machine. |
| MicrosoftATP.Machine.RiskScore | String | The risk score of the machine. |
| MicrosoftATP.Machine.ExposureLevel | String | The exposure level of the machine. |
| MicrosoftATP.Machine.IsAADJoined | Boolean | Whether the machine is AAD joined. |
| MicrosoftATP.Machine.AADDeviceID | String | The AAD device ID. |
| MicrosoftATP.Machine.MachineTags | String | The set of machine tags. |
Command Example
!microsoft-atp-add-remove-machine-tag action=Add machine_id=f70f9fe6b29cd9511652434919c6530618f06606 tag="test add tag"
Context Example
{
"MicrosoftATP.Machine": {
"OSBuild": 18363,
"ExposureLevel": "Medium",
"OSPlatform": "Windows10",
"MachineTags": [
"test add tag",
"testing123"
],
"ComputerDNSName": "desktop-s2455r9",
"RBACGroupID": 0,
"OSProcessor": "x64",
"HealthStatus": "Active",
"AgentVersion": "10.6940.18362.693",
"LastExternalIPAddress": "81.166.99.236",
"LastIPAddress": "192.168.1.73",
"OSVersion": "1909",
"RiskScore": "Medium",
"ID": "f70f9fe6b29cd9511652434919c6530618f06606",
"FirstSeen": "2020-02-20T14:44:11.4627779Z",
"LastSeen": "2020-03-23T07:55:50.9986715Z"
}
}
Human Readable Output
Succeed to Add tag to f70f9fe6b29cd9511652434919c6530618f06606
| ID | ComputerDNSName | OSPlatform | LastExternalIPAddress | HealthStatus | RiskScore | ExposureLevel | MachineTags |
|---|---|---|---|---|---|---|---|
| f70f9fe6b29cd9511652434919c6530618f06606 | desktop-s2455r9 | Windows10 | 81.166.99.236 | Active | Medium | Medium | test add tag, testing123 |
microsoft-atp-indicator-list
Deprecated. Use the microsoft-atp-sc-indicator-list command instead. Lists all indicators by the ID that the system creates when the indicator is ingested.
Base Command
microsoft-atp-indicator-list
Input
| Argument Name | Description | Required |
|---|---|---|
| limit | The maximum number of indicators to return. Default is 50. | Optional |
| page_size | Specify the page size of the result set. Maximum is 200. Default value is 50. | Optional |
Context Output
| Path | Type | Description | |
|---|---|---|---|
| MicrosoftATP.Indicators.id | String | Created by the system when the indicator is ingested. Generated GUID/unique identifier. | |
| MicrosoftATP.Indicators.action | String | The action to apply if the indicator is matched from within the targetProduct security tool. Possible values are: unknown, allow, block, alert. | |
| MicrosoftATP.Indicators.additionalInformation | String | A catchall area into which extra data from the indicator not covered by the other indicator properties may be placed. Data placed into additionalInformation is typically not be used by the targetProduct security tool. | |
| MicrosoftATP.Indicators.azureTenantId | String | Stamped by the system when the indicator is ingested. The Entra ID tenant ID of submitting client. | |
| MicrosoftATP.Indicators.confidence | Number | An integer representing the confidence with which the data within the indicator accurately identifies malicious behavior. Possible values are 0 – 100, with 100 being the highest. | |
| MicrosoftATP.Indicators.description | String | Brief description (100 characters or less) of the threat represented by the indicator. | |
| MicrosoftATP.Indicators.diamondModel | String | The area of the Diamond Model in which this indicator exists. Possible values are: “unknown”, “adversary”, “capability”, “infrastructure”, “victim”. | |
| MicrosoftATP.Indicators.domainName | String | Domain name associated with this indicator. Should be in the format subdomain.domain.topleveldomain. | |
| MicrosoftATP.Indicators.emailEncoding | String | The type of text encoding used in the email. | |
| MicrosoftATP.Indicators.emailLanguage | String | The language of the email. | |
| MicrosoftATP.Indicators.emailRecipient | String | Recipient email address. | |
| MicrosoftATP.Indicators.emailSenderAddress | String | Email address of the attacker | victim. |
| MicrosoftATP.Indicators.emailSenderName | String | Display name of the attacker | victim.. |
| MicrosoftATP.Indicators.emailSourceDomain | String | Domain used in the email. | |
| MicrosoftATP.Indicators.emailSourceIpAddress | String | Source IP address of the email. | |
| MicrosoftATP.Indicators.emailSubject | String | Subject line of the email. | |
| MicrosoftATP.Indicators.emailXMailer | String | X-Mailer value used in the email. | |
| MicrosoftATP.Indicators.expirationDateTime | Date | DateTime string indicating when the indicator expires. To avoid stale indicators persisting in the system, all indicators must have an expiration date. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.externalId | String | An identification number that ties the indicator back to the indicator provider’s system (e.g. a foreign key). | |
| MicrosoftATP.Indicators.fileCompileDateTime | Date | DateTime when the file was compiled. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.fileCreatedDateTime | Date | DateTime when the file was created.The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.fileHashType | String | The type of hash stored in fileHashValue. Possible values are: “unknown”, “sha1”, “sha256”, “md5”, “authenticodeHash256”, “lsHash”, and “ctph”. | |
| MicrosoftATP.Indicators.fileHashValue | String | The file hash value. | |
| MicrosoftATP.Indicators.fileMutexName | String | Mutex name used in file-based detections. | |
| MicrosoftATP.Indicators.fileName | String | Name of the file if the indicator is file-based. Supports comma-separate list of file names. | |
| MicrosoftATP.Indicators.filePacker | String | The packer used to build the file in question. | |
| MicrosoftATP.Indicators.filePath | String | Path of the file indicating a compromise. May be a Windows or *nix style. | |
| MicrosoftATP.Indicators.fileSize | Number | Size of the file in bytes. | |
| MicrosoftATP.Indicators.fileType | String | Text description of the type of file. For example, “Word Document” or “Binary”. | |
| MicrosoftATP.Indicators.ingestedDateTime | Date | Stamped by the system when the indicator is ingested. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.isActive | Boolean | Used to deactivate indicators within system. By default, any indicator submitted is set as active. However, providers may submit existing indicators with this set to ‘False’ to deactivate indicators in the system. | |
| MicrosoftATP.Indicators.knownFalsePositives | String | Scenarios in which the indicator may cause false positives. This should be human-readable text. | |
| MicrosoftATP.Indicators.lastReportedDateTime | Date | The last time the indicator was seen. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.networkCidrBlock | String | CIDR Block notation representation of the network referenced in this indicator. Use only if the Source and Destination cannot be identified. | |
| MicrosoftATP.Indicators.networkDestinationAsn | Number | The destination autonomous system identifier of the network referenced in the indicator. | |
| MicrosoftATP.Indicators.networkDestinationCidrBlock | String | CIDR Block notation representation of the destination network in this indicator. | |
| MicrosoftATP.Indicators.networkDestinationIPv4 | String | IPv4 IP address destination. | |
| MicrosoftATP.Indicators.networkDestinationIPv6 | String | IPv6 IP address destination. | |
| MicrosoftATP.Indicators.networkDestinationPort | Number | TCP port destination. | |
| MicrosoftATP.Indicators.networkIPv4 | String | IPv4 IP address. | |
| MicrosoftATP.Indicators.networkIPv6 | String | IPv6 IP address. | |
| MicrosoftATP.Indicators.networkPort | Number | TCP port. | |
| MicrosoftATP.Indicators.networkProtocol | Number | Decimal representation of the protocol field in the IPv4 header. | |
| MicrosoftATP.Indicators.networkSourceAsn | Number | The source autonomous system identifier of the network referenced in the indicator. | |
| MicrosoftATP.Indicators.networkSourceCidrBlock | String | CIDR Block notation representation of the source network in this indicator. | |
| MicrosoftATP.Indicators.networkSourceIPv4 | String | IPv4 IP address source. | |
| MicrosoftATP.Indicators.networkSourceIPv6 | String | IPv6 IP address source. | |
| MicrosoftATP.Indicators.networkSourcePort | Number | TCP port source. | |
| MicrosoftATP.Indicators.passiveOnly | Boolean | Determines if the indicator should trigger an event that is visible to an end user. When set to ‘true,’ security tools will not notify the end user that a ‘hit’ has occurred. This is most often treated as audit or silent mode by security products where they will simply log that a match occurred but will not perform the action. Default value is false. | |
| MicrosoftATP.Indicators.severity | Number | Severity of the malicious behavior identified by the data within the indicator. Possible values are 0 – 5, where 5 is the most severe and zero is not severe at all. Default is 3 | |
| MicrosoftATP.Indicators.targetProduct | String | A string value representing a single security product to which the indicator should be applied. | |
| MicrosoftATP.Indicators.threatType | String | Each indicator must have a valid Indicator Threat Type. Possible values are: Botnet, C2, CryptoMining, Darknet, DDoS, MaliciousUrl, Malware, Phishing, Proxy, PUA, WatchList. | |
| MicrosoftATP.Indicators.tlpLevel | String | Traffic Light Protocol value for the indicator. Possible values are: unknown, white, green, amber, and red. | |
| MicrosoftATP.Indicators.url | String | Uniform Resource Locator. This URL complies with RFC 1738. | |
| MicrosoftATP.Indicators.userAgent | String | User-Agent string from a web request that could indicate compromise. | |
| MicrosoftATP.Indicators.vendorInformation | String | Information about the vendor. |
Command Example
#### Context Example
```json
{
"MicrosoftATP": {
"Indicators": {
"action": "block",
"activityGroupNames": [],
"azureTenantId": "TENANT-ID",
"description": "Title: Indicator Jacoviya.net of type DomainName, Description: Blob!",
"domainName": "jacoviya.net",
"expirationDateTime": "2020-09-02T17:08:46Z",
"id": "16",
"ingestedDateTime": "2020-08-26T17:08:49.158136Z",
"isActive": true,
"killChain": [],
"malwareFamilyNames": [],
"severity": 2,
"tags": [],
"targetProduct": "Microsoft Defender ATP"
}
}
}
Human Readable Output
Indicators from Microsoft ATP
id action severity domainName 16 block 2 jacoviya.net
microsoft-atp-indicator-get-by-id
Deprecated. Use the microsoft-atp-sc-indicator-get-by-id command instead. Gets an indicator by its ID.
Base Command
microsoft-atp-indicator-get-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| indicator_id | The ID of the indicator to get. | Required |
Context Output
| Path | Type | Description | |
|---|---|---|---|
| MicrosoftATP.Indicators.id | String | Created by the system when the indicator is ingested. Generated GUID/unique identifier. | |
| MicrosoftATP.Indicators.action | String | The action to apply if the indicator is matched from within the targetProduct security tool. Possible values are: unknown, allow, block, alert. | |
| MicrosoftATP.Indicators.additionalInformation | String | A catchall area into which extra data from the indicator not covered by the other indicator properties may be placed. Data placed into additionalInformation will typically not be used by the targetProduct security tool. | |
| MicrosoftATP.Indicators.azureTenantId | String | Timestamp when the indicator was ingested into the system. | |
| MicrosoftATP.Indicators.confidence | Number | An integer representing the confidence with which the data within the indicator accurately identifies malicious behavior. Possible values are 0 – 100, with 100 being the highest. | |
| MicrosoftATP.Indicators.description | String | Brief description (100 characters or less) of the threat represented by the indicator. | |
| MicrosoftATP.Indicators.diamondModel | String | The area of the Diamond Model in which this indicator exists. Possible values are: unknown, adversary, capability, infrastructure, victim. | |
| MicrosoftATP.Indicators.domainName | String | Domain name associated with this indicator. Should be in the format subdomain.domain.topleveldomain. | |
| MicrosoftATP.Indicators.emailEncoding | String | The type of text encoding used in the email. | |
| MicrosoftATP.Indicators.emailLanguage | String | The language of the email. | |
| MicrosoftATP.Indicators.emailRecipient | String | Recipient email address. | |
| MicrosoftATP.Indicators.emailSenderAddress | String | Email address of the attacker | victim. |
| MicrosoftATP.Indicators.emailSenderName | String | Display name of the attacker | victim.. |
| MicrosoftATP.Indicators.emailSourceDomain | String | Domain used in the email. | |
| MicrosoftATP.Indicators.emailSourceIpAddress | String | Source IP address of the email. | |
| MicrosoftATP.Indicators.emailSubject | String | Subject line of the email. | |
| MicrosoftATP.Indicators.emailXMailer | String | X-Mailer value used in the email. | |
| MicrosoftATP.Indicators.expirationDateTime | Date | DateTime string indicating when the indicator expires. To avoid stale indicators persisting in the system, all indicators must have an expiration date. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.externalId | String | An identification number that ties the indicator back to the indicator provider’s system (e.g. a foreign key). | |
| MicrosoftATP.Indicators.fileCompileDateTime | Date | DateTime when the file was compiled. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.fileCreatedDateTime | Date | DateTime when the file was created.The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.fileHashType | String | The type of hash stored in fileHashValue. Possible values are: unknown, sha1, sha256, md5, authenticodeHash256, lsHash, ctph. | |
| MicrosoftATP.Indicators.fileHashValue | String | The file hash value. | |
| MicrosoftATP.Indicators.fileMutexName | String | Mutex name used in file-based detections. | |
| MicrosoftATP.Indicators.fileName | String | Name of the file if the indicator is file-based. Supports comma-separate list of file names. | |
| MicrosoftATP.Indicators.filePacker | String | The packer used to build the file in question. | |
| MicrosoftATP.Indicators.filePath | String | Path of the file indicating a compromise. May be a Windows or *nix style. | |
| MicrosoftATP.Indicators.fileSize | Number | Size of the file in bytes. | |
| MicrosoftATP.Indicators.fileType | String | Text description of the type of file. For example, “Word Document” or “Binary”. | |
| MicrosoftATP.Indicators.ingestedDateTime | Date | Stamped by the system when the indicator is ingested. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.isActive | Boolean | Used to deactivate indicators within system. By default, any indicator submitted is set as active. However, providers may submit existing indicators with this set to ‘False’ to deactivate indicators in the system. | |
| MicrosoftATP.Indicators.knownFalsePositives | String | Scenarios in which the indicator may cause false positives. This should be human-readable text. | |
| MicrosoftATP.Indicators.lastReportedDateTime | Date | The last time the indicator was seen. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.networkCidrBlock | String | CIDR Block notation representation of the network referenced in this indicator. Use only if the Source and Destination cannot be identified. | |
| MicrosoftATP.Indicators.networkDestinationAsn | Number | The destination autonomous system identifier of the network referenced in the indicator. | |
| MicrosoftATP.Indicators.networkDestinationCidrBlock | String | CIDR Block notation representation of the destination network in this indicator. | |
| MicrosoftATP.Indicators.networkDestinationIPv4 | String | IPv4 IP address destination. | |
| MicrosoftATP.Indicators.networkDestinationIPv6 | String | IPv6 IP address destination. | |
| MicrosoftATP.Indicators.networkDestinationPort | Number | TCP port destination. | |
| MicrosoftATP.Indicators.networkIPv4 | String | IPv4 IP address. | |
| MicrosoftATP.Indicators.networkIPv6 | String | IPv6 IP address. | |
| MicrosoftATP.Indicators.networkPort | Number | TCP port. | |
| MicrosoftATP.Indicators.networkProtocol | Number | Decimal representation of the protocol field in the IPv4 header. | |
| MicrosoftATP.Indicators.networkSourceAsn | Number | The source autonomous system identifier of the network referenced in the indicator. | |
| MicrosoftATP.Indicators.networkSourceCidrBlock | String | CIDR Block notation representation of the source network in this indicator. | |
| MicrosoftATP.Indicators.networkSourceIPv4 | String | IPv4 IP address source. | |
| MicrosoftATP.Indicators.networkSourceIPv6 | String | IPv6 IP address source. | |
| MicrosoftATP.Indicators.networkSourcePort | Number | TCP port source. | |
| MicrosoftATP.Indicators.passiveOnly | Boolean | Determines if the indicator should trigger an event that is visible to an end user. When set to ‘true,’ security tools will not notify the end user that a ‘hit’ has occurred. This is most often treated as audit or silent mode by security products where they will simply log that a match occurred but will not perform the action. Default value is false. | |
| MicrosoftATP.Indicators.severity | Number | Severity of the malicious behavior identified by the data within the indicator. Possible values are 0 – 5, where 5 is the most severe and zero is not severe at all. Default is 3 | |
| MicrosoftATP.Indicators.targetProduct | String | A string value representing a single security product to which the indicator should be applied. | |
| MicrosoftATP.Indicators.threatType | String | Each indicator must have a valid Indicator Threat Type. Possible values are: Botnet, C2, CryptoMining, Darknet, DDoS, MaliciousUrl, Malware, Phishing, Proxy, PUA, WatchList. | |
| MicrosoftATP.Indicators.tlpLevel | String | Traffic Light Protocol value for the indicator. Possible values are: unknown, white, green, or amber. | |
| MicrosoftATP.Indicators.url | String | Uniform Resource Locator. This URL complies with RFC 1738. | |
| MicrosoftATP.Indicators.userAgent | String | User-Agent string from a web request that could indicate compromise. | |
| MicrosoftATP.Indicators.vendorInformation | String | Information about the vendor. |
Command Example
!microsoft-atp-indicator-get-by-id indicator_id=17
Context Example
{
"MicrosoftATP": {
"Indicators": {
"action": "block",
"activityGroupNames": [],
"azureTenantId": "TENANT-ID",
"description": "Title: Indicator example.com of type DomainName, Description: A description!",
"domainName": "example.com",
"expirationDateTime": "2020-09-02T17:17:57Z",
"id": "17",
"ingestedDateTime": "2020-08-26T17:18:00.0537984Z",
"isActive": true,
"killChain": [],
"malwareFamilyNames": [],
"severity": 2,
"tags": [],
"targetProduct": "Microsoft Defender ATP"
}
}
}
Human Readable Output
Indicators from Microsoft ATP
id action severity domainName 17 block 2 example.com
microsoft-atp-indicator-create-network
Deprecated. Use the microsoft-atp-sc-indicator-create command instead. Creates a network indicator.
Base Command
microsoft-atp-indicator-create-network
Input
| Argument Name | Description | Required |
|---|---|---|
| action | The action to apply if the indicator is matched from within the targetProduct security tool. | Required |
| description | Brief description (100 characters or less) of the threat represented by the indicator. | Required |
| expiration_time | DateTime string indicating when the indicator expires. Format: (<number> <time unit>, e.g., 12 hours, 7 days). | Required |
| threat_type | Each indicator must have a valid Indicator Threat Type. Possible values are: Botnet, C2, Cryptomining, Darknet, DDoS, MaliciousUrl, Malware, Phishing, Proxy, PUA, or WatchList. | Required |
| tlp_level | Traffic Light Protocol value for the indicator. Possible values are: unknown, white, green, or amber. | Optional |
| confidence | An integer representing the confidence with which the data within the indicator accurately identifies malicious behavior. Possible values are 0 – 100 with 100 being the highest. | Optional |
| severity | The severity of the malicious behavior identified by the data within the indicator. Possible values are Informational, Low, MediumLow, MediumHigh, High, where 5 is the most severe and zero is not severe at all. | Optional |
| tags | A comma-separated list that stores arbitrary tags/keywords. | Optional |
| domain_name | Domain name associated with this indicator. Should be in the format subdomain.domain.topleveldomain (For example, example.domain.net) | Optional |
| network_cidr_block | CIDR Block notation representation of the network referenced in this indicator. Use only if the Source and Destination cannot be identified. | Optional |
| network_destination_asn | The destination autonomous system identifier of the network referenced in the indicator. | Optional |
| network_destination_cidr_block | CIDR Block notation representation of the destination network in this indicator. | Optional |
| network_destination_ipv4 | IPv4 IP address destination. | Optional |
| network_destination_ipv6 | IPv6 IP address destination. |
Optional |
| network_destination_port | TCP port destination. | Optional |
| network_ipv4 | IPv4 IP address. Use only if the Source and Destination cannot be identified. | Optional |
| network_ipv6 | IPv6 IP address. Use only if the Source and Destination cannot be identified. | Optional |
| network_port | TCP port. Use only if the Source and Destination cannot be identified. | Optional |
| network_protocol | Decimal representation of the protocol field in the IPv4 header. | Optional |
| network_source_asn | The source autonomous system identifier of the network referenced in the indicator. | Optional |
| network_source_cidr_block | CIDR Block notation representation of the source network in this indicator. | Optional |
| network_source_ipv4 | IPv4 IP address source. | Optional |
| network_source_ipv6 | IPv6 IP address source. | Optional |
| network_source_port | TCP port source. | Optional |
| url | Uniform Resource Locator. This URL must comply with RFC 1738. | Optional |
| user_agent | User-Agent string from a web request that could indicate compromise. | Optional |
Context Output
| Path | Type | Description | |
|---|---|---|---|
| MicrosoftATP.Indicators.id | String | Created by the system when the indicator is ingested. Generated GUID/unique identifier. | |
| MicrosoftATP.Indicators.action | String | The action to apply if the indicator is matched from within the targetProduct security tool. Possible values are: unknown, allow, block, alert. | |
| MicrosoftATP.Indicators.additionalInformation | String | A catchall area into which extra data from the indicator not covered by the other indicator properties may be placed. Data placed into additionalInformation will typically not be used by the targetProduct security tool. | |
| MicrosoftATP.Indicators.azureTenantId | String | Timestamp when the indicator was ingested into the system. | |
| MicrosoftATP.Indicators.confidence | Number | An integer representing the confidence with which the data within the indicator accurately identifies malicious behavior. Possible values are 0 – 100, with 100 being the highest. | |
| MicrosoftATP.Indicators.description | String | Brief description (100 characters or less) of the threat represented by the indicator. | |
| MicrosoftATP.Indicators.diamondModel | String | The area of the Diamond Model in which this indicator exists. Possible values are: unknown, adversary, capability, infrastructure, victim. | |
| MicrosoftATP.Indicators.domainName | String | Domain name associated with this indicator. Should be in the format subdomain.domain.topleveldomain. | |
| MicrosoftATP.Indicators.emailEncoding | String | The type of text encoding used in the email. | |
| MicrosoftATP.Indicators.emailLanguage | String | The language of the email. | |
| MicrosoftATP.Indicators.emailRecipient | String | Recipient email address. | |
| MicrosoftATP.Indicators.emailSenderAddress | String | Email address of the attacker | victim. |
| MicrosoftATP.Indicators.emailSenderName | String | Display name of the attacker | victim.. |
| MicrosoftATP.Indicators.emailSourceDomain | String | Domain used in the email. | |
| MicrosoftATP.Indicators.emailSourceIpAddress | String | Source IP address of the email. | |
| MicrosoftATP.Indicators.emailSubject | String | Subject line of the email. | |
| MicrosoftATP.Indicators.emailXMailer | String | X-Mailer value used in the email. | |
| MicrosoftATP.Indicators.expirationDateTime | Date | DateTime string indicating when the indicator expires. To avoid stale indicators persisting in the system, all indicators must have an expiration date. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.externalId | String | An identification number that ties the indicator back to the indicator provider’s system (e.g. a foreign key). | |
| MicrosoftATP.Indicators.fileCompileDateTime | Date | DateTime when the file was compiled. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.fileCreatedDateTime | Date | DateTime when the file was created.The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.fileHashType | String | The type of hash stored in fileHashValue. Possible values are: unknown, sha1, sha256, md5, authenticodeHash256, lsHash, or ctph. Possible values are: unknown, sha1, sha256, md5, authenticodeHash256, lsHash, ctph. | |
| MicrosoftATP.Indicators.fileHashValue | String | The file hash value. | |
| MicrosoftATP.Indicators.fileMutexName | String | Mutex name used in file-based detections. | |
| MicrosoftATP.Indicators.fileName | String | Name of the file if the indicator is file-based. Supports comma-separate list of file names. | |
| MicrosoftATP.Indicators.filePacker | String | The packer used to build the file in question. | |
| MicrosoftATP.Indicators.filePath | String | Path of the file indicating a compromise. May be a Windows or *nix style. | |
| MicrosoftATP.Indicators.fileSize | Number | Size of the file in bytes. | |
| MicrosoftATP.Indicators.fileType | String | Text description of the type of file. For example, “Word Document” or “Binary”. | |
| MicrosoftATP.Indicators.ingestedDateTime | Date | Stamped by the system when the indicator is ingested. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.isActive | Boolean | Used to deactivate indicators within system. By default, any indicator submitted is set as active. However, providers may submit existing indicators with this set to ‘False’ to deactivate indicators in the system. | |
| MicrosoftATP.Indicators.knownFalsePositives | String | Scenarios in which the indicator may cause false positives. This should be human-readable text. | |
| MicrosoftATP.Indicators.lastReportedDateTime | Date | The last time the indicator was seen. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.networkCidrBlock | String | CIDR Block notation representation of the network referenced in this indicator. Use only if the Source and Destination cannot be identified. | |
| MicrosoftATP.Indicators.networkDestinationAsn | Number | The destination autonomous system identifier of the network referenced in the indicator. | |
| MicrosoftATP.Indicators.networkDestinationCidrBlock | String | CIDR Block notation representation of the destination network in this indicator. | |
| MicrosoftATP.Indicators.networkDestinationIPv4 | String | IPv4 IP address destination. | |
| MicrosoftATP.Indicators.networkDestinationIPv6 | String | IPv6 IP address destination. | |
| MicrosoftATP.Indicators.networkDestinationPort | Number | TCP port destination. | |
| MicrosoftATP.Indicators.networkIPv4 | String | IPv4 IP address. | |
| MicrosoftATP.Indicators.networkIPv6 | String | IPv6 IP address. | |
| MicrosoftATP.Indicators.networkPort | Number | TCP port. | |
| MicrosoftATP.Indicators.networkProtocol | Number | Decimal representation of the protocol field in the IPv4 header. | |
| MicrosoftATP.Indicators.networkSourceAsn | Number | The source autonomous system identifier of the network referenced in the indicator. | |
| MicrosoftATP.Indicators.networkSourceCidrBlock | String | CIDR Block notation representation of the source network in this indicator. | |
| MicrosoftATP.Indicators.networkSourceIPv4 | String | IPv4 IP address source. | |
| MicrosoftATP.Indicators.networkSourceIPv6 | String | IPv6 IP address source. | |
| MicrosoftATP.Indicators.networkSourcePort | Number | TCP port source. | |
| MicrosoftATP.Indicators.passiveOnly | Boolean | Determines if the indicator should trigger an event that is visible to an end user. When set to ‘true,’ security tools will not notify the end user that a ‘hit’ has occurred. This is most often treated as audit or silent mode by security products where they will simply log that a match occurred but will not perform the action. Default value is false. | |
| MicrosoftATP.Indicators.severity | Number | Severity of the malicious behavior identified by the data within the indicator. Possible values are 0 – 5, where 5 is the most severe and zero is not severe at all. Default is 3 | |
| MicrosoftATP.Indicators.targetProduct | String | A string value representing a single security product to which the indicator should be applied. | |
| MicrosoftATP.Indicators.threatType | String | Each indicator must have a valid Indicator Threat Type. Possible values are: Botnet, C2, CryptoMining, Darknet, DDoS, MaliciousUrl, Malware, Phishing, Proxy, PUA, WatchList. | |
| MicrosoftATP.Indicators.tlpLevel | String | Traffic Light Protocol value for the indicator. Possible values are: unknown, white, green, or amber. | |
| MicrosoftATP.Indicators.url | String | Uniform Resource Locator. This URL complies with RFC 1738. | |
| MicrosoftATP.Indicators.userAgent | String | User-Agent string from a web request that could indicate compromise. | |
| MicrosoftATP.Indicators.vendorInformation | String | Information about the vendor. |
Command Example
!microsoft-atp-indicator-create-network action=unknown description="A description!" expiration_time="7 days" threat_type=CryptoMining domain_name="example.com"
Context Example
{
"MicrosoftATP": {
"Indicators": {
"action": "block",
"activityGroupNames": [],
"azureTenantId": "TENANT-ID",
"description": "Title: Indicator example.com of type DomainName, Description: A description!",
"domainName": "example.com",
"expirationDateTime": "2020-09-02T17:17:57Z",
"id": "17",
"ingestedDateTime": "2020-08-26T17:18:00.0537984Z",
"isActive": true,
"killChain": [],
"malwareFamilyNames": [],
"severity": 2,
"tags": [],
"targetProduct": "Microsoft Defender ATP"
}
}
}
Human Readable Output
Indicator 17 was successfully created
id action severity domainName 17 block 2 example.com
microsoft-atp-indicator-create-file
Deprecated. Use the microsoft-atp-sc-indicator-create command instead. Creates a file indicator
Base Command
microsoft-atp-indicator-create-file
Input
| Argument Name | Description | Required |
|---|---|---|
| action | The action to apply if the indicator is matched from within the targetProduct security tool. | Required |
| description | Brief description (100 characters or less) of the threat represented by the indicator. | Required |
| expiration_time | DateTime string indicating when the indicator expires. Format: (<number> <time unit>, e.g., 12 hours, 7 days). | Required |
| threat_type | Each indicator must have a valid Indicator Threat Type. Possible values are: Botnet, C2, Cryptomining, Darknet, DDoS, MaliciousUrl, Malware, Phishing, Proxy, PUA, or WatchList. | Required |
| tlp_level | Traffic Light Protocol value for the indicator. Possible values are: unknown, white, green, or amber. | Optional |
| confidence | An integer representing the confidence with which the data within the indicator accurately identifies malicious behavior. Possible values are 0 – 100 with 100 being the highest. | Optional |
| severity | The severity of the malicious behavior identified by the data within the indicator. Possible values are Informational, Low, MediumLow, MediumHigh, High, where 5 is the most severe and zero is not severe at all. | Optional |
| tags | A comma-separated list that stores arbitrary tags/keywords. | Optional |
| file_compile_date_time | DateTime when the file was compiled. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | Optional |
| file_created_date_time | DateTime when the file was created.The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | Optional |
| file_hash_type | The type of hash stored in fileHashValue. Possible values are: unknown, sha1, sha256, md5, authenticodeHash256, lsHash, or ctph. | Optional |
| file_hash_value | The file hash value. | Optional |
| file_mutex_name | Mutex name used in file-based detections. | Optional |
| file_name | Name of the file if the indicator is file-based. Supports comma-separate list of file names. | Optional |
| file_packer | The packer used to build the file in question. | Optional |
| file_path | Path of the file indicating a compromise. Can be a Windows or *nix style path. | Optional |
| file_size | Size of the file in bytes. | Optional |
| file_type | Text description of the type of file. For example, “Word Document” or “Binary”. | Optional |
Context Output
| Path | Type | Description | |
|---|---|---|---|
| MicrosoftATP.Indicators.id | String | Created by the system when the indicator is ingested. Generated GUID/unique identifier. | |
| MicrosoftATP.Indicators.action | String | The action to apply if the indicator is matched from within the targetProduct security tool. Possible values are: unknown, allow, block, alert. | |
| MicrosoftATP.Indicators.additionalInformation | String | A catchall area into which extra data from the indicator not covered by the other indicator properties may be placed. Data placed into additionalInformation will typically not be used by the targetProduct security tool. | |
| MicrosoftATP.Indicators.azureTenantId | String | Timestamp when the indicator was ingested into the system. | |
| MicrosoftATP.Indicators.confidence | Number | An integer representing the confidence with which the data within the indicator accurately identifies malicious behavior. Possible values are 0 – 100, with 100 being the highest. | |
| MicrosoftATP.Indicators.description | String | Brief description (100 characters or less) of the threat represented by the indicator. | |
| MicrosoftATP.Indicators.diamondModel | String | The area of the Diamond Model in which this indicator exists. Possible values are: unknown, adversary, capability, infrastructure, victim. | |
| MicrosoftATP.Indicators.domainName | String | Domain name associated with this indicator. Should be in the format subdomain.domain.topleveldomain. | |
| MicrosoftATP.Indicators.emailEncoding | String | The type of text encoding used in the email. | |
| MicrosoftATP.Indicators.emailLanguage | String | The language of the email. | |
| MicrosoftATP.Indicators.emailRecipient | String | Recipient email address. | |
| MicrosoftATP.Indicators.emailSenderAddress | String | Email address of the attacker | victim. |
| MicrosoftATP.Indicators.emailSenderName | String | Display name of the attacker | victim.. |
| MicrosoftATP.Indicators.emailSourceDomain | String | Domain used in the email. | |
| MicrosoftATP.Indicators.emailSourceIpAddress | String | Source IP address of the email. | |
| MicrosoftATP.Indicators.emailSubject | String | Subject line of the email. | |
| MicrosoftATP.Indicators.emailXMailer | String | X-Mailer value used in the email. | |
| MicrosoftATP.Indicators.expirationDateTime | Date | DateTime string indicating when the indicator expires. To avoid stale indicators persisting in the system, all indicators must have an expiration date. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.externalId | String | An identification number that ties the indicator back to the indicator provider’s system (e.g. a foreign key). | |
| MicrosoftATP.Indicators.fileCompileDateTime | Date | DateTime when the file was compiled. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.fileCreatedDateTime | Date | DateTime when the file was created.The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.fileHashType | String | The type of hash stored in fileHashValue. Possible values are: unknown, sha1, sha256, md5, authenticodeHash256, lsHash, or ctph. Possible values are: unknown, sha1, sha256, md5, authenticodeHash256, lsHash, ctph. | |
| MicrosoftATP.Indicators.fileHashValue | String | The file hash value. | |
| MicrosoftATP.Indicators.fileMutexName | String | Mutex name used in file-based detections. | |
| MicrosoftATP.Indicators.fileName | String | Name of the file if the indicator is file-based. Supports comma-separate list of file names. | |
| MicrosoftATP.Indicators.filePacker | String | The packer used to build the file in question. | |
| MicrosoftATP.Indicators.filePath | String | Path of the file indicating a compromise. May be a Windows or *nix style. | |
| MicrosoftATP.Indicators.fileSize | Number | Size of the file in bytes. | |
| MicrosoftATP.Indicators.fileType | String | Text description of the type of file. For example, “Word Document” or “Binary”. | |
| MicrosoftATP.Indicators.ingestedDateTime | Date | Stamped by the system when the indicator is ingested. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.isActive | Boolean | Used to deactivate indicators within system. By default, any indicator submitted is set as active. However, providers may submit existing indicators with this set to ‘False’ to deactivate indicators in the system. | |
| MicrosoftATP.Indicators.knownFalsePositives | String | Scenarios in which the indicator may cause false positives. This should be human-readable text. | |
| MicrosoftATP.Indicators.lastReportedDateTime | Date | The last time the indicator was seen. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.networkCidrBlock | String | CIDR Block notation representation of the network referenced in this indicator. Use only if the Source and Destination cannot be identified. | |
| MicrosoftATP.Indicators.networkDestinationAsn | Number | The destination autonomous system identifier of the network referenced in the indicator. | |
| MicrosoftATP.Indicators.networkDestinationCidrBlock | String | CIDR Block notation representation of the destination network in this indicator. | |
| MicrosoftATP.Indicators.networkDestinationIPv4 | String | IPv4 IP address destination. | |
| MicrosoftATP.Indicators.networkDestinationIPv6 | String | IPv6 IP address destination. | |
| MicrosoftATP.Indicators.networkDestinationPort | Number | TCP port destination. | |
| MicrosoftATP.Indicators.networkIPv4 | String | IPv4 IP address. | |
| MicrosoftATP.Indicators.networkIPv6 | String | IPv6 IP address. | |
| MicrosoftATP.Indicators.networkPort | Number | TCP port. | |
| MicrosoftATP.Indicators.networkProtocol | Number | Decimal representation of the protocol field in the IPv4 header. | |
| MicrosoftATP.Indicators.networkSourceAsn | Number | The source autonomous system identifier of the network referenced in the indicator. | |
| MicrosoftATP.Indicators.networkSourceCidrBlock | String | CIDR Block notation representation of the source network in this indicator. | |
| MicrosoftATP.Indicators.networkSourceIPv4 | String | IPv4 IP address source. | |
| MicrosoftATP.Indicators.networkSourceIPv6 | String | IPv6 IP address source. | |
| MicrosoftATP.Indicators.networkSourcePort | Number | TCP port source. | |
| MicrosoftATP.Indicators.passiveOnly | Boolean | Determines if the indicator should trigger an event that is visible to an end user. When set to ‘true,’ security tools will not notify the end user that a ‘hit’ has occurred. This is most often treated as audit or silent mode by security products where they will simply log that a match occurred but will not perform the action. Default value is false. | |
| MicrosoftATP.Indicators.severity | Number | Severity of the malicious behavior identified by the data within the indicator. Possible values are 0 – 5, where 5 is the most severe and zero is not severe at all. Default is 3 | |
| MicrosoftATP.Indicators.targetProduct | String | A string value representing a single security product to which the indicator should be applied. | |
| MicrosoftATP.Indicators.threatType | String | Each indicator must have a valid Indicator Threat Type. Possible values are: Botnet, C2, CryptoMining, Darknet, DDoS, MaliciousUrl, Malware, Phishing, Proxy, PUA, WatchList. | |
| MicrosoftATP.Indicators.tlpLevel | String | Traffic Light Protocol value for the indicator. Possible values are: unknown, white, green, or amber. | |
| MicrosoftATP.Indicators.url | String | Uniform Resource Locator. This URL complies with RFC 1738. | |
| MicrosoftATP.Indicators.userAgent | String | User-Agent string from a web request that could indicate compromise. | |
| MicrosoftATP.Indicators.vendorInformation | String | Information about the vendor. |
Command Example
!microsoft-atp-indicator-create-file action=allow description="A description" expiration_time="3 days" threat_type=Darknet confidence=23 file_hash_type=sha256 file_hash_value=50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c
Context Example
{
"MicrosoftATP": {
"Indicators": {
"action": "allow",
"activityGroupNames": [],
"azureTenantId": "TENANT-ID",
"description": "Title: Indicator 50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c of type FileSha256, Description: A description",
"expirationDateTime": "2020-08-29T17:18:01Z",
"fileHashType": "sha256",
"fileHashValue": "50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c",
"id": "18",
"ingestedDateTime": "2020-08-26T17:18:03.5249643Z",
"isActive": true,
"killChain": [],
"malwareFamilyNames": [],
"severity": 2,
"tags": [],
"targetProduct": "Microsoft Defender ATP"
}
}
}
Human Readable Output
Indicator 18 was successfully created
id action severity fileHashType fileHashValue 18 allow 2 sha256 50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c
microsoft-atp-indicator-update
Deprecated. Use the microsoft-atp-sc-indicator-update command instead. Updates the specified indicator.
Base Command
microsoft-atp-indicator-update
Input
| Argument Name | Description | Required |
|---|---|---|
| indicator_id | The ID of the indicator to update. | Required |
| severity | The severity of the malicious behavior identified by the data within the indicator. Possible values are Informational, Low, MediumLow, MediumHigh, High, where High is the most severe and Informational is not severe at all. | Optional |
| expiration_time | DateTime string indicating when the indicator expires. Format: (<number> <time unit>, e.g., 12 hours, 7 days). | Required |
| description | Brief description (100 characters or less) of the threat represented by the indicator. | Optional |
Context Output
| Path | Type | Description | |
|---|---|---|---|
| MicrosoftATP.Indicators.id | String | Created by the system when the indicator is ingested. Generated GUID/unique identifier. | |
| MicrosoftATP.Indicators.action | String | The action to apply if the indicator is matched from within the targetProduct security tool. Possible values are: unknown, allow, block, alert. | |
| MicrosoftATP.Indicators.additionalInformation | String | A catchall area into which extra data from the indicator not covered by the other indicator properties may be placed. Data placed into additionalInformation will typically not be used by the targetProduct security tool. | |
| MicrosoftATP.Indicators.azureTenantId | String | Timestamp when the indicator was ingested into the system. | |
| MicrosoftATP.Indicators.confidence | Number | An integer representing the confidence with which the data within the indicator accurately identifies malicious behavior. Possible values are 0 – 100, with 100 being the highest. | |
| MicrosoftATP.Indicators.description | String | Brief description (100 characters or less) of the threat represented by the indicator. | |
| MicrosoftATP.Indicators.diamondModel | String | The area of the Diamond Model in which this indicator exists. Possible values are: unknown, adversary, capability, infrastructure, victim. | |
| MicrosoftATP.Indicators.domainName | String | Domain name associated with this indicator. Should be in the format subdomain.domain.topleveldomain. | |
| MicrosoftATP.Indicators.emailEncoding | String | The type of text encoding used in the email. | |
| MicrosoftATP.Indicators.emailLanguage | String | The language of the email. | |
| MicrosoftATP.Indicators.emailRecipient | String | Recipient email address. | |
| MicrosoftATP.Indicators.emailSenderAddress | String | Email address of the attacker | victim. |
| MicrosoftATP.Indicators.emailSenderName | String | Display name of the attacker | victim.. |
| MicrosoftATP.Indicators.emailSourceDomain | String | Domain used in the email. | |
| MicrosoftATP.Indicators.emailSourceIpAddress | String | Source IP address of the email. | |
| MicrosoftATP.Indicators.emailSubject | String | Subject line of the email. | |
| MicrosoftATP.Indicators.emailXMailer | String | X-Mailer value used in the email. | |
| MicrosoftATP.Indicators.expirationDateTime | Date | DateTime string indicating when the indicator expires. To avoid stale indicators persisting in the system, all indicators must have an expiration date. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.externalId | String | An identification number that ties the indicator back to the indicator provider’s system (e.g. a foreign key). | |
| MicrosoftATP.Indicators.fileCompileDateTime | Date | DateTime when the file was compiled. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.fileCreatedDateTime | Date | DateTime when the file was created.The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.fileHashType | String | The type of hash stored in fileHashValue. Possible values are: unknown, sha1, sha256, md5, authenticodeHash256, lsHash, or ctph. Possible values are: unknown, sha1, sha256, md5, authenticodeHash256, lsHash, ctph. | |
| MicrosoftATP.Indicators.fileHashValue | String | The file hash value. | |
| MicrosoftATP.Indicators.fileMutexName | String | Mutex name used in file-based detections. | |
| MicrosoftATP.Indicators.fileName | String | Name of the file if the indicator is file-based. Supports comma-separate list of file names. | |
| MicrosoftATP.Indicators.filePacker | String | The packer used to build the file in question. | |
| MicrosoftATP.Indicators.filePath | String | Path of the file indicating a compromise. May be a Windows or *nix style. | |
| MicrosoftATP.Indicators.fileSize | Number | Size of the file in bytes. | |
| MicrosoftATP.Indicators.fileType | String | Text description of the type of file. For example, “Word Document” or “Binary”. | |
| MicrosoftATP.Indicators.ingestedDateTime | Date | Stamped by the system when the indicator is ingested. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.isActive | Boolean | Used to deactivate indicators within system. By default, any indicator submitted is set as active. However, providers may submit existing indicators with this set to ‘False’ to deactivate indicators in the system. | |
| MicrosoftATP.Indicators.knownFalsePositives | String | Scenarios in which the indicator may cause false positives. This should be human-readable text. | |
| MicrosoftATP.Indicators.lastReportedDateTime | Date | The last time the indicator was seen. The Timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ | |
| MicrosoftATP.Indicators.networkCidrBlock | String | CIDR Block notation representation of the network referenced in this indicator. Use only if the Source and Destination cannot be identified. | |
| MicrosoftATP.Indicators.networkDestinationAsn | Number | The destination autonomous system identifier of the network referenced in the indicator. | |
| MicrosoftATP.Indicators.networkDestinationCidrBlock | String | CIDR Block notation representation of the destination network in this indicator. | |
| MicrosoftATP.Indicators.networkDestinationIPv4 | String | IPv4 IP address destination. | |
| MicrosoftATP.Indicators.networkDestinationIPv6 | String | IPv6 IP address destination. | |
| MicrosoftATP.Indicators.networkDestinationPort | Number | TCP port destination. | |
| MicrosoftATP.Indicators.networkIPv4 | String | IPv4 IP address. | |
| MicrosoftATP.Indicators.networkIPv6 | String | IPv6 IP address. | |
| MicrosoftATP.Indicators.networkPort | Number | TCP port. | |
| MicrosoftATP.Indicators.networkProtocol | Number | Decimal representation of the protocol field in the IPv4 header. | |
| MicrosoftATP.Indicators.networkSourceAsn | Number | The source autonomous system identifier of the network referenced in the indicator. | |
| MicrosoftATP.Indicators.networkSourceCidrBlock | String | CIDR Block notation representation of the source network in this indicator. | |
| MicrosoftATP.Indicators.networkSourceIPv4 | String | IPv4 IP address source. | |
| MicrosoftATP.Indicators.networkSourceIPv6 | String | IPv6 IP address source. | |
| MicrosoftATP.Indicators.networkSourcePort | Number | TCP port source. | |
| MicrosoftATP.Indicators.passiveOnly | Boolean | Determines if the indicator should trigger an event that is visible to an end user. When set to ‘true,’ security tools will not notify the end user that a ‘hit’ has occurred. This is most often treated as audit or silent mode by security products where they will simply log that a match occurred but will not perform the action. Default value is false. | |
| MicrosoftATP.Indicators.severity | Number | Severity of the malicious behavior identified by the data within the indicator. Possible values are 0 – 5, where 5 is the most severe and zero is not severe at all. Default is 3 | |
| MicrosoftATP.Indicators.targetProduct | String | A string value representing a single security product to which the indicator should be applied. | |
| MicrosoftATP.Indicators.threatType | String | Each indicator must have a valid Indicator Threat Type. Possible values are: Botnet, C2, CryptoMining, Darknet, DDoS, MaliciousUrl, Malware, Phishing, Proxy, PUA, WatchList. | |
| MicrosoftATP.Indicators.tlpLevel | String | Traffic Light Protocol value for the indicator. Possible values are: unknown, white, green, or amber. | |
| MicrosoftATP.Indicators.url | String | Uniform Resource Locator. This URL complies with RFC 1738. | |
| MicrosoftATP.Indicators.userAgent | String | User-Agent string from a web request that could indicate compromise. | |
| MicrosoftATP.Indicators.vendorInformation | String | Information about the vendor. |
Command Example
!microsoft-atp-indicator-update expiration_time="2 days" indicator_id=18
Context Example
{
"MicrosoftATP": {
"Indicators": {
"action": "allow",
"activityGroupNames": [],
"azureTenantId": "TENANT-ID",
"description": "Title: Indicator 50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c of type FileSha256, Description: A description",
"expirationDateTime": "2020-08-28T17:21:15Z",
"fileHashType": "sha256",
"fileHashValue": "50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c",
"id": "18",
"ingestedDateTime": "2020-08-26T17:18:03.5249643Z",
"isActive": true,
"killChain": [],
"malwareFamilyNames": [],
"severity": 0,
"tags": [],
"targetProduct": "Microsoft Defender ATP"
}
}
}
Human Readable Output
Indicator ID: 18 was updated successfully
action azureTenantId description expirationDateTime fileHashType fileHashValue id ingestedDateTime isActive severity targetProduct allow TENANT-ID Title: Indicator 50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c of type FileSha256, Description: A description 2020-08-28T17:21:15Z sha256 50d858e0985ecc7f60418aaf0cc5ab587f42c2570a884095a9e8ccacd0f6545c 18 2020-08-26T17:18:03.5249643Z true 0 Microsoft Defender ATP
microsoft-atp-indicator-delete
Deprecated. Use the microsoft-atp-sc-indicator-delete command instead. Deletes the specified indicator.
Base Command
microsoft-atp-indicator-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| indicator_id | The ID of the indicator to delete. | Required |
Context Output
There is no context output for this command.
Command Example
!microsoft-atp-indicator-delete indicator_id=18
Human Readable Output
Indicator ID: 18 was successfully deleted
microsoft-atp-sc-indicator-list
Lists all indicators by the ID that the system creates when the indicator is ingested.
Permissions
Ti.ReadWrite
Note
To ensure that the application is accessible to all indicators, the ‘Ti.ReadWrite.All’ permission must be granted. Without this permission, the application will only be accessible to the indicators it has created.
Base Command
microsoft-atp-sc-indicator-list
Input
| Argument Name | Description | Required |
|---|---|---|
| limit | The maximum number of indicators to return. Default is 50. | Optional |
| skip | The number of indicators that are to be skipped and not included in the result. | Optional |
| indicator_value | The value of the indicator to get. | Optional |
| indicator_title | The title of the indicator to get. | Optional |
| indicator_type | The type of the indicator to get. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Indicators.id | String | Created by the system when the indicator is ingested. Generated GUID/unique identifier. |
| MicrosoftATP.Indicators.action | String | The action to apply if the indicator is matched from within the targetProduct security tool. Possible values: “unknown”, “allow”, “block”, and “alert”. |
| MicrosoftATP.Indicators.description | String | Brief description (100 characters or less) of the threat represented by the indicator. |
| MicrosoftATP.Indicators.expirationTime | Date | DateTime string indicating when the indicator expires. To avoid stale indicators persisting in the system, all indicators must have an expiration date. The timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ |
| MicrosoftATP.Indicators.severity | String | The severity of the malicious behavior identified by the data within the indicator. Possible values: “Informational”, “Low”, “Medium”, and “High”, where High is the most severe and Informational is not severe at all. |
| MicrosoftATP.Indicators.indicatorValue | String | The value of the indicator. |
| MicrosoftATP.Indicators.recommendedActions | String | Recommended actions for the indicator. |
| MicrosoftATP.Indicators.generateAlert | Boolean | Whether an alert was generated. |
| MicrosoftATP.Indicators.rbacGroupNames | Unknown | A list of RBAC device group names where the indicator is exposed and active. Empty list if it is exposed to all devices. |
| MicrosoftATP.Indicators.mitreTechniques | Unknown | A list of MITRE techniques. |
| MicrosoftATP.Indicators.indicatorType | String | Indicator Type. Possible values: “FileSha1”, “FileSha256”, “IpAddress”, “DomainName” and “Url”. |
| MicrosoftATP.Indicators.lastUpdateTime | Date | The last time the indicator was updated. |
| MicrosoftATP.Indicators.createdByDisplayName | String | Display name of the created app. |
| MicrosoftATP.Indicators.application | String | The application associated with the indicator. |
| MicrosoftATP.Indicators.title | String | Indicator title. |
| MicrosoftATP.Indicators.createdBySource | String | Source of indicator creation. For example, PublicApi. |
| MicrosoftATP.Indicators.historicalDetection | Boolean | Whether a historical detection exists. |
| MicrosoftATP.Indicators.lastUpdatedBy | String | Identity of the user/application that last updated the indicator. |
| MicrosoftATP.Indicators.creationTimeDateTimeUtc | Date | The date and time when the indicator was created. |
| MicrosoftATP.Indicators.category | Number | A number representing the indicator category. |
| MicrosoftATP.Indicators.createdBy | String | Unique identity of the user/application that submitted the indicator. |
| File.MD5 | String | The MD5 hash of the file. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| Domain.Name | String | The domain name, for example: “google.com”. |
| IP.Address | String | IP address. |
| URL.Data | String | The URL. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
Command Example
!microsoft-atp-sc-indicator-list limit=2
Context Example
{
"DBotScore": [
{
"Indicator": "1.1.1.1",
"Score": 0,
"Type": "ip",
"Vendor": "Microsoft Defender Advanced Threat Protection test"
},
{
"Indicator": "5.5.5.5",
"Score": 0,
"Type": "ip",
"Vendor": "Microsoft Defender Advanced Threat Protection test"
}
],
"IP": [
{
"Address": "1.1.1.1"
},
{
"Address": "5.5.5.5"
}
],
"MicrosoftATP": {
"Indicators": [
{
"action": "Allowed",
"category": 1,
"createdBy": "1281a70f-8ffb-4b3c-bc82-eef2a44dbb2a",
"createdByDisplayName": "MS Graph ATP",
"createdBySource": "PublicApi",
"creationTimeDateTimeUtc": "2021-08-17T08:57:46.1460707Z",
"description": "description",
"expirationTime": "2021-08-18T08:57:45Z",
"generateAlert": false,
"historicalDetection": false,
"id": "5142",
"indicatorType": "IpAddress",
"indicatorValue": "1.1.1.1",
"lastUpdateTime": "2021-08-17T08:57:46.1563409Z",
"severity": "Low",
"title": "title"
},
{
"action": "Allowed",
"category": 1,
"createdBy": "1281a70f-8ffb-4b3c-bc82-eef2a44dbb2a",
"createdByDisplayName": "MS Graph ATP",
"createdBySource": "PublicApi",
"creationTimeDateTimeUtc": "2021-08-17T08:56:49.1898574Z",
"description": "description",
"expirationTime": "2021-08-18T08:56:48Z",
"generateAlert": false,
"historicalDetection": false,
"id": "5141",
"indicatorType": "IpAddress",
"indicatorValue": "5.5.5.5",
"lastUpdateTime": "2021-08-17T08:56:49.2017376Z",
"severity": "Low",
"title": "title"
}
]
}
}
Human Readable Output
Results found in Microsoft Defender ATP SC for value: 5.5.5.5
id action indicatorValue indicatorType severity title description 5141 Allowed 5.5.5.5 IpAddress Low title description
microsoft-atp-sc-indicator-update
Updates the specified indicator.
Permissions
Ti.ReadWrite
Base Command
microsoft-atp-sc-indicator-update
Input
| Argument Name | Description | Required |
|---|---|---|
| indicator_value | The value of the indicator to update. | Required |
| indicator_type | Indicator Type. Possible values are: FileSha1, FileSha256, IpAddress, DomainName, Url. | Required |
| action | The action taken if the indicator is discovered in the organization. Possible values are: Alert, AlertAndBlock, Allowed. | Required |
| severity | The severity of the malicious behavior identified by the data within the indicator. Possible values: “Informational”, “Low”, “Medium”, and “High”, where High is the most severe and Informational is not severe at all. | Optional |
| expiration_time | DateTime string indicating when the indicator expires. Format: (<number> <time unit>, e.g., 12 hours, 7 days). Default is 14 days. | Optional |
| indicator_description | Brief description (100 characters or less) of the threat represented by the indicator. | Required |
| indicator_title | Indicator alert title. | Required |
| indicator_application | The application associated with the indicator. | Optional |
| recommended_actions | TI indicator alert recommended actions. | Optional |
| rbac_group_names | Comma-separated list of RBAC group names the indicator is applied to. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Indicators.id | String | Created by the system when the indicator is ingested. Generated GUID/unique identifier. |
| MicrosoftATP.Indicators.action | String | The action to apply if the indicator is matched from within the targetProduct security tool. Possible values: “unknown”, “allow”, “block”, and “alert”. |
| MicrosoftATP.Indicators.description | String | Brief description (100 characters or less) of the threat represented by the indicator. |
| MicrosoftATP.Indicators.expirationTime | Date | DateTime string indicating when the indicator expires. To avoid stale indicators persisting in the system, all indicators must have an expiration date. The timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ |
| MicrosoftATP.Indicators.severity | String | The severity of the malicious behavior identified by the data within the indicator. Possible values: “Informational”, “Low”, “Medium”, and “High”, where High is the most severe and Informational is not severe at all. |
| MicrosoftATP.Indicators.indicatorValue | String | The value of the indicator. |
| MicrosoftATP.Indicators.recommendedActions | String | Recommended actions for the indicator. |
| MicrosoftATP.Indicators.generateAlert | Boolean | Whether an alert was generated. |
| MicrosoftATP.Indicators.rbacGroupNames | Unknown | A list of RBAC device group names where the indicator is exposed and active. Empty list if it is exposed to all devices. |
| MicrosoftATP.Indicators.mitreTechniques | Unknown | A list of MITRE techniques. |
| MicrosoftATP.Indicators.indicatorType | String | Indicator Type. Possible values: “FileSha1”, “FileSha256”, “IpAddress”, “DomainName” and “Url”. |
| MicrosoftATP.Indicators.lastUpdateTime | Date | The last time the indicator was updated. |
| MicrosoftATP.Indicators.createdByDisplayName | String | Display name of the created app. |
| MicrosoftATP.Indicators.application | String | The application associated with the indicator. |
| MicrosoftATP.Indicators.title | String | Indicator title. |
| MicrosoftATP.Indicators.createdBySource | String | Source of indicator creation. For example, PublicApi. |
| MicrosoftATP.Indicators.historicalDetection | Boolean | Whether a historical detection exists. |
| MicrosoftATP.Indicators.lastUpdatedBy | String | Identity of the user/application that last updated the indicator. |
| MicrosoftATP.Indicators.creationTimeDateTimeUtc | Date | The date and time when the indicator was created. |
| MicrosoftATP.Indicators.category | Number | An number representing the indicator category. |
| MicrosoftATP.Indicators.createdBy | String | Unique identity of the user/application that submitted the indicator. |
| File.MD5 | String | The MD5 hash of the file. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| Domain.Name | String | The domain name, for example: “google.com”. |
| IP.Address | String | IP address. |
| URL.Data | String | The URL. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
Command Example
!microsoft-atp-sc-indicator-update action=Allowed indicator_description=test indicator_title=title indicator_type=IpAddress indicator_value=2.2.2.2 expiration_time="1 day" severity=Low
Context Example
{
"DBotScore": {
"Indicator": "2.2.2.2",
"Score": 0,
"Type": "ip",
"Vendor": "Microsoft Defender Advanced Threat Protection test"
},
"IP": {
"Address": "2.2.2.2"
},
"MicrosoftATP": {
"Indicators": {
"@odata.context": "https://api.securitycenter.microsoft.com/api/$metadata#Indicators/$entity",
"action": "Allowed",
"category": 1,
"createdBy": "1281a70f-8ffb-4b3c-bc82-eef2a44dbb2a",
"createdByDisplayName": "MS Graph ATP",
"createdBySource": "PublicApi",
"creationTimeDateTimeUtc": "2021-08-17T08:58:12.0340768Z",
"description": "test",
"expirationTime": "2021-08-18T08:58:12Z",
"generateAlert": false,
"historicalDetection": false,
"id": "5143",
"indicatorType": "IpAddress",
"indicatorValue": "2.2.2.2",
"lastUpdateTime": "2021-08-17T08:58:13.5312934Z",
"lastUpdatedBy": "1281a70f-8ffb-4b3c-bc82-eef2a44dbb2a",
"mitreTechniques": [],
"rbacGroupIds": [],
"rbacGroupNames": [],
"severity": "Low",
"title": "title"
}
}
}
Human Readable Output
Indicator 2.2.2.2 was updated successfully
id action indicatorValue indicatorType severity title description 5143 Allowed 2.2.2.2 IpAddress Low title test
microsoft-atp-sc-indicator-get-by-id
Gets an indicator by its ID.
Permissions
Ti.ReadWrite
Base Command
microsoft-atp-sc-indicator-get-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| indicator_id | The ID of the indicator to get. The ID can be retrieved by running the microsoft-atp-sc-indicator-list command. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Indicators.id | String | Created by the system when the indicator is ingested. Generated GUID/unique identifier. |
| MicrosoftATP.Indicators.action | String | The action to apply if the indicator is matched from within the targetProduct security tool. Possible values: “unknown”, “allow”, “block”, and “alert”. |
| MicrosoftATP.Indicators.description | String | Brief description (100 characters or less) of the threat represented by the indicator. |
| MicrosoftATP.Indicators.expirationTime | Date | DateTime string indicating when the indicator expires. To avoid stale indicators persisting in the system, all indicators must have an expiration date. The timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ |
| MicrosoftATP.Indicators.severity | String | The severity of the malicious behavior identified by the data within the indicator. Possible values: “Informational”, “Low”, “Medium” and “High”, where High is the most severe and Informational is not severe at all. |
| MicrosoftATP.Indicators.indicatorValue | String | The value of the indicator. |
| MicrosoftATP.Indicators.recommendedActions | String | Recommended actions for the indicator. |
| MicrosoftATP.Indicators.generateAlert | Boolean | Whether an alert was generated. |
| MicrosoftATP.Indicators.rbacGroupNames | Unknown | A list of RBAC device group names where the indicator is exposed and active. Empty list if it is exposed to all devices. |
| MicrosoftATP.Indicators.mitreTechniques | Unknown | A list of MITRE techniques. |
| MicrosoftATP.Indicators.indicatorType | String | Indicator Type. Possible values: “FileSha1”, “FileSha256”, “IpAddress”, “DomainName” and “Url”. |
| MicrosoftATP.Indicators.lastUpdateTime | Date | The last time the indicator was updated. |
| MicrosoftATP.Indicators.createdByDisplayName | String | Display name of the created app. |
| MicrosoftATP.Indicators.application | String | The application associated with the indicator. |
| MicrosoftATP.Indicators.title | String | Indicator title. |
| MicrosoftATP.Indicators.createdBySource | String | Source of indicator creation. For example, PublicApi. |
| MicrosoftATP.Indicators.historicalDetection | Boolean | Whether a historical detection exists. |
| MicrosoftATP.Indicators.lastUpdatedBy | String | Identity of the user/application that last updated the indicator. |
| MicrosoftATP.Indicators.creationTimeDateTimeUtc | Date | The date and time when the indicator was created. |
| MicrosoftATP.Indicators.category | Number | An number representing the indicator category. |
| MicrosoftATP.Indicators.createdBy | String | Unique identity of the user/application that submitted the indicator. |
| File.MD5 | String | The MD5 hash of the file. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| Domain.Name | String | The domain name, for example: “google.com”. |
| IP.Address | String | IP address. |
| URL.Data | String | The URL. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
Command Example
!microsoft-atp-sc-indicator-get-by-id indicator_id=5142
Context Example
{
"DBotScore": {
"Indicator": "1.1.1.1",
"Score": 0,
"Type": "ip",
"Vendor": "Microsoft Defender Advanced Threat Protection test"
},
"IP": {
"Address": "1.1.1.1"
},
"MicrosoftATP": {
"Indicators": {
"@odata.context": "https://api.securitycenter.microsoft.com/api/$metadata#Indicators/$entity",
"action": "Allowed",
"additionalInfo": null,
"application": null,
"bypassDurationHours": null,
"category": 1,
"certificateInfo": null,
"createdBy": "1281a70f-8ffb-4b3c-bc82-eef2a44dbb2a",
"createdByDisplayName": "MS Graph ATP",
"createdBySource": "PublicApi",
"creationTimeDateTimeUtc": "2021-08-17T08:57:46.1460707Z",
"description": "description",
"educateUrl": null,
"expirationTime": "2021-08-18T08:57:45Z",
"externalId": null,
"generateAlert": false,
"historicalDetection": false,
"id": "5142",
"indicatorType": "IpAddress",
"indicatorValue": "1.1.1.1",
"lastUpdateTime": "2021-08-17T08:57:46.1563409Z",
"lastUpdatedBy": null,
"lookBackPeriod": null,
"mitreTechniques": [],
"notificationBody": null,
"notificationId": null,
"rbacGroupIds": [],
"rbacGroupNames": [],
"recommendedActions": null,
"severity": "Low",
"title": "title",
"version": null
}
}
}
Human Readable Output
Results found in Microsoft Defender ATP SC for value: 1.1.1.1
id action indicatorValue indicatorType severity title description 5142 Allowed 1.1.1.1 IpAddress Low title description
microsoft-atp-sc-indicator-delete
Deletes the specified indicator.
Permissions
Ti.ReadWrite
Base Command
microsoft-atp-sc-indicator-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| indicator_id | The ID of the indicator to delete. The ID can be retrieved by running the microsoft-atp-sc-indicator-list command. | Required |
Context Output
There is no context output for this command.
Command Example
!microsoft-atp-sc-indicator-delete indicator_id=5142
Human Readable Output
Indicator ID: 5142 was successfully deleted
microsoft-atp-sc-indicator-create
Creates a new indicator.
Permissions
Ti.ReadWrite
Base Command
microsoft-atp-sc-indicator-create
Input
| Argument Name | Description | Required |
|---|---|---|
| indicator_value | The value of the indicator to update. | Required |
| indicator_type | Indicator Type. Possible values are: FileSha1, FileSha256, IpAddress, DomainName, Url. | Required |
| action | The action taken if the indicator is discovered in the organization. Possible values are: Alert, AlertAndBlock, Allowed. | Required |
| severity | The severity of the malicious behavior identified by the data within the indicator. Possible values: “Informational”, “Low”, “Medium”, and “High”, where High is the most severe and Informational is not severe at all. | Optional |
| expiration_time | DateTime string indicating when the indicator expires. Format: (<number> <time unit>, e.g., 12 hours, 7 days). Default is 14 days. | Optional |
| indicator_description | Brief description (100 characters or less) of the threat represented by the indicator. | Required |
| indicator_title | Indicator alert title. | Required |
| indicator_application | The application associated with the indicator. | Optional |
| recommended_actions | TI indicator alert recommended actions. | Optional |
| rbac_group_names | Comma-separated list of RBAC group names the indicator is applied to. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Indicators.id | String | Created by the system when the indicator is ingested. Generated GUID/unique identifier. |
| MicrosoftATP.Indicators.action | String | The action to apply if the indicator is matched from within the targetProduct security tool. Possible values: “unknown”, “allow”, “block”, “alert”. |
| MicrosoftATP.Indicators.description | String | Brief description (100 characters or less) of the threat represented by the indicator. |
| MicrosoftATP.Indicators.expirationTime | Date | DateTime string indicating when the indicator expires. To avoid stale indicators persisting in the system, all indicators must have an expiration date. The timestamp type represents date and time information in ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 looks like: ‘2014-01-01T00:00:00Z’ |
| MicrosoftATP.Indicators.severity | String | The severity of the malicious behavior identified by the data within the indicator. Possible values: “Informational”, “Low”, “Medium”, and “High”, where High is the most severe and Informational is not severe at all. |
| MicrosoftATP.Indicators.indicatorValue | String | The value of the indicator. |
| MicrosoftATP.Indicators.recommendedActions | String | Recommended actions for the indicator. |
| MicrosoftATP.Indicators.generateAlert | Boolean | Whether an alert was generated. |
| MicrosoftATP.Indicators.rbacGroupNames | Unknown | A list of RBAC device group names where the indicator is exposed and active. Empty list if it is exposed to all devices. |
| MicrosoftATP.Indicators.mitreTechniques | Unknown | A list of MITRE techniques. |
| MicrosoftATP.Indicators.indicatorType | String | Type of the indicator. Possible values: “FileSha1”, “FileSha256”, “IpAddress”, “DomainName” and “Url”. |
| MicrosoftATP.Indicators.lastUpdateTime | Date | The last time the indicator was updated. |
| MicrosoftATP.Indicators.createdByDisplayName | String | Display name of the created app. |
| MicrosoftATP.Indicators.application | String | The application associated with the indicator. |
| MicrosoftATP.Indicators.title | String | Indicator title. |
| MicrosoftATP.Indicators.createdBySource | String | Source of indicator creation. For example, PublicApi. |
| MicrosoftATP.Indicators.historicalDetection | Boolean | Whether a historical detection exists. |
| MicrosoftATP.Indicators.lastUpdatedBy | String | Identity of the user/application that last updated the indicator. |
| MicrosoftATP.Indicators.creationTimeDateTimeUtc | Date | The date and time when the indicator was created. |
| MicrosoftATP.Indicators.category | Number | An number representing the indicator category. |
| MicrosoftATP.Indicators.createdBy | String | Unique identity of the user/application that submitted the indicator. |
| File.MD5 | String | The MD5 hash of the file. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| Domain.Name | String | The domain name, for example: “google.com”. |
| IP.Address | String | IP address. |
| URL.Data | String | The URL. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
Command Example
!microsoft-atp-sc-indicator-create action=Allowed indicator_description=test indicator_title=title indicator_type=IpAddress indicator_value=2.2.2.2 expiration_time="1 day" severity=Informational
Context Example
{
"DBotScore": {
"Indicator": "2.2.2.2",
"Score": 0,
"Type": "ip",
"Vendor": "Microsoft Defender Advanced Threat Protection test"
},
"IP": {
"Address": "2.2.2.2"
},
"MicrosoftATP": {
"Indicators": {
"@odata.context": "https://api.securitycenter.microsoft.com/api/$metadata#Indicators/$entity",
"action": "Allowed",
"createdBy": "1281a70f-8ffb-4b3c-bc82-eef2a44dbb2a",
"createdByDisplayName": "MS Graph ATP",
"createdBySource": "PublicApi",
"creationTimeDateTimeUtc": "2021-08-17T08:58:12.0340768Z",
"description": "test",
"expirationTime": "2021-08-18T08:58:11Z",
"generateAlert": false,
"historicalDetection": false,
"id": "5143",
"indicatorType": "IpAddress",
"indicatorValue": "2.2.2.2",
"lastUpdateTime": "2021-08-17T08:58:12.0438875Z",
"mitreTechniques": [],
"rbacGroupIds": [],
"rbacGroupNames": [],
"severity": "Informational",
"title": "title"
}
}
}
Human Readable Output
Indicator 2.2.2.2 was updated successfully
id action indicatorValue indicatorType severity title description 5143 Allowed 2.2.2.2 IpAddress Informational title test
microsoft-atp-list-machines-by-vulnerability
Retrieves a list of machines affected by a vulnerability.
Required Permissions
Vulnerability.Read.All
Base Command
microsoft-atp-list-machines-by-vulnerability
Input
| Argument Name | Description | Required |
|---|---|---|
| cve_id | A comma-separated list of CVE IDs used for getting the machines. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.CveMachine.ID | String | The machine ID. |
| MicrosoftATP.CveMachine.ComputerDNSName | String | The machine hostname. |
| MicrosoftATP.CveMachine.OSPlatform | String | The operating system platform. |
| MicrosoftATP.CveMachine.RBACGroupName | String | The machine RBAC group name. |
| MicrosoftATP.CveMachine.CVE | Unknown | The given CVE IDs related to this machine. |
Command example
!microsoft-atp-list-machines-by-vulnerability cve_id=CVE-2021-32810,CVE-2020-12321
Context Example
{
"MicrosoftATP": {
"CveMachine": [
{
"ComputerDNSName": "ec2amaz",
"ID": "f3bba49a",
"OSPlatform": "WindowsServer2016",
"RBACGroupID": 0,
"CVE": ["CVE-2021-32810", "CVE-2020-12321"]
},
{
"ComputerDNSName": "msde-agent-host-centos7",
"ID": "48a62a74",
"OSPlatform": "Linux",
"RBACGroupID": 0,
"CVE": ["CVE-2020-12321"]
}
]
}
}
Human Readable Output
Microsoft Defender ATP machines by vulnerabilities: [‘CVE-2021-32810’, ‘CVE-2020-12321’]
ID ComputerDNSName OSPlatform RBACGroupID CVE f3bba49a ec2amaz WindowsServer2016 0 CVE-2021-32810,CVE-2020-12321 48a62a74 msde-agent-host-centos7 Linux 0 CVE-2020-12321
microsoft-atp-get-file-info
Retrieves file information by a file hash (SHA1 or SHA256).
Required Permissions
File.Read.All
Base Command
microsoft-atp-get-file-info
Input
| Argument Name | Description | Required |
|---|---|---|
| hash | A comma-separated list of file hashes (SHA1 or SHA256) used for getting the file information. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.File.Sha1 | String | The SHA1 hash of the file. |
| MicrosoftATP.File.Md5 | String | The MD5 hash of the file. |
| MicrosoftATP.File.Sha256 | String | The SHA256 hash of the file. |
| MicrosoftATP.File.GlobalPrevalence | Number | The file prevalence across the organization. |
| MicrosoftATP.File.GlobalFirstObserved | Date | The first time the file was observed. |
| MicrosoftATP.File.GlobalLastObserved | Date | The last time the file was observed. |
| MicrosoftATP.File.Size | Number | The size of the file. |
| MicrosoftATP.File.FileType | String | The type of the file. |
| MicrosoftATP.File.IsPeFile | Boolean | True if the file is portable executable, False otherwise. |
| MicrosoftATP.File.FilePublisher | String | The file’s publisher. |
| MicrosoftATP.File.FileProductName | String | The file product name. |
| MicrosoftATP.File.Signer | String | The file signer. |
| MicrosoftATP.File.Issuer | String | The file issuer. |
| MicrosoftATP.File.SignerHash | String | The hash of the signing certificate. |
| MicrosoftATP.File.IsValidCertificate | Boolean | Was signing certificate successfully verified by Microsoft Defender ATP agent. |
| MicrosoftATP.File.DeterminationValue | String | The file determination value. |
| MicrosoftATP.File.DeterminationType | String | The file determination type. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.Type | String | The file type. |
| File.Size | Number | The file size. |
Command example
!microsoft-atp-get-file-info hash="3395856ce81,db79e9e669c"
Context Example
{
"File": [
{
"Sha1": "3395856ce81",
"Sha256": "275a021bbfb648",
"Size": 68
},
{
"Sha1": "db79e9e669c",
"Sha256": "ef67e4b2bb4ee5",
"Size": 36768
}
],
"MicrosoftATP": {
"File": [
{
"DeterminationType": "Unknown",
"DeterminationValue": "Virus:DOS/EICAR_Test_File",
"GlobalFirstObserved": "2013-03-03T14:00:34.8213548Z",
"GlobalLastObserved": "2022-01-26T17:31:27.4706316Z",
"GlobalPrevalence": 37933,
"IsPeFile": false,
"Md5": "44d88612fea8a8",
"Sha1": "3395856ce81",
"Sha256": "275a021bbfb648",
"Size": 68,
"SizeInBytes": 68
},
{
"DeterminationType": "Unknown",
"GlobalFirstObserved": "2022-01-14T18:04:15.9389909Z",
"GlobalLastObserved": "2022-01-26T17:36:07.8400883Z",
"GlobalPrevalence": 8418,
"IsPeFile": false,
"Md5": "b0c6a0cfdac",
"Sha1": "db79e9e669c",
"Sha256": "ef67e4b2bb4ee5",
"Size": 36768,
"SizeInBytes": 36768
}
]
}
}
Human Readable Output
Microsoft Defender ATP file info by hashes: [‘3395856ce81’, ‘db79e9e669c’]
Sha1 Sha256 Size 3395856ce81 275a021bbfb648 68 db79e9e669c ef67e4b2bb4ee5 36768
endpoint
Gets machines that have communicated with Microsoft Defender for Endpoint cloud. At least one of the following arguments is required ip, hostanme ot id. Otherwise, an error appears.
Required Permissions
Machine.Read.All
Machine.ReadWrite.All
Base Command
endpoint
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The endpoint ID. | Optional |
| ip | The endpoint IP address. | Optional |
| hostname | The endpoint hostname. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Endpoint.ID | String | The endpoint’s identifier. |
| Endpoint.Hostname | String | The hostname of the endpoint. |
| Endpoint.OS | String | The endpoint’s operating system. |
| Endpoint.OSVersion | String | The endpoint’s operating system’s version. |
| Endpoint.IPAddress | String | The endpoint’s IP address. |
| Endpoint.Status | String | The health status of the endpoint. |
| Endpoint.MACAddress | String | The endpoint’s MAC address. |
| Endpoint.Vendor | String | The integration name of the endpoint vendor. |
| MicrosoftATP.Machine.ID | String | The machine ID. |
| MicrosoftATP.Machine.ComputerDNSName | String | The machine DNS name. |
| MicrosoftATP.Machine.FirstSeen | Date | The first date and time where the machine was observed by Microsoft Defender ATP. |
| MicrosoftATP.Machine.LastSeen | Date | The last date and time where the machine was observed by Microsoft Defender ATP. |
| MicrosoftATP.Machine.OSPlatform | String | The operating system platform. |
| MicrosoftATP.Machine.OSVersion | String | The operating system version. |
| MicrosoftATP.Machine.OSProcessor | String | The operating system processor. |
| MicrosoftATP.Machine.LastIPAddress | String | The last IP on the machine. |
| MicrosoftATP.Machine.LastExternalIPAddress | String | The last machine IP to access the internet. |
| MicrosoftATP.Machine.OSBuild | Number | The operating system build number. |
| MicrosoftATP.Machine.HealthStatus | String | The machine health status. |
| MicrosoftATP.Machine.RBACGroupID | Number | The machine RBAC group ID. |
| MicrosoftATP.Machine.RBACGroupName | String | The machine RBAC group name. |
| MicrosoftATP.Machine.RiskScore | String | The machine risk score. |
| MicrosoftATP.Machine.ExposureLevel | String | The machine exposure score. |
| MicrosoftATP.Machine.IsAADJoined | Boolean | True if machine is AAD joined, False otherwise. |
| MicrosoftATP.Machine.AADDeviceID | String | The AAD Device ID. |
| MicrosoftATP.Machine.MachineTags | String | Set of machine tags. |
| MicrosoftATP.Machine.IPAddresses.ipAddress | String | The machine IP address. |
| MicrosoftATP.Machine.IPAddresses.MACAddress | String | The machine MAC address. |
| MicrosoftATP.Machine.IPAddresses.operationalStatus | String | The machine operational status. |
| MicrosoftATP.Machine.IPAddresses.type | String | The machine macine IP address type. |
| MicrosoftATP.Machine.AgentVersion | String | The machine Agent version. |
Command example
!endpoint id="f3bba49a,48a62a74"ip=1.2.3.4 hostname="ec2amaz-ua9hieu"
Context Example
{
"Endpoint": [
{
"Hostname": "msde-agent-host-centos7.c.dmst-integrations.internal",
"ID": "48a62a74",
"IPAddress": "10.0.0.1",
"MACAddress": "123456789123",
"OS": "CentOS",
"OSVersion": "7.9 x64 bit",
"Status": "Online",
"Vendor": "Microsoft Defender ATP"
},
{
"Hostname": "ec2amaz-ua9hieu",
"ID": "f3bba49a",
"IPAddress": "1.2.3.4",
"MACAddress": "123456789123",
"OS": "WindowsServer2016",
"OSVersion": "1607 x64 bit",
"Status": "Online",
"Vendor": "Microsoft Defender ATP"
}
],
"MicrosoftATP": {
"Machine": [
{
"AgentVersion": "30.121112.15302.0",
"ComputerDNSName": "msde-agent-host-centos7.c.dmst-integrations.internal",
"ExposureLevel": "Medium",
"FirstSeen": "2022-01-23T09:13:42.982Z",
"HealthStatus": "Active",
"ID": "48a62a74",
"IPAddresses": [
{
"ipAddress": "10.0.0.1",
"macAddress": "123456789123",
"operationalStatus": "Up",
"type": "Other"
},
{
"ipAddress": "fe80::178b:6498:fc7f:2856",
"macAddress": "123456789123",
"operationalStatus": "Up",
"type": "Other"
},
{
"ipAddress": "127.0.0.1",
"macAddress": "000000000000",
"operationalStatus": "Up",
"type": "Other"
},
{
"ipAddress": "::1",
"macAddress": "000000000000",
"operationalStatus": "Up",
"type": "Other"
}
],
"IsAADJoined": false,
"LastExternalIPAddress": "127.0.0.1",
"LastIPAddress": "10.0.0.1",
"LastSeen": "2022-01-27T09:13:53.1394181Z",
"MACAddress": "123456789123",
"OSPlatform": "CentOS",
"OSProcessor": "x64",
"OSVersion": "7.9",
"RBACGroupID": 0,
"RiskScore": "Medium"
},
{
"AgentVersion": "10.3720.16299.2015",
"ComputerDNSName": "ec2amaz-ua9hieu",
"ExposureLevel": "High",
"FirstSeen": "2022-01-23T15:36:02.286Z",
"HealthStatus": "Active",
"ID": "f3bba49a",
"IPAddresses": [
{
"ipAddress": "1.2.3.4",
"macAddress": "123456789123",
"operationalStatus": "Up",
"type": "Ethernet"
},
{
"ipAddress": "fe80::a998:1c4a:7e1c:4865",
"macAddress": "123456789123",
"operationalStatus": "Up",
"type": "Ethernet"
},
{
"ipAddress": "127.0.0.1",
"macAddress": "",
"operationalStatus": "Up",
"type": "SoftwareLoopback"
},
{
"ipAddress": "::1",
"macAddress": "",
"operationalStatus": "Up",
"type": "SoftwareLoopback"
},
{
"ipAddress": "fe80::5efe:1.2.3.4",
"macAddress": "00000000000000E0",
"operationalStatus": "Down",
"type": "Tunnel"
},
{
"ipAddress": "127.0.0.1",
"macAddress": "00000000000000E0",
"operationalStatus": "Up",
"type": "Tunnel"
},
{
"ipAddress": "fe80::2412:1420:53e0:f88b",
"macAddress": "00000000000000E0",
"operationalStatus": "Up",
"type": "Tunnel"
}
],
"IsAADJoined": false,
"LastExternalIPAddress": "127.0.0.1",
"LastIPAddress": "1.2.3.4",
"LastSeen": "2022-01-26T22:21:19.2024139Z",
"MACAddress": "123456789123",
"OSBuild": 14393,
"OSPlatform": "WindowsServer2016",
"OSProcessor": "x64",
"OSVersion": "1607",
"RBACGroupID": 0,
"RiskScore": "None"
}
]
}
}
Human Readable Output
Microsoft Defender ATP Machine
ID ComputerDNSName OSPlatform LastIPAddress LastExternalIPAddress HealthStatus RiskScore ExposureLevel f3bba49a ec2amaz-ua9hieu WindowsServer2016 1.2.3.4 127.0.0.1 Active None High
microsoft-atp-indicator-batch-update
Updates batch of indicator. If an indicator does not exist, a new indicator will be created.
Required Permissions
Ti.ReadWrite
Ti.ReadWrite.All
Limitations
- Rate limitations for this API are 30 calls per minute.
- There is a limit of 15,000 active indicators per tenant.
- Maximum batch size for one API call is 500.
Note
Please read here about the Microsoft Defender for Endpoint indicator resource type.
We suggest using the TransformIndicatorToMSDefenderIOC automation to load the XSOAR IOCs to MSDE indicator format.
Base Command
microsoft-atp-indicator-batch-update
Input
| Argument Name | Description | Required |
|---|---|---|
| indicator_batch | A JSON object with a list of MS defender ATP indicators to update. The indicator_batch query should be a list of dictionaries. For example: [{“indicatorValue”: “value1”}, {“indicatorValue”: “value2”}]. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Indicators.ID | String | Created by the system when the indicator is ingested. Generated GUID/unique identifier. |
| MicrosoftATP.Indicators.Value | String | The value of the indicator. |
| MicrosoftATP.Indicators.FailureReason | String | The reason for update failure. |
| MicrosoftATP.Indicators.IsFailed | Boolean | Whether the update failed. |
Command example
!microsoft-atp-indicator-batch-update indicator_batch=`[{"indicatorValue": "220e7d15b011d7fac48f2bd61114db1022197f7f","indicatorType": "FileSha1","title": "demo","application": "demo-test", "action": "Alert","severity": "Informational","description": "demo2","recommendedActions": "nothing","rbacGroupNames": ["group1", "group2"]},{"indicatorValue": "2233223322332233223322332233223322332233223322332233223322332222","indicatorType": "FileSha256","title": "demo2","application": "demo-test2","action": "Alert","severity": "Medium","description": "demo2","recommendedActions": "nothing","rbacGroupNames": []}]`
Context Example
{
"MicrosoftATP": {
"Indicators": [
{
"FailureReason": null,
"ID": "5217",
"IsFailed": false,
"Value": "220e7d15b011d7fac48f2bd61114db1022197f7f"
},
{
"FailureReason": null,
"ID": "5218",
"IsFailed": false,
"Value": "2233223322332233223322332233223322332233223322332233223322332222"
}
]
}
}
Human Readable Output
Indicators updated successfully
ID Value IsFailed 5217 220e7d15b011d7fac48f2bd61114db1022197f7f false 5218 2233223322332233223322332233223322332233223322332233223322332222 false
microsoft-atp-get-alert-by-id (Deprecated)
This command has been deprecated. Use ‘msg-get-alert-details’ in the ‘Microsoft Graph Security’ integration instead.
Retrieves specific alert by the given alert ID.
Required Permissions
Alert.ReadWrite.All
Base Command
microsoft-atp-get-alert-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_ids | A comma-separated list of alert IDs. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Alert.ID | String | The alert ID. |
| MicrosoftATP.Alert.IncidentID | Number | The incident ID of the alert. |
| MicrosoftATP.Alert.InvestigationID | Number | The investigation ID related to the alert. |
| MicrosoftATP.Alert.InvestigationState | String | The current state of the Investigation. |
| MicrosoftATP.Alert.AssignedTo | String | The owner of the alert. |
| MicrosoftATP.Alert.Severity | String | The severity of the alert. |
| MicrosoftATP.Alert.Status | String | The current status of the alert. |
| MicrosoftATP.Alert.Classification | String | The alert Classification. |
| MicrosoftATP.Alert.Determination | String | The determination of the alert. |
| MicrosoftATP.Alert.DetectionSource | String | The detection source. |
| MicrosoftATP.Alert.Category | String | The category of the alert. |
| MicrosoftATP.Alert.ThreatFamilyName | String | The threat family. |
| MicrosoftATP.Alert.Title | String | The alert title. |
| MicrosoftATP.Alert.Description | String | The alert description. |
| MicrosoftATP.Alert.AlertCreationTime | Date | The date and time the alert was created. |
| MicrosoftATP.Alert.FirstEventTime | Date | The first event time that triggered the alert on that machine. |
| MicrosoftATP.Alert.LastEventTime | Date | The last event time that triggered the alert on that machine. |
| MicrosoftATP.Alert.LastUpdateTime | Date | The UTC time of the last update. |
| MicrosoftATP.Alert.ResolvedTime | Date | The date and time when the status of the alert was changed to ‘Resolved’. |
| MicrosoftATP.Alert.MachineID | String | The machine ID that is associated with the alert. |
| MicrosoftATP.Alert.ComputerDNSName | String | The machine DNS name. |
| MicrosoftATP.Alert.AADTenantID | String | The AAD tenant ID. |
| MicrosoftATP.Alert.Comments.Comment | String | The alert comment string. |
| MicrosoftATP.Alert.Comments.CreatedBy | String | The alert comment created by string. |
| MicrosoftATP.Alert.Comments.CreatedTime | Date | The alert comment created time date. |
| MicrosoftATP.Alert.Evidence | Unknown | Evidence related to the alert. |
| MicrosoftATP.Alert.DetectorID | String | The ID of the detector that triggered the alert. |
| MicrosoftATP.Alert.ThreatName | String | The threat name. |
| MicrosoftATP.Alert.RelatedUser | String | Details of the user related to a specific alert. |
| MicrosoftATP.Alert.MitreTechniques | String | MITRE Enterprise technique ID. |
| MicrosoftATP.Alert.RBACGroupName | String | The device RBAC group name. |
Command example
!microsoft-atp-get-alert-by-id alert_ids=da637797972607470400_795854214,da637750706361180181_-1167994114
Context Example
{
"MicrosoftATP": {
"Alert": [
{
"AADTenantID": "ebac1a16-81bf-449b-8d43-5732c3c1d999",
"AlertCreationTime": "2022-02-07T02:21:00.7470678Z",
"AssignedTo": "Automation",
"Category": "SuspiciousActivity",
"Classification": null,
"Comments": [
{
"Comment": null,
"CreatedBy": null,
"CreatedTime": null
}
],
"ComputerDNSName": "msde-agent-host-win2016-dc.msde.lab.demisto",
"Description": "MS Graph ATP (Application Id: 1281a70f-8ffb-4b3c-bc82-eef2a44dbb2a) initiated an Automated investigation on msde-agent-host-win2016-dc.msde.lab.demisto.\r\nThe investigation automatically identifies and reviews threat artifacts for possible remediation.\r\n\r\nDetails: testing",
"DetectionSource": "AutomatedInvestigation",
"DetectorID": "5c6b7d86-c91f-4f8c-8aec-9d2086f46527",
"Determination": null,
"Evidence": [],
"FirstEventTime": "2022-02-07T02:21:00.6440488Z",
"ID": "da637797972607470400_795854214",
"IncidentID": 645,
"InvestigationID": 656,
"InvestigationState": "Benign",
"LastEventTime": "2022-02-07T02:21:00.6440488Z",
"LastUpdateTime": "2022-02-07T02:53:34.76Z",
"MachineID": "96444b946be252d1f4550354edef5fdc23aca2c5",
"MitreTechniques": [],
"RBACGroupName": null,
"RelatedUser": null,
"ResolvedTime": "2022-02-07T02:53:34.7299762Z",
"Severity": "Informational",
"Status": "Resolved",
"ThreatFamilyName": null,
"ThreatName": null,
"Title": "Automated investigation started manually"
},
{
"AADTenantID": "ebac1a16-81bf-449b-8d43-5732c3c1d999",
"AlertCreationTime": "2021-12-14T09:23:56.0980302Z",
"AssignedTo": "Automation",
"Category": "SuspiciousActivity",
"Classification": "TruePositive",
"Comments": [
{
"Comment": null,
"CreatedBy": null,
"CreatedTime": null
}
],
"ComputerDNSName": "desktop-s2455r8",
"Description": "MS Graph ATP (Application Id: 1281a70f-8ffb-4b3c-bc82-eef2a44dbb2a) initiated an Automated investigation on desktop-s2455r8.\r\nThe investigation automatically identifies and reviews threat artifacts for possible remediation.\r\n\r\nDetails: testing",
"DetectionSource": "AutomatedInvestigation",
"DetectorID": "5c6b7d86-c91f-4f8c-8aec-9d2086f46527",
"Determination": null,
"Evidence": [],
"FirstEventTime": "2021-12-14T09:23:55.875227Z",
"ID": "da637750706361180181_-1167994114",
"IncidentID": 510,
"InvestigationID": 441,
"InvestigationState": "Benign",
"LastEventTime": "2021-12-14T09:23:55.875227Z",
"LastUpdateTime": "2021-12-15T01:52:41.3Z",
"MachineID": "4899036531e374137f63289c3267bad772c13fef",
"MitreTechniques": [],
"RBACGroupName": null,
"RelatedUser": null,
"ResolvedTime": "2021-12-14T09:52:16.8080395Z",
"Severity": "Informational",
"Status": "Resolved",
"ThreatFamilyName": null,
"ThreatName": null,
"Title": "Automated investigation started manually"
}
]
}
}
Human Readable Output
Microsoft Defender ATP Alerts Info for IDs [‘da637797972607470400795854214’, ‘da637750706361180181-1167994114’]
ID Title Description IncidentID Severity Status Classification Category MachineID da637797972607470400_795854214 Automated investigation started manually MS Graph ATP (Application Id: 1281a70f-8ffb-4b3c-bc82-eef2a44dbb2a) initiated an Automated investigation on msde-agent-host-win2016-dc.msde.lab.demisto.
The investigation automatically identifies and reviews threat artifacts for possible remediation.
Details: testing645 Informational Resolved SuspiciousActivity 96444b946be252d1f4550354edef5fdc23aca2c5 da637750706361180181_-1167994114 Automated investigation started manually MS Graph ATP (Application Id: 1281a70f-8ffb-4b3c-bc82-eef2a44dbb2a) initiated an Automated investigation on desktop-s2455r8.
The investigation automatically identifies and reviews threat artifacts for possible remediation.
Details: testing510 Informational Resolved TruePositive SuspiciousActivity 4899036531e374137f63289c3267bad772c13fef
microsoft-atp-live-response-put-file
Puts a file from the library to the device. Files are saved in a working folder and are deleted when the device restarts by default.
Base Command
microsoft-atp-live-response-put-file
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | Machine ID to add file to. | Required |
| comment | A comment to associate with the action. | Required |
| file_name | File name to take from library to device. | Required |
| machine_action_id | Action ID to retrieve status and data for. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.LiveResponseAction.id | String | The machine action ID. |
| MicrosoftATP.LiveResponseAction.type | String | The machine action type. |
| MicrosoftATP.LiveResponseAction.title | String | The machine action title. |
| MicrosoftATP.LiveResponseAction.requestor | String | The machine action requestor. |
| MicrosoftATP.LiveResponseAction.requestorComment | String | The machine action requestorComment. |
| MicrosoftATP.LiveResponseAction.status | String | The machine action status. |
| MicrosoftATP.LiveResponseAction.machineId | String | The machine ID. |
| MicrosoftATP.LiveResponseAction.computerDnsName | String | The computerDnsName. |
| MicrosoftATP.LiveResponseAction.creationDateTimeUtc | Date | The action creationDateTimeUtc. |
| MicrosoftATP.LiveResponseAction.lastUpdateDateTimeUtc | Date | The machine action lastUpdateDateTimeUtc. |
| MicrosoftATP.LiveResponseAction.cancellationRequestor | String | The machine action cancellationRequestor. |
| MicrosoftATP.LiveResponseAction.cancellationComment | String | The machine action cancellationComment. |
| MicrosoftATP.LiveResponseAction.cancellationDateTimeUtc | String | The cancellationDateTimeUtc. |
| MicrosoftATP.LiveResponseAction.errorHResult | String | The errorHResult if exists. |
| MicrosoftATP.LiveResponseAction.scope | String | The action scope. |
| MicrosoftATP.LiveResponseAction.externalId | String | The machine action externalId. |
| MicrosoftATP.LiveResponseAction.requestSource | String | The machine action requestSource. |
| MicrosoftATP.LiveResponseAction.relatedFileInfo | String | The machine action relatedFileInfo. |
| MicrosoftATP.LiveResponseAction.commands.index | String | The machine action command index. |
| MicrosoftATP.LiveResponseAction.commands.startTime | String | The machine action command startTime. |
| MicrosoftATP.LiveResponseAction.commands.endTime | String | The machine action command endTime. |
| MicrosoftATP.LiveResponseAction.commands.commandStatus | String | The machine action command Status. |
| MicrosoftATP.LiveResponseAction.commands.errors | String | The machine action command errors if found. |
| MicrosoftATP.LiveResponseAction.commands.command.type | String | The machine action command type. |
| MicrosoftATP.LiveResponseAction.commands.command.params.key | String | The machine action command params key. |
| MicrosoftATP.LiveResponseAction.commands.command.params.value | String | The machine action command params value. |
| MicrosoftATP.LiveResponseAction.troubleshootInfo | String | The machine action troubleshootInfo. |
Command example
!microsoft-atp-live-response-put-file machine_id="4899036531e374137f63289c3267bad772c13fef" comment="testing" file_name="C:\Users\demisto\Desktop\test.txt"
Context Example
{
"MicrosoftATP": {
"LiveResponseAction": {
"@odata.context": "https://api-us.securitycenter.microsoft.com/api/$metadata#MachineActions/$entity",
"cancellationComment": null,
"cancellationDateTimeUtc": null,
"cancellationRequestor": null,
"commands": [
{
"command": {
"params": [
{
"key": "FileName",
"value": "C:\Users\demisto\Desktop\test.txt"
}
],
"type": "PutFile"
},
"commandStatus": "Created",
"endTime": null,
"errors": [],
"index": 0,
"startTime": null
}
],
"computerDnsName": "desktop-s2455r8",
"creationDateTimeUtc": "2022-02-07T10:32:14.1704612Z",
"errorHResult": 0,
"externalId": null,
"id": "20d1de3f-acef-4715-8bed-a92223c5553c",
"lastUpdateDateTimeUtc": "2022-02-07T10:32:14.1704612Z",
"machineId": "4899036531e374137f63289c3267bad772c13fef",
"relatedFileInfo": null,
"requestSource": "PublicApi",
"requestor": "2f48b784-5da5-4e61-9957-012d2630f1e4",
"requestorComment": "testing",
"scope": null,
"status": "Pending",
"title": null,
"troubleshootInfo": null,
"type": "LiveResponse"
}
}
}
Human Readable Output
Machine Action
Commands Creation time Hostname Machine Action Id MachineId Status {‘index’: 0, ‘startTime’: None, ‘endTime’: None, ‘commandStatus’: ‘Created’, ‘errors’: [], ‘command’: {‘type’: ‘PutFile’, ‘params’: [{‘key’: ‘FileName’, ‘value’: ‘C:\Users\demisto\Desktop\test.txt’}]}} 2022-02-07T10:32:14.1704612Z desktop-s2455r8 20d1de3f-acef-4715-8bed-a92223c5553c 4899036531e374137f63289c3267bad772c13fef Failed
microsoft-atp-live-response-run-script
Runs a script from the library on a device. The Args parameter is passed to your script. Timeouts after 10 minutes.
Base Command
microsoft-atp-live-response-run-script
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | Machine ID to add file to. | Required |
| comment | A comment to associate with the action. | Required |
| scriptName | Script name to run on device. | Required |
| arguments | Arguments to run the script with. | Optional |
| machine_action_id | Action ID to retrieve status and data for. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.LiveResponseAction.script_name | String | The script name. |
| MicrosoftATP.LiveResponseAction.exit_code | String | The script exit code. |
| MicrosoftATP.LiveResponseAction.script_output | String | The script outputs. |
| MicrosoftATP.LiveResponseAction.script_errors | String | The script errors if found. |
microsoft-atp-live-response-get-file
Collect file from a device. NOTE: Backslashes in path must be escaped.
Base Command
microsoft-atp-live-response-get-file
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | Machine ID to add file to. | Required |
| comment | A comment to associate with the action. | Required |
| path | File path to get from device. | Required |
| machine_action_id | Action ID to retrieve status and data for. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.LiveResponseAction.id | String | The machine action ID. |
| MicrosoftATP.LiveResponseAction.type | String | The machine action type. |
| MicrosoftATP.LiveResponseAction.title | String | The machine action title. |
| MicrosoftATP.LiveResponseAction.requestor | String | The machine action requestor. |
| MicrosoftATP.LiveResponseAction.requestorComment | String | The machine action requestorComment. |
| MicrosoftATP.LiveResponseAction.status | String | The machine action status. |
| MicrosoftATP.LiveResponseAction.machineId | String | The machine ID. |
| MicrosoftATP.LiveResponseAction.computerDnsName | String | The computerDnsName. |
| MicrosoftATP.LiveResponseAction.creationDateTimeUtc | Date | The action creationDateTimeUtc. |
| MicrosoftATP.LiveResponseAction.lastUpdateDateTimeUtc | Date | The machine action lastUpdateDateTimeUtc. |
| MicrosoftATP.LiveResponseAction.cancellationRequestor | String | The machine action cancellationRequestor. |
| MicrosoftATP.LiveResponseAction.cancellationComment | String | The machine action cancellationComment. |
| MicrosoftATP.LiveResponseAction.cancellationDateTimeUtc | String | The cancellationDateTimeUtc. |
| MicrosoftATP.LiveResponseAction.errorHResult | String | The errorHResult if exists. |
| MicrosoftATP.LiveResponseAction.scope | String | The action scope. |
| MicrosoftATP.LiveResponseAction.externalId | String | The machine action externalId. |
| MicrosoftATP.LiveResponseAction.requestSource | String | The machine action requestSource. |
| MicrosoftATP.LiveResponseAction.relatedFileInfo | String | The machine action relatedFileInfo. |
| MicrosoftATP.LiveResponseAction.commands.index | String | The machine action command index. |
| MicrosoftATP.LiveResponseAction.commands.startTime | String | The machine action command startTime. |
| MicrosoftATP.LiveResponseAction.commands.endTime | String | The machine action command endTime. |
| MicrosoftATP.LiveResponseAction.commands.commandStatus | String | The machine action command Status. |
| MicrosoftATP.LiveResponseAction.commands.errors | String | The machine action command errors if found. |
| MicrosoftATP.LiveResponseAction.commands.command.type | String | The machine action command type. |
| MicrosoftATP.LiveResponseAction.commands.command.params.key | String | The machine action command params key. |
| MicrosoftATP.LiveResponseAction.commands.command.params.value | String | The machine action command params value. |
| MicrosoftATP.LiveResponseAction.troubleshootInfo | String | The machine action troubleshootInfo. |
microsoft-atp-live-response-result
Gets a result file for a specified action.
Base Command
microsoft-atp-live-response-result
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_action_id | Action ID to retrieve status and data for. | Required |
| command_index | A command index to retrieve file for. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.LiveResponseAction | String | The machine action ID. |
Command example
!microsoft-atp-live-response-result machine_action_id=11a86b87-12b8-423b-9e8d-9775ab2da78f command_index=0
Context Example
{
"File": {
"EntryID": "230@c1c0b1a7-2a6b-40be-8479-7399ee467a6b",
"Info": "application/json",
"MD5": "1f2bc070ced88de8c80323acfcdbd33c",
"Name": "Response Result",
"SHA1": "eb7568c1342d7fac8c570e53e2ce8103025b605b",
"SHA256": "9df3ced59fd1f346aad035016beb5ebf89838b2f02b1610ee7e0cbfd396cbf02",
"SHA512": "a62de5d64827f60a9885e95658d203f4a7eb7d070873a0379c5ac52d8b013fc12c0e9187c3f83103dcb1bf937d88bf0b48f32f77e72ead30231e5eefca681de9",
"SSDeep": "6:YWGc00ZR/+MqifdvuxAbimLPsYRa7+R98A7V/NJviD5BW+yWrbmD3he6an:YWGb0ZRmKQODYqa7+X7XSB9y+bmhan",
"Size": 293,
"Type": "JSON data"
},
"MicrosoftATP": {
"LiveResponseResult": {
"exit_code": 0,
"script_errors": "",
"script_name": "test_script.ps1",
"script_output": "Transcript started, output file is C:\\ProgramData\\Microsoft\\Windows Defender Advanced Threat Protection\\Temp\\PSScriptOutputs\\PSScript_Transcript_{1954B499-1836-4928-90A2-86DE508BD1B0}.txt\n\u0000"
}
}
}
Human Readable Output
file_link: https://automatedirstrprdeus.blob.core.windows.net/investigation-actions-data/b7df6ab7-5c73-4e13-8cd3-82e1f3d849ed/CustomPlaybookCommandOutput/7ef257a5069c45fe790be86d479d1518?se=2022-02-07T14%3A33%3A07Z&sp=rt&sv=2020-06-12&sr=b&rscd=attachment%3B%20filename%3Doutput_11a86b87-12b8-423b-9e8d-9775ab2da78f_0.json&skoid=34334208-452d-4d6d-afc6-0c319d62a726&sktid=124edf19-b350-4797-aefc-3206115ffdb3&skt=2022-02-07T13%3A48%3A07Z&ske=2022-02-07T14%3A33%3A07Z&sks=b&skv=2020-06-12&sig=IRxMKavzQqHplTsAL350holkkm%2B3NI2mhUUWxaHbOAM%3D
microsoft-atp-advanced-hunting-lateral-movement-evidence
NOTE: This endpoint will be deprecated by Microsoft on January 31, 2027. We recommend switching to the Microsoft Graph Security Integration and using the msg-advanced-hunting command. For more information, see the Microsoft documentation
Detects evidence of attempted lateral movement. When you select a “query_purpose” argument, a designated query template is used.
Base Command
microsoft-atp-advanced-hunting-lateral-movement-evidence
Input
| Argument Name | Description | Required |
|---|---|---|
| query_purpose | When you select a “query_purpose” argument, a designated query template is used. “network_connections” - The network connections initiated by the host/file to other internal hosts. “smb_connections” - SMB connections. “credential_dumping” - Was there a use of credential dumping? If so can we detect the use of the dumped users on other hosts on the network. “management_connection” - Management connection attempts to other hosts. | Required |
| device_name | Device name to look for. | Optional |
| remote_ip_count | Threshold for network enumeration in smb_connection. | Optional |
| file_name | File name to look for. | Optional |
| sha1 | SHA1 hash to look for. | Optional |
| sha256 | SHA256 hash to look for. | Optional |
| md5 | MD5 hash to look for. | Optional |
| device_id | Device ID to look for. | Optional |
| query_operation | Query operator to use with provided arguments. Possible values are: or, and. Default is or. | Optional |
| limit | The maximum number of results to retrieve. Default is 50. | Optional |
| time_range | Time range to look back. Expected syntax is a human readable time range, e.g. 60 minutes, 6 hours, 1 day, etc. | Optional |
| timeout | The amount of time (in seconds) that a request waits for the query response before a timeout occurs. Default is 10. | Optional |
| page | The page number from which to start a search. Default is 1. | Optional |
| show_query | Show the query as part of the entry result. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.HuntLateralMovementEvidence.Result.network_connections | String | The query results for network_connections query_purpose. |
| MicrosoftATP.HuntLateralMovementEvidence.Result.smb_connections | String | The query results for smb_connections query_purpose. |
| MicrosoftATP.HuntLateralMovementEvidence.Result.credential_dumping | String | The query results for credential_dumping query_purpose. |
| MicrosoftATP.HuntLateralMovementEvidence.Result.management_connection | String | The query results for management_connection query_purpose. |
Command example
!microsoft-atp-advanced-hunting-lateral-movement-evidence query_purpose=network_connections device_name=devicename_2,devicename_1 limit=6
Context Example
{
"MicrosoftATP": {
"HuntLateralMovementEvidence": {
"Result": {
"network_connections": [
{
"DeviceName": "devicename_2",
"InitiatingProcessFileName": "",
"RemoteIP": "ip1",
"RemotePort": 54296,
"TotalConnections": 21
}
]
}
}
}
}
Human Readable Output
Lateral Movement Evidence Hunt (network_connections) Results
DeviceName RemoteIP RemotePort TotalConnections devicename_2 ip1 54296 21
Command example
!microsoft-atp-advanced-hunting-lateral-movement-evidence query_purpose=smb_connections device_name=devicename_1
Context Example
{
"MicrosoftATP": {
"HuntLateralMovementEvidence": {
"Result": {
"smb_connections": [
{
"DeviceName": "devicename_1",
"InitiatingProcessCreationTime": "2022-03-03T19:43:46.4373311Z",
"InitiatingProcessFileName": "powershell.exe",
"InitiatingProcessId": 5748,
"RemoteIPCount": 5
},
{
"DeviceName": "devicename_1",
"InitiatingProcessCreationTime": "2022-03-03T19:51:43.2411889Z",
"InitiatingProcessFileName": "powershell_ise.exe",
"InitiatingProcessId": 10084,
"RemoteIPCount": 17
}
]
}
}
}
}
Human Readable Output
Lateral Movement Evidence Hunt (smb_connections) Results
DeviceName InitiatingProcessCreationTime InitiatingProcessFileName InitiatingProcessId RemoteIPCount devicename_1 2022-03-03T19:43:46.4373311Z powershell.exe 5748 5 devicename_1 2022-03-03T19:51:43.2411889Z powershell_ise.exe 10084 17
Command example
!microsoft-atp-advanced-hunting-lateral-movement-evidence query_purpose="management_connection" device_id="4cceb3c642212014e0e9553aa8b59e999ea515ff" query_operation="or" limit="50" timeout="10"
Context Example
{
"MicrosoftATP": {
"HuntLateralMovementEvidence": {
"Result": {
"management_connection": [
{
"DeviceName": "device_name",
"LocalIP": "ip3",
"RemoteIP": "ip4",
"RemotePort": 135,
"TotalCount": 41
},
{
"DeviceName": "device_name",
"LocalIP": "ip3",
"RemoteIP": "ip3",
"RemotePort": 139,
"TotalCount": 1
}
]
}
}
}
}
Human Readable Output
Lateral Movement Evidence Hunt (management_connection) Results
DeviceName LocalIP RemoteIP RemotePort TotalCount device_name ip3 ip4 135 41 device_name ip3 ip3 139 1
microsoft-atp-advanced-hunting-persistence-evidence
NOTE: This endpoint will be deprecated by Microsoft on January 31, 2027. We recommend switching to the Microsoft Graph Security Integration and using the msg-advanced-hunting command. For more information, see the Microsoft documentation
Detects evidence of persistence. When you select a “query_purpose” argument, a designated query template is used.
Base Command
microsoft-atp-advanced-hunting-persistence-evidence
Input
| Argument Name | Description | Required |
|---|---|---|
| query_purpose | When you select a “query_purpose” argument, a designated query template is used. “scheduled_job” - Did the process create any scheduled jobs? “registry_entry” - Did it write to the registry? Requires also argument process_cmd to be provided. “startup_folder_changes” - Was anything added to the startup folder? “new_service_created” - Was a new service created? “service_updated” - Was an existing service edited? “file_replaced” - Was a file replaced in program files? “new_user” - Was a new user created? (On the local machine). “new_group” - Was a new group created? “group_user_change” - Was a user added to a group? (On the local machine) “local_firewall_change” - Was there a change to the local FW rules? “host_file_change” - Was there a change to the hosts file?. Possible values are: scheduled_job, registry_entry, startup_folder_changes, new_service_created, service_updated, file_replaced, new_user, new_group, group_user_change, local_firewall_change, host_file_change. | Required |
| device_name | Device name to look for. | Optional |
| file_name | File name to look for. | Optional |
| sha1 | SHA1 hash to look for. | Optional |
| sha256 | SHA256 hash to look for. | Optional |
| md5 | MD5 hash to look for. | Optional |
| device_id | Device ID to look for. | Optional |
| query_operation | Query operator to use with provided arguments. Possible values are: or, and. Default is or. | Optional |
| limit | Maximum number of results to retrieve. Default is 50. | Optional |
| time_range | Time range to look back. Expected syntax is a human readable time range, e.g. 60 minutes, 6 hours, 1 day, etc. | Optional |
| timeout | The amount of time (in seconds) that a request waits for the query response before a timeout occurs. Default is 10. | Optional |
| process_cmd | Proccess command line that initiated the registry entry. Can only be used with “registry_entry” query_purpose. | Optional |
| page | The page number from which to start a search. Default is 1. | Optional |
| show_query | Show the query as part of the entry result. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.HuntPersistenceEvidence.Result.scheduled_job | String | The query results for scheduled_job query_purpose. |
| MicrosoftATP.HuntPersistenceEvidence.Result.registry_entry | String | The query results for registry_entry query_purpose. |
| MicrosoftATP.HuntPersistenceEvidence.Result.startup_folder_changes | String | The query results for startup_folder_changes query_purpose. |
| MicrosoftATP.HuntPersistenceEvidence.Result.new_service_created | String | The query results for new_service_created query_purpose. |
| MicrosoftATP.HuntPersistenceEvidence.Result.service_updated | String | The query results for service_updated query_purpose. |
| MicrosoftATP.HuntPersistenceEvidence.Result.file_replaced | String | The query results for file_replaced query_purpose. |
| MicrosoftATP.HuntPersistenceEvidence.Result.new_user | String | The query results for new_user query_purpose. |
| MicrosoftATP.HuntPersistenceEvidence.Result.new_group | String | The query results for new_group query_purpose. |
| MicrosoftATP.HuntPersistenceEvidence.Result.group_user_change | String | The query results for group_user_change query_purpose. |
| MicrosoftATP.HuntPersistenceEvidence.Result.local_firewall_change | String | The query results for local_firewall_change query_purpose. |
| MicrosoftATP.HuntPersistenceEvidence.Result.host_file_change | String | The query results for host_file_change query_purpose. |
Command example
!microsoft-atp-advanced-hunting-persistence-evidence query_purpose=scheduled_job device_name=devicename_2 device_id=4cceb3c642212014e0e9553aa8b59e999ea515ff,96444b946be252d1f4550354edef5fdc23aca2c5 query_operation=or
Human Readable Output
Persistence EvidenceHunt Hunt (scheduled_job) Results
No entries.
Command example
!microsoft-atp-advanced-hunting-persistence-evidence query_purpose=new_service_created file_name=installer,services
Context Example
{
"MicrosoftATP": {
"HuntPersistenceEvidence": {
"Result": {
"new_service_created": [
{
"DeviceName": "devicename_2",
"InitiatingProcessCommandLine": "services.exe",
"InitiatingProcessFileName": "services.exe",
"InitiatingProcessVersionInfoOriginalFileName": "services.exe",
"InitiatingProcessVersionInfoProductName": "Microsoft\u00ae Windows\u00ae Operating System",
"RegistryKey": "HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\MpKsl49022091",
"RegistryValueData": "",
"RegistryValueName": "",
"RegistryValueType": "None",
"Timestamp": "2022-03-12T00:45:51.2745622Z"
},
{
"DeviceName": "devicename_2",
"InitiatingProcessCommandLine": "services.exe",
"InitiatingProcessFileName": "services.exe",
"InitiatingProcessVersionInfoOriginalFileName": "services.exe",
"InitiatingProcessVersionInfoProductName": "Microsoft\u00ae Windows\u00ae Operating System",
"RegistryKey": "HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\MpKsl897892ef",
"RegistryValueData": "",
"RegistryValueName": "",
"RegistryValueType": "None",
"Timestamp": "2022-03-13T00:45:49.9561415Z"
}
]
}
}
}
}
Human Readable Output
Persistence EvidenceHunt Hunt (new_service_created) Results
DeviceName InitiatingProcessCommandLine InitiatingProcessFileName InitiatingProcessVersionInfoOriginalFileName InitiatingProcessVersionInfoProductName RegistryKey RegistryValueType Timestamp devicename_2 services.exe services.exe services.exe Microsoft® Windows® Operating System HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\MpKsl49022091 None 2022-03-12T00:45:51.2745622Z devicename_2 services.exe services.exe services.exe Microsoft® Windows® Operating System HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\MpKsl897892ef None 2022-03-13T00:45:49.9561415Z
Command example
!microsoft-atp-advanced-hunting-persistence-evidence query_purpose=new_user device_name=desktop
Context Example
{
"MicrosoftATP": {
"HuntPersistenceEvidence": {
"Result": {
"new_user": [
{
"AccountDomain": "devicename_1",
"AccountName": "delete_me",
"AccountSid": "accound-sid",
"DeviceName": "devicename_1",
"InitiatingProcessAccountName": "demisto",
"InitiatingProcessLogonId": 74706995,
"Timestamp": "2022-03-03T21:25:52.4538765Z"
}
]
}
}
}
}
Human Readable Output
Persistence EvidenceHunt Hunt (new_user) Results
AccountDomain AccountName AccountSid DeviceName InitiatingProcessAccountName InitiatingProcessLogonId Timestamp devicename_1 delete_me accound-sid devicename_1 demisto 74706995 2022-03-03T21:25:52.4538765Z
Command example
!microsoft-atp-advanced-hunting-persistence-evidence query_purpose=new_group device_id=deviceid device_name=desktop query_operation=and
Context Example
{
"MicrosoftATP": {
"HuntPersistenceEvidence": {
"Result": {
"new_group": [
{
"AccountDomain": "",
"AccountName": "",
"AccountSid": "",
"AdditionalFields": "{\"GroupName\":\"Test_group_delete\",\"GroupDomainName\":\"devicename_1\",\"GroupSid\":\"S-1-5-21-4197691174-1403503641-4006700887-1006\"}",
"DeviceName": "devicename_1",
"InitiatingProcessAccountName": "demisto",
"InitiatingProcessLogonId": 74706995,
"Timestamp": "2022-03-03T21:26:30.8791017Z"
}
]
}
}
}
}
Human Readable Output
Persistence EvidenceHunt Hunt (new_group) Results
AdditionalFields DeviceName InitiatingProcessAccountName InitiatingProcessLogonId Timestamp {“GroupName”:”Test_group_delete”,”GroupDomainName”:”devicename_1”,”GroupSid”:”S-1-5-21-4197691174-1403503641-4006700887-1006”} devicename_1 demisto 74706995 2022-03-03T21:26:30.8791017Z
Command example
!microsoft-atp-advanced-hunting-persistence-evidence query_purpose=group_user_change device_name=desktop
Context Example
{
"MicrosoftATP": {
"HuntPersistenceEvidence": {
"Result": {
"group_user_change": [
{
"AccountSid": "accound-sid"
}
]
}
}
}
}
Human Readable Output
Persistence EvidenceHunt Hunt (group_user_change) Results
AccountSid accound-sid
Command example
!microsoft-atp-advanced-hunting-persistence-evidence query_purpose=local_firewall_change device_name=desktop
Human Readable Output
Persistence EvidenceHunt Hunt (local_firewall_change) Results
No entries.
Command example
!microsoft-atp-advanced-hunting-persistence-evidence query_purpose=host_file_change device_name=desktop
Human Readable Output
Persistence EvidenceHunt Hunt (host_file_change) Results
No entries.
microsoft-atp-advanced-hunting-process-details
NOTE: This endpoint will be deprecated by Microsoft on January 31, 2027. We recommend switching to the Microsoft Graph Security Integration and using the msg-advanced-hunting command. For more information, see the Microsoft documentation
Detects process details. When you select a “query_purpose” argument, a designated query template is used.
Base Command
microsoft-atp-advanced-hunting-process-details
Input
| Argument Name | Description | Required |
|---|---|---|
| query_purpose | When you select a “query_purpose” argument, a designated query template is used. “parent_process” - Parent process. “grandparent_process” - Grandparent process. “process_details” - Process hash, path, signature details. “beaconing_evidence” - Does the process appear to be beaconing? “powershell_execution_unsigned_files” - Has the file executed PowerShell? Query without specifying processes. No additional arguments are required. “process_excecution_powershell” - Has the file executed PowerShell?. Possible values are: parent_process, grandparent_process, process_details, beaconing_evidence, powershell_execution_unsigned_files, process_excecution_powershell. | Required |
| device_name | Device name to look for. | Optional |
| file_name | File name to look for. | Optional |
| sha1 | SHA1 hash to look for. | Optional |
| sha256 | SHA256 hash to look for. | Optional |
| md5 | MD5 hash to look for. | Optional |
| device_id | Device ID to look for. | Optional |
| query_operation | Query operator to use with provided arguments. Possible values are: or, and. Default is or. | Optional |
| limit | Maximum number of results to retrieve. Default is 50. | Optional |
| time_range | Time range to look back. Expected syntax is a human readable time range, e.g. 60 minutes, 6 hours, 1 day, etc. | Optional |
| timeout | The amount of time (in seconds) that a request waits for the query response before a timeout occurs. Default is 10. | Optional |
| page | The page number from which to start a search. Default is 1. | Optional |
| show_query | Show the query as part of the entry result. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.HuntProcessDetails.Result.parent_process | String | The query results for parent_process query_purpose. |
| MicrosoftATP.HuntProcessDetails.Result.grandparent_process | String | The query results for grandparent_process query_purpose. |
| MicrosoftATP.HuntProcessDetails.Result.process_details | String | The query results for process_details query_purpose. |
| MicrosoftATP.HuntProcessDetails.Result.beaconing_evidence | String | The query results for beaconing_evidence query_purpose. |
| MicrosoftATP.HuntProcessDetails.Result.powershell_execution_unsigned_files | String | The query results for powershell_execution_unsigned_files query_purpose. |
| MicrosoftATP.HuntProcessDetails.Result.process_excecution_powershell | String | The query results for process_excecution_powershell query_purpose. |
Command example
!microsoft-atp-advanced-hunting-process-details query_purpose=beaconing_evidence file_name=powershell device_name=desktop query_operation=and
Context Example
{
"MicrosoftATP": {
"HuntProcessDetails": {
"Result": {
"beaconing_evidence": [
{
"ActionType": "ConnectionSuccess",
"DeviceId": "deviceid_2",
"DeviceName": "devicename_2",
"InitiatingProcessFileName": "powershell.exe",
"InitiatingProcessMD5": "md5",
"InitiatingProcessSHA1": "sha1",
"InitiatingProcessSHA256": "sha256",
"LocalIP": "ip1",
"LocalIPType": "Private",
"LocalPort": 49169,
"Protocol": "Tcp",
"RemoteIP": "ip3",
"RemoteIPType": "Public",
"RemotePort": 443,
"RemoteUrl": "winatp-gw-eus.microsoft.com",
"Timestamp": "2022-03-15T20:38:30.5393171Z"
},
{
"ActionType": "ConnectionSuccess",
"DeviceId": "deviceid",
"DeviceName": "devicename_1",
"InitiatingProcessFileName": "powershell.exe",
"InitiatingProcessMD5": "md5",
"InitiatingProcessSHA1": "sha1",
"InitiatingProcessSHA256": "sha256",
"LocalIP": "ip2",
"LocalIPType": "Private",
"LocalPort": 52110,
"Protocol": "Tcp",
"RemoteIP": "ip3",
"RemoteIPType": "Public",
"RemotePort": 443,
"RemoteUrl": "winatp-gw-eus.microsoft.com",
"Timestamp": "2022-03-15T15:33:29.0892401Z"
}
]
}
}
}
}
Human Readable Output
Process Details Hunt (beaconing_evidence) Results
ActionType DeviceId DeviceName InitiatingProcessFileName InitiatingProcessMD5 InitiatingProcessSHA1 InitiatingProcessSHA256 LocalIP LocalIPType LocalPort Protocol RemoteIP RemoteIPType RemotePort RemoteUrl Timestamp ConnectionSuccess deviceid_2 devicename_2 powershell.exe md5 sha1 sha256 ip1 Private 49169 Tcp ip3 Public 443 winatp-gw-eus.microsoft.com 2022-03-15T20:38:30.5393171Z ConnectionSuccess deviceid devicename_1 powershell.exe md5 sha1 sha256 ip2 Private 52110 Tcp ip3 Public 443 winatp-gw-eus.microsoft.com 2022-03-15T15:33:29.0892401Z
microsoft-atp-advanced-hunting-network-connections
NOTE: This endpoint will be deprecated by Microsoft on January 31, 2027. We recommend switching to the Microsoft Graph Security Integration and using the msg-advanced-hunting command. For more information, see the Microsoft documentation
Detects network connections. When you select a “query_purpose” argument, a designated query template is used.
Base Command
microsoft-atp-advanced-hunting-network-connections
Input
| Argument Name | Description | Required |
|---|---|---|
| query_purpose | When you select a “query_purpose” argument, a designated query template is used. “external_addresses” - Network connections to external addresses. “dns_query” - DNS query. Query by providing hash or filename or specific processes. At least one of file arguments (file_name, sha1, sha256, md5) is required and one of device arguments (device_name, device_id). “encoded_commands” - Are there commands with base 64 encoding? Only device arguments are required (device_name, device_id), at least one. Possible values are: external_addresses, dns_query, encoded_commands. | Required |
| device_name | Device name to look for. | Optional |
| file_name | File name to look for. | Optional |
| sha1 | SHA1 hash to look for. | Optional |
| sha256 | SHA256 hash to look for. | Optional |
| md5 | MD5 hash to look for. | Optional |
| device_id | Device ID to look for. | Optional |
| query_operation | Query operator to use with provided arguments. Possible values are: or, and. Default is or. | Optional |
| limit | Maximum number of results to retrieve. Default is 50. | Optional |
| time_range | Time range to look back. Expected syntax is a human readable time range, e.g. 60 minutes, 6 hours, 1 day, etc. | Optional |
| timeout | The amount of time (in seconds) that a request waits for the query response before a timeout occurs. Default is 10. | Optional |
| page | The page number from which to start a search. Default is 1. | Optional |
| show_query | Show the query as part of the entry result. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.HuntNetworkConnections.Result.external_addresses | String | The query results for external_addresses query_purpose. |
| MicrosoftATP.HuntNetworkConnections.Result.dns_query | String | The query results for dns_query query_purpose. |
| MicrosoftATP.HuntNetworkConnections.Result.encoded_commands | String | The query results for encoded_commands query_purpose. |
Command example
!microsoft-atp-advanced-hunting-network-connections query_purpose=dns_query device_name=devicename_1,devicename_2
Context Example
{
"MicrosoftATP": {
"HuntNetworkConnections": {
"Result": {
"dns_query": [
{
"ActionType": "NetworkSignatureInspected",
"DeviceName": "devicename_2",
"Packetinfo": "{\"SignatureName\":\"DNS_Request\",\"SignatureMatchedContent\":\"h%D4%01%00%00%01%00%00%00%00%00%00%05ctldl%0Dwindowsupdate%03com\",\"SamplePacketContent\":\"[\\\"h%D4%01%00%00%01%00%00%00%00%00%00%05ctldl%0Dwindowsupdate%03com%00%00%01%00%01\\\"]\"}",
"RemoteIP": "8.8.8.8",
"Timestamp": "2022-03-15T20:01:20.3307099Z"
},
{
"ActionType": "NetworkSignatureInspected",
"DeviceName": "devicename_2",
"Packetinfo": "{\"SignatureName\":\"DNS_Request\",\"SignatureMatchedContent\":\"%B0%C5%01%00%00%01%00%00%00%00%00%00%06us-v20%06events%04data%09microsoft%03com\",\"SamplePacketContent\":\"[\\\"%B0%C5%01%00%00%01%00%00%00%00%00%00%06us-v20%06events%04data%09microsoft%03com%00%00%01%00%01\\\"]\"}",
"RemoteIP": "8.8.8.8",
"Timestamp": "2022-03-15T20:01:20.3327319Z"
}
]
}
}
}
}
Human Readable Output
Network Connections Hunt (dns_query) Results
ActionType DeviceName Packetinfo RemoteIP Timestamp NetworkSignatureInspected devicename_2 {“SignatureName”:”DNS_Request”,”SignatureMatchedContent”:”h%D4%01%00%00%01%00%00%00%00%00%00%05ctldl%0Dwindowsupdate%03com”,”SamplePacketContent”:”["h%D4%01%00%00%01%00%00%00%00%00%00%05ctldl%0Dwindowsupdate%03com%00%00%01%00%01"]”} 8.8.8.8 2022-03-15T20:01:20.3307099Z NetworkSignatureInspected devicename_2 {“SignatureName”:”DNS_Request”,”SignatureMatchedContent”:”%B0%C5%01%00%00%01%00%00%00%00%00%00%06us-v20%06events%04data%09microsoft%03com”,”SamplePacketContent”:”["%B0%C5%01%00%00%01%00%00%00%00%00%00%06us-v20%06events%04data%09microsoft%03com%00%00%01%00%01"]”} 8.8.8.8 2022-03-15T20:01:20.3327319Z
microsoft-atp-advanced-hunting-cover-up
NOTE: This endpoint will be deprecated by Microsoft on January 31, 2027. We recommend switching to the Microsoft Graph Security Integration and using the msg-advanced-hunting command. For more information, see the Microsoft documentation
Detects cover up actions. When you select a “query_purpose” argument, a designated query template is used.
Base Command
microsoft-atp-advanced-hunting-cover-up
Input
| Argument Name | Description | Required |
|---|---|---|
| query_purpose | When you select a “query_purpose” argument, a designated query template is used. “file_deleted” - Did the file delete itself? “event_log_cleared” - Was the event log cleared? Requires at least one of device arguments (device_name/device_id). “compromised_information” - Information on a compromised user and Its activities Requires only username argument. “connected_devices” - All connected devices by compromised user Requires only username argument. “action_types” - All action types created by a user on each machine Requires only username argument. “common_files” - Most common files associated with a user Requires only username argument. Possible values are: file_deleted, event_log_cleared, compromised_information, connected_devices, action_types, common_files. | Required |
| device_name | Device name to look for. | Optional |
| file_name | File name to look for. | Optional |
| sha1 | SHA1 hash to look for. | Optional |
| sha256 | SHA256 hash to look for. | Optional |
| md5 | MD5 hash to look for. | Optional |
| device_id | Device ID to look for. | Optional |
| username | Username to look for in relevant query types. | Optional |
| query_operation | Query operator to use with provided arguments. Possible values are: or, and. Default is or. | Optional |
| limit | Maximum number of results to retrieve. Default is 50. | Optional |
| time_range | Time range to look back. Expected syntax is a human readable time range, e.g. 60 minutes, 6 hours, 1 day, etc. | Optional |
| timeout | The amount of time (in seconds) that a request waits for the query response before a timeout occurs. Default is 10. | Optional |
| page | The page number from which to start a search. Default is 1. | Optional |
| show_query | Show the query as part of the entry result. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.HuntCoverUp.Result.file_deleted | String | The query results for file_deleted query_purpose. |
| MicrosoftATP.HuntCoverUp.Result.event_log_cleared | String | The query results for event_log_cleared query_purpose. |
| MicrosoftATP.HuntCoverUp.Result.compromised_information | String | The query results for compromised_information query_purpose. |
| MicrosoftATP.HuntCoverUp.Result.connected_devices | String | The query results for connected_devices query_purpose. |
| MicrosoftATP.HuntCoverUp.Result.action_types | String | The query results for action_types query_purpose. |
| MicrosoftATP.HuntCoverUp.Result.common_files | String | The query results for common_files query_purpose. |
Command example
!microsoft-atp-advanced-hunting-cover-up query_purpose=file_deleted file_name=chrome device_name=desktop query_operation=and
Context Example
{
"MicrosoftATP": {
"HuntCoverUp": {
"Result": {
"file_deleted": [
{
"DeviceId": "deviceid",
"DeviceName": "devicename_1",
"FileName": "old_chrome_proxy.exe",
"FolderPath": "C:\\Program Files\\Google\\Chrome\\Temp\\scoped_dir9640_1501542081",
"InitiatingProcessCommandLine": "\"setup.exe\" --rename-chrome-exe --system-level --verbose-logging --channel=stable",
"InitiatingProcessFileName": "setup.exe",
"InitiatingProcessVersionInfoProductName": "Google Chrome Installer",
"Timestamp": "2022-03-10T09:41:21.9388696Z"
},
{
"DeviceId": "deviceid",
"DeviceName": "devicename_1",
"FileName": "old_chrome_proxy.exe",
"FolderPath": "C:\\Program Files\\Google\\Chrome\\Temp\\scoped_dir9640_1501542081",
"InitiatingProcessCommandLine": "\"setup.exe\" --rename-chrome-exe --system-level --verbose-logging --channel=stable",
"InitiatingProcessFileName": "setup.exe",
"InitiatingProcessVersionInfoProductName": "Google Chrome Installer",
"Timestamp": "2022-03-10T09:41:21.9390745Z"
},
{
"DeviceId": "deviceid",
"DeviceName": "devicename_1",
"FileName": "chrome_pwa_launcher.exe",
"FolderPath": "C:\\Program Files\\Google\\Chrome\\Application\\98.0.4758.102",
"InitiatingProcessCommandLine": "\"setup.exe\" --channel=stable --delete-old-versions --system-level --verbose-logging",
"InitiatingProcessFileName": "setup.exe",
"InitiatingProcessVersionInfoProductName": "Google Chrome Installer",
"Timestamp": "2022-03-10T09:41:37.3955125Z"
},
{
"DeviceId": "deviceid",
"DeviceName": "devicename_1",
"FileName": "chrome_pwa_launcher.exe",
"FolderPath": "C:\\Program Files\\Google\\Chrome\\Application\\98.0.4758.102",
"InitiatingProcessCommandLine": "\"setup.exe\" --channel=stable --delete-old-versions --system-level --verbose-logging",
"InitiatingProcessFileName": "setup.exe",
"InitiatingProcessVersionInfoProductName": "Google Chrome Installer",
"Timestamp": "2022-03-10T09:41:37.3957224Z"
},
{
"DeviceId": "deviceid",
"DeviceName": "devicename_1",
"FileName": "99.0.4844.51_98.0.4758.102_chrome_updater.exe",
"FolderPath": "C:\\Program Files (x86)\\Google\\Update\\Install\\{CD86F442-5CCD-4E90-B0AC-36D19A65A0C5}",
"InitiatingProcessCommandLine": "\"GoogleUpdate.exe\" /svc",
"InitiatingProcessFileName": "GoogleUpdate.exe",
"InitiatingProcessVersionInfoProductName": "Google Update",
"Timestamp": "2022-03-08T13:29:06.7875767Z"
},
{
"DeviceId": "deviceid",
"DeviceName": "devicename_1",
"FileName": "99.0.4844.51_98.0.4758.102_chrome_updater.exe",
"FolderPath": "C:\\Program Files (x86)\\Google\\Update\\Install\\{CD86F442-5CCD-4E90-B0AC-36D19A65A0C5}",
"InitiatingProcessCommandLine": "\"GoogleUpdate.exe\" /svc",
"InitiatingProcessFileName": "GoogleUpdate.exe",
"InitiatingProcessVersionInfoProductName": "Google Update",
"Timestamp": "2022-03-08T13:29:06.7877821Z"
}
]
}
}
}
}
Human Readable Output
Cover Up Hunt (file_deleted) Results
DeviceId DeviceName FileName FolderPath InitiatingProcessCommandLine InitiatingProcessFileName InitiatingProcessVersionInfoProductName Timestamp deviceid devicename_1 old_chrome_proxy.exe C:\Program Files\Google\Chrome\Temp\scoped_dir9640_1501542081 “setup.exe” –rename-chrome-exe –system-level –verbose-logging –channel=stable setup.exe Google Chrome Installer 2022-03-10T09:41:21.9388696Z deviceid devicename_1 old_chrome_proxy.exe C:\Program Files\Google\Chrome\Temp\scoped_dir9640_1501542081 “setup.exe” –rename-chrome-exe –system-level –verbose-logging –channel=stable setup.exe Google Chrome Installer 2022-03-10T09:41:21.9390745Z deviceid devicename_1 chrome_pwa_launcher.exe C:\Program Files\Google\Chrome\Application\98.0.4758.102 “setup.exe” –channel=stable –delete-old-versions –system-level –verbose-logging setup.exe Google Chrome Installer 2022-03-10T09:41:37.3955125Z deviceid devicename_1 chrome_pwa_launcher.exe C:\Program Files\Google\Chrome\Application\98.0.4758.102 “setup.exe” –channel=stable –delete-old-versions –system-level –verbose-logging setup.exe Google Chrome Installer 2022-03-10T09:41:37.3957224Z deviceid devicename_1 99.0.4844.51_98.0.4758.102_chrome_updater.exe C:\Program Files (x86)\Google\Update\Install{CD86F442-5CCD-4E90-B0AC-36D19A65A0C5} “GoogleUpdate.exe” /svc GoogleUpdate.exe Google Update 2022-03-08T13:29:06.7875767Z deviceid devicename_1 99.0.4844.51_98.0.4758.102_chrome_updater.exe C:\Program Files (x86)\Google\Update\Install{CD86F442-5CCD-4E90-B0AC-36D19A65A0C5} “GoogleUpdate.exe” /svc GoogleUpdate.exe Google Update 2022-03-08T13:29:06.7877821Z
Command example
!microsoft-atp-advanced-hunting-cover-up query_purpose=event_log_cleared device_name=devicename_1
Context Example
{
"MicrosoftATP": {
"HuntCoverUp": {
"Result": {
"event_log_cleared": [
{
"ClearedLogList": [
"\"wevtutil.exe\" clear-log System",
"\"wevtutil.exe\" cl System"
],
"DeviceId": "deviceid",
"DeviceName": "devicename_1",
"FileName": "wevtutil.exe",
"InitiatingProcessFileName": "powershell.exe",
"LogClearCount": 2,
"Timestamp": "2022-03-09T07:15:00Z"
}
]
}
}
}
}
Human Readable Output
Cover Up Hunt (event_log_cleared) Results
ClearedLogList DeviceId DeviceName FileName InitiatingProcessFileName LogClearCount Timestamp “wevtutil.exe” clear-log System,
“wevtutil.exe” cl Systemdeviceid devicename_1 wevtutil.exe powershell.exe 2 2022-03-09T07:15:00Z
Command example
!microsoft-atp-advanced-hunting-cover-up query_purpose=compromised_information username=demisto
Context Example
{
"MicrosoftATP": {
"HuntCoverUp": {
"Result": {
"compromised_information": [
{
"ActionType": "LogonSuccess",
"DeviceId": "deviceid",
"DeviceName": "devicename_1",
"FileName": "",
"FolderPath": "",
"InitiatingProcessFileName": "lsass.exe",
"MD5": "",
"SHA1": "",
"SHA256": "",
"Timestamp": "2022-03-16T08:05:44.8315718Z"
},
{
"ActionType": "LogonSuccess",
"DeviceId": "deviceid",
"DeviceName": "devicename_1",
"FileName": "",
"FolderPath": "",
"InitiatingProcessFileName": "lsass.exe",
"MD5": "",
"SHA1": "",
"SHA256": "",
"Timestamp": "2022-02-28T12:34:02.8853766Z"
},
{
"ActionType": "LogonSuccess",
"DeviceId": "deviceid",
"DeviceName": "devicename_1",
"FileName": "",
"FolderPath": "",
"InitiatingProcessFileName": "",
"MD5": "",
"SHA1": "",
"SHA256": "",
"Timestamp": "2022-02-28T12:34:02.8855892Z"
},
{
"ActionType": "LogonSuccess",
"DeviceId": "deviceid",
"DeviceName": "devicename_1",
"FileName": "",
"FolderPath": "",
"InitiatingProcessFileName": "lsass.exe",
"MD5": "",
"SHA1": "",
"SHA256": "",
"Timestamp": "2022-02-28T12:34:05.6575357Z"
},
{
"ActionType": "LogonAttempted",
"DeviceId": "deviceid",
"DeviceName": "devicename_1",
"FileName": "",
"FolderPath": "",
"InitiatingProcessFileName": "svchost.exe",
"MD5": "",
"SHA1": "",
"SHA256": "",
"Timestamp": "2022-02-28T12:34:05.7005903Z"
},
{
"ActionType": "LogonFailed",
"DeviceId": "deviceid",
"DeviceName": "devicename_1",
"FileName": "",
"FolderPath": "",
"InitiatingProcessFileName": "",
"MD5": "",
"SHA1": "",
"SHA256": "",
"Timestamp": "2022-03-16T08:05:36.0887779Z"
}
]
}
}
}
}
Human Readable Output
Cover Up Hunt (compromised_information) Results
ActionType DeviceId DeviceName InitiatingProcessFileName Timestamp LogonSuccess deviceid devicename_1 lsass.exe 2022-03-16T08:05:44.8315718Z LogonSuccess deviceid devicename_1 lsass.exe 2022-02-28T12:34:02.8853766Z LogonSuccess deviceid devicename_1 2022-02-28T12:34:02.8855892Z LogonSuccess deviceid devicename_1 lsass.exe 2022-02-28T12:34:05.6575357Z LogonAttempted deviceid devicename_1 svchost.exe 2022-02-28T12:34:05.7005903Z LogonFailed deviceid devicename_1 2022-03-16T08:05:36.0887779Z
microsoft-atp-advanced-hunting-file-origin
NOTE: This endpoint will be deprecated by Microsoft on January 31, 2027. We recommend switching to the Microsoft Graph Security Integration and using the msg-advanced-hunting command. For more information, see the Microsoft documentation
How did the file get on the machine. Possible details are “dropped_file” - Was the file dropped? From where? “created_file” - Created by another File (script, compiled binary). “network_shared” - Shared via network. “execution_chain” - What is the process execution chain.
Base Command
microsoft-atp-advanced-hunting-file-origin
Input
| Argument Name | Description | Required |
|---|---|---|
| device_name | Device name to look for. | Optional |
| file_name | File name to look for. | Optional |
| sha1 | SHA1 hash to look for. | Optional |
| sha256 | SHA256 hash to look for. | Optional |
| md5 | MD5 hash to look for. | Optional |
| device_id | Device ID to look for. | Optional |
| query_operation | Query operator to use with provided arguments. Possible values are: or, and. Default is or. | Optional |
| limit | Maximum number of results to retrieve. Default is 50. | Optional |
| time_range | Time range to look back. Expected syntax is a human readable time range, e.g. 60 minutes, 6 hours, 1 day, etc. | Optional |
| timeout | The amount of time (in seconds) that a request waits for the query response before a timeout occurs. Default is 10. | Optional |
| page | The page number from which to start a search. Default is 1. | Optional |
| show_query | Show the query as part of the entry result. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.HuntFileOrigin.Result | String | The query results. |
microsoft-atp-advanced-hunting-privilege-escalation
NOTE: This endpoint will be deprecated by Microsoft on January 31, 2027. We recommend switching to the Microsoft Graph Security Integration and using the msg-advanced-hunting command. For more information, see the Microsoft documentation
Is there evidence for privilege escalation.
Base Command
microsoft-atp-advanced-hunting-privilege-escalation
Input
| Argument Name | Description | Required |
|---|---|---|
| device_name | Device name to look for. | Optional |
| device_id | Device ID to look for. | Optional |
| query_operation | Query operator to use with provided arguments. Possible values are: or, and. Default is or. | Optional |
| limit | Maximum number of results to retrieve. Default is 50. | Optional |
| time_range | Time range to look back. Expected syntax is a human readable time range, e.g. 60 minutes, 6 hours, 1 day, etc. | Optional |
| timeout | The amount of time (in seconds) that a request waits for the query response before a timeout occurs. Default is 10. | Optional |
| page | The page number from which to start a search. Default is 1. | Optional |
| show_query | Show the query as part of the entry result. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.HuntPrivilegeEscalation.Result | String | The query results. |
microsoft-atp-advanced-hunting-tampering
NOTE: This endpoint will be deprecated by Microsoft on January 31, 2027. We recommend switching to the Microsoft Graph Security Integration and using the msg-advanced-hunting command. For more information, see the Microsoft documentation
Detect if there was any evidence of MSDE agent/sensor manipulation.
Base Command
microsoft-atp-advanced-hunting-tampering
Input
| Argument Name | Description | Required |
|---|---|---|
| device_name | Device name to look for. | Optional |
| device_id | Device ID to look for. | Optional |
| query_operation | Query operator to use with provided arguments. Possible values are: or, and. Default is or. | Optional |
| limit | Maximum number of results to retrieve. Default is 50. | Optional |
| time_range | Time range to look back. Expected syntax is a human readable time range, e.g. 60 minutes, 6 hours, 1 day, etc. | Optional |
| timeout | The amount of time (in seconds) that a request waits for the query response before a timeout occurs. Default is 10. | Optional |
| page | The page number from which to start a search. Default is 1. | Optional |
| show_query | Show the query as part of the entry result. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.HuntTampering.Result | String | The query results. |
microsoft-atp-live-response-cancel-action
Cancels an action with an unfinished status.
Base Command
microsoft-atp-live-response-cancel-action
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_action_id | Action ID to retrieve status and data for. | Required |
| comment | A comment to associate with the action. | Required |
Context Output
There is no context output for this command.
microsoft-atp-get-machine-users
Retrieves a collection of logged on users on a specific device.
Required Permissions
User.Read.All
Base Command
microsoft-atp-get-machine-users
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | A machine ID used for getting logged on users. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.MachineUser.ID | String | The user ID. |
| MicrosoftATP.MachineUser.AccountName | String | The user account name. |
| MicrosoftATP.MachineUser.AccountDomain | String | The domain of the user account. |
| MicrosoftATP.MachineUser.FirstSeen | Date | The first date and time the user has logged on the machine. |
| MicrosoftATP.MachineUser.LastSeen | Date | The last date and time the user has logged on the machine. |
| MicrosoftATP.MachineUser.LogonTypes | String | The logon types of the user on the machine. |
| MicrosoftATP.MachineUser.DomainAdmin | Boolean | True if user is Domain Admin, False otherwise. |
| MicrosoftATP.MachineUser.NetworkUser | Boolean | True if user is network user, False otherwise. |
| MicrosoftATP.MachineUser.MachineID | String | The machine ID. |
Command example
!microsoft-atp-get-machine-users machine_id=0a3250e0693a109f1affc9217be9459028aa8424
Context Example
{
"MicrosoftATP": {
"MachineUser": [
{
"id": "contoso\\user1",
"accountName": "user1",
"accountDomain": "contoso",
"firstSeen": "2019-12-18T08:02:54Z",
"lastSeen": "2020-01-06T08:01:48Z",
"logonTypes": "Interactive",
"isDomainAdmin": true,
"isOnlyNetworkUser": false,
"machineId": "111e6dd8c833c8a052ea231ec1b19adaf497b625"
},
...
]
}
}
Human Readable Output
Microsoft Defender ATP logon users for machine 111e6dd8c833c8a052ea231ec1b19adaf497b625
ID AccountName AccountDomain FirstSeen LastSeen LogonTypes DomainAdmin NetworkUser contoso\user1 user1 contoso 2019-12-18T08:02:54Z 2020-01-06T08:01:48Z Interactive True False
microsoft-atp-get-machine-alerts (Deprecated)
This command has been deprecated. No available replacement.
Retrieves all alerts related to a specific device.
Required Permissions
Alert.ReadWrite.All
Base Command
microsoft-atp-get-machine-alerts
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | A machine ID used for getting machine related alerts, e.g. 0a3250e0693a109f1affc9217be9459028aa8424. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.MachineAlerts.ID | String | The alert ID. |
| MicrosoftATP.MachineAlerts.Title | String | The alert title. |
| MicrosoftATP.MachineAlerts.Description | String | The alert description. |
| MicrosoftATP.MachineAlerts.IncidentID | String | The incident ID, if alert belongs to one. |
| MicrosoftATP.MachineAlerts.Severity | String | The alert severtiy. |
| MicrosoftATP.MachineAlerts.Status | String | The alert status. |
| MicrosoftATP.MachineAlerts.Classification | String | The alert classification. |
| MicrosoftATP.MachineAlerts.Category | String | The alert category. |
| MicrosoftATP.MachineAlerts.ThreatFamilyName | String | The alert threat family name. |
| MicrosoftATP.MachineAlerts.MachineID | String | The alerts machine ID. |
Command example
!microsoft-atp-get-machine-alerts machine_id=0a3250e0693a109f1affc9217be9459028aa8424
Context Example
{
"MicrosoftATP": {
"MachineAlerts": [
{
"id": "da637472900382838869_1364969609",
"incidentId": 1126093,
"severity": "Low",
"status": "New",
"category": "Execution",
"classification": null,
"threatFamilyName": null,
"title": "Low-reputation arbitrary code executed by signed executable",
"description": "Binaries signed by Microsoft can be used to run low-reputation arbitrary code. This technique hides the execution of malicious code within a trusted process. As a result, the trusted process might exhibit suspicious behaviors, such as opening a listening port or connecting to a command-and-control (C&C) server.",
"machineId": "111e6dd8c833c8a052ea231ec1b19adaf497b625"
},
...
]
}
}
Human Readable Output
Alerts that are related to machine 111e6dd8c833c8a052ea231ec1b19adaf497b625
ID Title Description IncidentID Severity Status Classification Category ThreatFamilyName MachineID da637472900382838869_1364969609 Low-reputation arbitrary code executed by signed executable Binaries signed by Microsoft can be used to run low-reputation arbitrary code. This technique hides the execution of malicious code within a trusted process. As a result, the trusted process might exhibit suspicious behaviors, such as opening a listening port or connecting to a command-and-control (C&C) server. 1126093 Low New Execution 111e6dd8c833c8a052ea231ec1b19adaf497b625
microsoft-atp-offboard-machine
Offboard a machine from microsoft ATP.
Required Permissions
Machine.Offboard
Base Command
microsoft-atp-offboard-machine
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | A comma-separated list of machine IDs to be used for offboarding. e.g., 0a3250e0693a109f1affc9217be9459028aa8426,0a3250e0693a109f1affc9217be9459028aa8424. | Required |
| comment | A comment to associate with the action. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.OffboardMachine.ID | String | The machine action ID. |
| MicrosoftATP.OffboardMachine.Type | String | Type of the machine action. |
| MicrosoftATP.OffboardMachine.Scope | Unknown | Scope of the action. |
| MicrosoftATP.OffboardMachine.Requestor | String | The ID of the user that executed the action. |
| MicrosoftATP.OffboardMachine.RequestorComment | String | Comment that was written when issuing the action. |
| MicrosoftATP.OffboardMachine.Status | String | The current status of the command. |
| MicrosoftATP.OffboardMachine.MachineID | String | The machine ID on which the action was executed. |
| MicrosoftATP.OffboardMachine.ComputerDNSName | String | The machine DNS name on which the action was executed. |
| MicrosoftATP.OffboardMachine.CreationDateTimeUtc | Date | The date and time when the action was created. |
| MicrosoftATP.OffboardMachine.LastUpdateTimeUtc | Date | The last date and time when the action status was updated. |
| MicrosoftATP.OffboardMachine.cancellationDateTimeUtc | Date | The date and time when the action was canceled. |
| MicrosoftATP.OffboardMachine.RelatedFileInfo | String | The file info. |
| MicrosoftATP.OffboardMachine.troubleshootInfo | String | Troubleshooting information. |
Command example
!microsoft-atp-offboard-machine comment="Testing Offboarding" machine_id="12342c13fef"
Context Example
{
"MicrosoftATP": {
"MachineAction": [
{
"cancellationDateTimeUtc": null,
"computerDnsName": "desktop-s2455r8",
"creationDateTimeUtc": "2022-07-12T14:19:55.4872498Z",
"id": "947a677a-a11a-4240-ab6q-91277e2386b9",
"lastUpdateDateTimeUtc": "2022-07-12T14:19:55.4872521Z",
"machineId": null,
"relatedFileInfo": null,
"requestor": "2f48b784-5da5-4e61-9957-012d2630f1e4",
"requestorComment": "Testing Offboarding",
"scope": null,
"status": "Pending",
"troubleshootInfo": null,
"type": "Offboard"
}
]
}
}
Human Readable Output
The offboarding request has been submitted successfully
ID Type Requestor RequestorComment Status MachineID ComputerDNSName 947a677a-a11a-4240-ab6q-91277e2386b9 Offboard 2f48b784-5da5-4e61-9957-012d2630f1e4 offboard test Pending 12342c13fef desktop-s2455r8
=======
microsoft-atp-request-and-download-investigation-package
Collect and download an investigation package as a gz file.
Base Command
microsoft-atp-request-and-download-investigation-package
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | The machine ID. | Required |
| comment | A comment to associate with the action. | Required |
| timeout_in_seconds | Timeout for polling. | Optional |
| machine_action_id | Action ID to retrieve status and data for. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.MachineAction.ID | String | The machine action ID. |
| MicrosoftATP.MachineAction.Status | String | The current status of the machine action. |
| MicrosoftATP.MachineAction.MachineID | String | The machine ID on which the action was executed. |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.MachineAction.ID | String | The machine action ID. |
| MicrosoftATP.MachineAction.Type | String | Type of the machine action. |
| MicrosoftATP.MachineAction.Scope | Unknown | Scope of the action. |
| MicrosoftATP.MachineAction.Requestor | String | The ID of the user that executed the action. |
| MicrosoftATP.MachineAction.RequestorComment | String | Comment that was written when issuing the action. |
| MicrosoftATP.MachineAction.Status | String | The current status of the command. |
| MicrosoftATP.MachineAction.MachineID | String | The machine ID on which the action was executed. |
| MicrosoftATP.MachineAction.ComputerDNSName | String | The machine DNS name on which the action was executed. |
| MicrosoftATP.MachineAction.CreationDateTimeUtc | Date | The date and time when the action was created. |
| MicrosoftATP.MachineAction.LastUpdateTimeUtc | Date | The last date and time when the action status was updated. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifier | String | The file identifier. |
| MicrosoftATP.MachineAction.RelatedFileInfo.FileIdentifierType | String | The type of the file identifier. Possible values: “SHA1” ,”SHA256”, and “MD5”. |
Command example
!microsoft-atp-isolate-machine comment=isolate_test_3 isolation_type=Full machine_id="12342c13fef,12342c13fef8f06606"
Context Example
{
"MicrosoftATP": {
"MachineAction": [
{
"ComputerDNSName": "desktop-s2455r8",
"CreationDateTimeUtc": "2022-01-25T14:25:52.6227941Z",
"ID": "1f3098e20464",
"LastUpdateTimeUtc": null,
"MachineID": "12342c13fef",
"RelatedFileInfo": {
"FileIdentifier": null,
"FileIdentifierType": null
},
"Requestor": "2f48b784-5da5-4e61-9957-012d2630f1e4",
"RequestorComment": "isolate_test_3",
"Scope": "Full",
"Status": "Pending",
"Type": "Isolate"
},
{
"ComputerDNSName": "desktop-s2455r9",
"CreationDateTimeUtc": "2022-01-25T14:25:53.2395007Z",
"ID": "6d39a3da0744",
"LastUpdateTimeUtc": null,
"MachineID": "12342c13fef8f06606",
"RelatedFileInfo": {
"FileIdentifier": null,
"FileIdentifierType": null
},
"Requestor": "2f48b784-5da5-4e61-9957-012d2630f1e4",
"RequestorComment": "isolate_test_3",
"Scope": "Full",
"Status": "Pending",
"Type": "Isolate"
}
]
}
}
Human Readable Output
The isolation request has been submitted successfully
ID Type Requestor RequestorComment Status MachineID ComputerDNSName 1f3098e20464 Isolate 2f48b784-5da5-4e61-9957-012d2630f1e4 isolate_test_3 Pending 12342c13fef desktop-s2455r8 6d39a3da0744 Isolate 2f48b784-5da5-4e61-9957-012d2630f1e4 isolate_test_3 Pending 12342c13fef8f06606 desktop-s2455r9
microsoft-atp-test
Tests connectivity to Microsoft Defender for Endpoint.
Base Command
microsoft-atp-test
Input
There are no input arguments for this command.
Context Output
There is no context output for this command.
microsoft-atp-list-software
Retrieves the organization software inventory.
Base Command
microsoft-atp-list-software
Input
| Argument Name | Description | Required |
|---|---|---|
| id | Software ID. | Optional |
| name | Software name. | Optional |
| vendor | Software publisher name. | Optional |
| limit | Maximum number of results to retrieve. Default is 50. | Optional |
| offset | The number of items in the queried collection that are to be skipped and not included in the result. Default is 0. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Software.id | String | Software ID. |
| MicrosoftATP.Software.name | String | Software name. |
| MicrosoftATP.Software.vendor | String | Software publisher name. |
| MicrosoftATP.Software.weaknesses | Number | Number of discovered vulnerabilities. |
| MicrosoftATP.Software.publicExploit | Boolean | Whether a public exploit exists for some of the vulnerabilities. |
| MicrosoftATP.Software.activeAlert | Boolean | Whether an active alert is associated with this software. |
| MicrosoftATP.Software.exposedMachines | Number | Number of exposed devices. |
| MicrosoftATP.Software.installedMachines | Number | The number of installed machines. |
| MicrosoftATP.Software.impactScore | Number | Exposure score impact of this software. |
| MicrosoftATP.Software.isNormalized | Boolean | Whether the software is normalized. |
| MicrosoftATP.Software.category | String | Software category. |
| MicrosoftATP.Software.distributions | String | Software distributions. |
Command example
!microsoft-atp-list-software id=some_id
Context Example
{
"MicrosoftATP": {
"Software": {
"activeAlert": false,
"category": "",
"distributions": [],
"exposedMachines": 0,
"id": "some_id",
"impactScore": 0,
"installedMachines": 1,
"isNormalized": false,
"name": "some_name",
"publicExploit": false,
"vendor": "some_vendor",
"weaknesses": 0
}
}
}
Human Readable Output
Microsoft Defender ATP list software
id name vendor weaknesses activeAlert exposedMachines installedMachines publicExploit some_id some_name some_vendor 0 false 0 1 false
microsoft-atp-list-software-version-distribution
Retrieves a list of your organization’s software version distribution.
Base Command
microsoft-atp-list-software-version-distribution
Input
| Argument Name | Description | Required |
|---|---|---|
| id | Software ID. Use the !microsoft-atp-list-software command to get the ID. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.SoftwareVersion.version | String | Version number |
| MicrosoftATP.SoftwareVersion.installations | Number | Installations number. |
| MicrosoftATP.SoftwareVersion.vulnerabilities | Number | Number of vulnerabilities. |
Command example
!microsoft-atp-list-software-version-distribution id=some_id
Context Example
{
"MicrosoftATP": {
"SoftwareVersion": [
{
"installations": 2,
"version": "7.0.2.0",
"vulnerabilities": 7
},
{
"installations": 1,
"version": "6.2.4.0",
"vulnerabilities": 0
}
]
}
}
Human Readable Output
Microsoft Defender ATP software version distribution
version installations vulnerabilities 7.0.2.0 2 7 6.2.4.0 1 0
microsoft-atp-list-machines-by-software
Retrieve a list of device references that has this software installed.
Base Command
microsoft-atp-list-machines-by-software
Input
| Argument Name | Description | Required |
|---|---|---|
| id | Software ID. Use the !microsoft-atp-list-software command to get the ID. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.SoftwareMachine.id | String | Machine identity. |
| MicrosoftATP.SoftwareMachine.computerDnsName | String | Machine fully qualified name. |
| MicrosoftATP.SoftwareMachine.osPlatform | String | Operating system platform. |
| MicrosoftATP.SoftwareMachine.rbacGroupName | String | Machine group name. |
| MicrosoftATP.SoftwareMachine.rbacGroupId | Number | Machine group ID. |
Command example
!microsoft-atp-list-machines-by-software id=some_id
Context Example
{
"MicrosoftATP": {
"SoftwareMachine": [
{
"computerDnsName": "some_dns_name_1",
"id": "1111111111111111111111111111111111111111",
"osPlatform": "WindowsServer2016",
"rbacGroupId": 1111,
"rbacGroupName": "UnassignedGroup"
},
{
"computerDnsName": "some_dns_name_2",
"id": "2222222222222222222222222222222222222222",
"osPlatform": "WindowsServer2016",
"rbacGroupId": 2222,
"rbacGroupName": "UnassignedGroup"
},
{
"computerDnsName": "some_dns_name_3",
"id": "3333333333333333333333333333333333333333",
"osPlatform": "Windows10",
"rbacGroupId": 3333,
"rbacGroupName": "UnassignedGroup"
}
]
}
}
Human Readable Output
Microsoft Defender ATP list machines by software: some_id
id computerDnsName osPlatform rbacGroupName rbacGroupId 1111111111111111111111111111111111111111 some_dns_name_1 WindowsServer2016 UnassignedGroup 1111 2222222222222222222222222222222222222222 some_dns_name_2 WindowsServer2016 UnassignedGroup 2222 3333333333333333333333333333333333333333 some_dns_name_3 Windows10 UnassignedGroup 3333
microsoft-atp-list-vulnerabilities-by-software
Retrieves a list of all the vulnerabilities affecting the organization per software.
Base Command
microsoft-atp-list-vulnerabilities-by-software
Input
| Argument Name | Description | Required |
|---|---|---|
| id | Software ID. Use the !microsoft-atp-list-software command to get the ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.SoftwareCVE.id | String | Vulnerability ID. |
| MicrosoftATP.SoftwareCVE.name | String | Vulnerability title. |
| MicrosoftATP.SoftwareCVE.description | String | Vulnerability description. |
| MicrosoftATP.SoftwareCVE.severity | String | Vulnerability severity. Possible values are: “Low”, “Medium”, “High”, “Critical” |
| MicrosoftATP.SoftwareCVE.cvssV3 | Number | CVSS v3 score. |
| MicrosoftATP.SoftwareCVE.exposedMachines | Number | Number of exposed devices. |
| MicrosoftATP.SoftwareCVE.publishedOn | Date | Date when vulnerability was published. Date format will be in ISO 8601 format or relational expressions like “7 days ago”. |
| MicrosoftATP.SoftwareCVE.updatedOn | Date | Date when vulnerability was updated. Date format will be in ISO 8601 format or relational expressions like “7 days ago”. |
| MicrosoftATP.SoftwareCVE.publicExploit | Boolean | Whether a public exploit exists for some of the vulnerabilities. |
| MicrosoftATP.SoftwareCVE.exploitVerified | Boolean | Whether a public exploit exists. |
| MicrosoftATP.SoftwareCVE.exploitInKit | Boolean | Whether the exploit is part of an exploit kit. |
| MicrosoftATP.SoftwareCVE.exploitTypes | String | Exploit impact. Possible values are: “Local privilege escalation”, “Denial of service”, “Local”. |
| MicrosoftATP.SoftwareCVE.exploitUris | String | Exploit source URLs. |
Command example
!microsoft-atp-list-vulnerabilities-by-software id=some_software
Context Example
{
"CVE": [
{
"CVSS": {
"Score": 5.9
},
"Description": "This vulnerability affects the following vendors: vendor_1, vendor_2, vendor_3. To view more details about this vulnerability please visit the vendor website.",
"ID": "CVE-2222-22222",
"Modified": "2021-05-17T22:56:00Z",
"Published": "2021-05-17T22:56:00Z"
}
],
"DBotScore": [
{
"Indicator": "CVE-2222-22222",
"Score": 0,
"Type": "cve",
"Vendor": "some_vendor"
}
],
"MicrosoftATP": {
"SoftwareCVE": [
{
"cvssV3": 5.9,
"description": "This vulnerability affects the following vendors: vendor_1, vendor_2, vendor_3. To view more details about this vulnerability please visit the vendor website.",
"exploitInKit": false,
"exploitTypes": [],
"exploitUris": [],
"exploitVerified": false,
"exposedMachines": 2,
"id": "CVE-2222-22222",
"name": "CVE-2222-22222",
"publicExploit": false,
"publishedOn": "2021-05-17T22:56:00Z",
"severity": "Medium",
"updatedOn": "2021-05-17T22:56:00Z"
}
]
}
}
Human Readable Output
Microsoft Defender ATP vulnerability CCVE-2222-22222 by software: some_software
id name description severity cvssV3 publishedOn updatedOn exposedMachines exploitVerified publicExploit CVE-2222-22222 CVE-2222-22222 This vulnerability affects the following vendors: vendor_1, vendor_2, vendor_3. To view more details about this vulnerability please visit the vendor website. Medium 5.9 2021-05-17T22:56:00Z 2021-05-17T22:56:00Z 2 false false
microsoft-atp-list-vulnerabilities-by-machine
Retrieves a list of all the vulnerabilities affecting the organization per machine.
Base Command
microsoft-atp-list-vulnerabilities-by-machine
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | A comma-separated list of machine IDs used for getting the vulnerabilities. | Optional |
| software_id | A comma-separated list of software IDs used for getting the vulnerabilities. | Optional |
| cve_id | A comma-separated list of CVE IDs used for getting the vulnerabilities. | Optional |
| product_name | A comma-separated list of product names used for getting the vulnerabilities. | Optional |
| product_version | A comma-separated list of product versions used for getting the vulnerabilities. | Optional |
| severity | A comma-separated list of vulnerability severities. Possible values are: “Low”, “Medium”, “High”, “Critical”. | Optional |
| product_vendor | A comma-separated list of product vendors used for getting the vulnerabilities. | Optional |
| limit | Maximum number of results to retrieve. Default is 25. | Optional |
| offset | The number of items in the queried collection that are to be skipped and not included in the result. Default is 0. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.MachineCVE.id | String | Vulnerability ID. |
| MicrosoftATP.MachineCVE.cveId | String | CVE ID. |
| MicrosoftATP.MachineCVE.machineId | String | Machine ID. |
| MicrosoftATP.MachineCVE.fixingKbId | Unknown | Fixing Kb ID. |
| MicrosoftATP.MachineCVE.productName | String | Product name. |
| MicrosoftATP.MachineCVE.productVendor | String | Name of the product vendor. |
| MicrosoftATP.MachineCVE.productVersion | String | Product version. |
| MicrosoftATP.MachineCVE.severity | String | Vulnerability severity. Possible values are: “Low”, “Medium”, “High”, “Critical”. |
Command example
!microsoft-atp-list-vulnerabilities-by-machine cve_id=CVE-1111-1111
Context Example
{
"CVE": {
"CVSS": {},
"ID": "1111111111111111111111111111111111111111-_-CVE-1111-1111-_-some_vendor-_-some_name-_-11.11.11.11111111-_-"
},
"DBotScore": {
"Indicator": "1111111111111111111111111111111111111111-_-CVE-1111-1111-_-some_vendor-_-some_name-_-11.11.11.11111111-_-",
"Score": 0,
"Type": "cve",
"Vendor": "Microsoft Defender Advanced Threat Protection"
},
"MicrosoftATP": {
"MachineCVE": {
"cveId": "CVE-1111-1111",
"fixingKbId": null,
"id": "1111111111111111111111111111111111111111-_-CVE-1111-1111-_-some_vendor-_-some_name-_-11.11.11.11111111-_-",
"machineId": "1111111111111111111111111111111111111111",
"productName": "some_name",
"productVendor": "some_vendor",
"productVersion": "11.11.11.11111111",
"severity": "Medium"
}
}
}
Human Readable Output
Microsoft Defender ATP vulnerability CVE-1111-1111
id cveId machineId productName productVendor productVersion severity 1111111111111111111111111111111111111111--CVE-1111-1111--some_vendor--some_name--11.11.11.11111111-_- CVE-1111-1111 1111111111111111111111111111111111111111 some_name some_vendor 11.11.11.11111111 Medium
microsoft-atp-list-vulnerabilities
Retrieves a list of all vulnerabilities.
Base Command
microsoft-atp-list-vulnerabilities
Input
| Argument Name | Description | Required |
|---|---|---|
| id | Vulnerability ID. | Optional |
| name_equal | Vulnerability title. | Optional |
| name_contains | Vulnerability title. Does not work with another filter arguments. | Optional |
| description_contains | Vulnerability description. Does not work with another filter arguments. | Optional |
| published_on | Date when the vulnerability was published. Date format will be in ISO 8601 format or relational expressions like “7 days ago”. | Optional |
| cvss | CVSS v3 score. | Optional |
| severity | A comma-separated list of vulnerability severities. Possible values are: “Low”, “Medium”, “High”, “Critical”. | Optional |
| updated_on | Date when the vulnerability was updated. Date format will be in ISO 8601 format or relational expressions like “7 days ago”. | Optional |
| limit | Maximum number of results to retrieve. Default is 25. | Optional |
| offset | The number of items in the queried collection that are to be skipped and not included in the result. Default is 0. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Vulnerability.id | String | Vulnerability ID. |
| MicrosoftATP.Vulnerability.name | String | Vulnerability title. |
| MicrosoftATP.Vulnerability.description | String | Vulnerability description. |
| MicrosoftATP.Vulnerability.severity | String | Vulnerability severity. Possible values are: “Low”, “Medium”, “High”, “Critical”. |
| MicrosoftATP.Vulnerability.cvssV3 | Number | CVSS v3 score. |
| MicrosoftATP.Vulnerability.exposedMachines | Number | Number of exposed devices. |
| MicrosoftATP.Vulnerability.publishedOn | Date | Date when the vulnerability was published. Date format will be in ISO 8601 format or relational expressions like “7 days ago”. |
| MicrosoftATP.Vulnerability.updatedOn | Date | Date when the vulnerability was updated. Date format will be in ISO 8601 format or relational expressions like “7 days ago”. |
| MicrosoftATP.Vulnerability.publicExploit | Boolean | Whether the public exploit exists. |
| MicrosoftATP.Vulnerability.exploitVerified | Boolean | Whether the exploit is verified to work. |
| MicrosoftATP.Vulnerability.exploitInKit | Boolean | Whether the exploit is part of an exploit kit. |
| MicrosoftATP.Vulnerability.exploitTypes | String | Exploit impact. Possible values are: “Local privilege escalation”, “Denial of service”, “Local”. |
| MicrosoftATP.Vulnerability.exploitUris | String | Exploit source URLs. |
Command example
!microsoft-atp-list-vulnerabilities id="CVE-1111-1111"
Context Example
{
"CVE": {
"CVSS": {
"Score": 6.5
},
"Description": "some_description.",
"ID": "CVE-1111-1111",
"Modified": "2002-09-10T00:00:00Z",
"Published": "2002-09-10T00:00:00Z"
},
"DBotScore": {
"Indicator": "CVE-1111-1111",
"Score": 0,
"Type": "cve",
"Vendor": "some_vendor"
},
"MicrosoftATP": {
"SoftwareCVE": {
"cvssV3": 6.5,
"description": "some_description.",
"exploitInKit": false,
"exploitTypes": [],
"exploitUris": [],
"exploitVerified": false,
"exposedMachines": 0,
"id": "CVE-1111-1111",
"name": "CVE-1111-1111",
"publicExploit": false,
"publishedOn": "2002-09-10T00:00:00Z",
"severity": "Medium",
"updatedOn": "2002-09-10T00:00:00Z"
}
}
}
Human Readable Output
Microsoft Defender ATP vulnerabilities
id name description severity publishedOn updatedOn exposedMachines exploitVerified publicExploit cvssV3 CVE-1111-1111 CVE-1111-1111 some_description. Medium 2002-09-10T00:00:00Z 2002-09-10T00:00:00Z 0 false false 6.5
microsoft-atp-list-missing-kb-by-software
Retrieves missing KBs (security updates) by software ID.
Base Command
microsoft-atp-list-missing-kb-by-software
Input
| Argument Name | Description | Required |
|---|---|---|
| id | Software ID. Use the !microsoft-atp-list-software command to get the ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicMicrosoftATP.SoftwareKB.id | String | Software ID. |
| MicMicrosoftATP.SoftwareKB.name | String | Software name. |
| MicMicrosoftATP.SoftwareKB.osBuild | Number | The operating system build number. |
| MicMicrosoftATP.SoftwareKB.productsNames | String | Product names. |
| MicMicrosoftATP.SoftwareKB.url | String | URL. |
| MicMicrosoftATP.SoftwareKB.machineMissedOn | Number | Machine missed on. |
| MicMicrosoftATP.SoftwareKB.cveAddressed | Number | CVE addressed. |
Command example
!microsoft-atp-list-missing-kb-by-software id=some_id
Context Example
{
"MicrosoftATP": {
"SoftwareKB": [
{
"cveAddressed": 2,
"id": "1111111",
"machineMissedOn": 1,
"name": "some_name_1",
"osBuild": 22222,
"productsNames": [
"some_id"
],
"url": "some_url_1"
},
{
"cveAddressed": 2,
"id": "2222222",
"machineMissedOn": 1,
"name": "some_name_2",
"osBuild": 22222,
"productsNames": [
"some_id"
],
"url": "some_url_2"
},
]
}
}
Human Readable Output
Microsoft Defender ATP missing kb by software: some_id
id name osBuild productsNames url machineMissedOn cveAddressed 1111111 some_name_1 22222 some_id some_url_1 1 2 2222222 some_name_2 22222 some_id some_url_2 1 2
microsoft-atp-generate-login-url
Generate the login url used for Authorization code flow.
Base Command
microsoft-atp-generate-login-url
Input
There are no input arguments for this command.
Context Output
There is no context output for this command.
Command Example
#### Human Readable Output
>### Authorization instructions
>
>1. Click on the [login URL](https://login.microsoftonline.com) to sign in and grant Cortex XSOAR permissions for your Azure Service Management.
You will be automatically redirected to a link with the following structure:
```REDIRECT_URI?code=AUTH_CODE&session_state=SESSION_STATE```
>2. Copy the `AUTH_CODE` (without the `code=` prefix, and the `session_state` parameter)
and paste it in your instance configuration under the **Authorization code** parameter.
### microsoft-atp-auth-reset
***
Run this command if for some reason you need to rerun the authentication process.
#### Base Command
`microsoft-atp-auth-reset`
#### Input
There are no input arguments for this command.
#### Context Output
There is no context output for this command.
### microsoft-atp-get-machine-by-ip
***
Find Machines seen with the requested internal IP in the time range of 15 minutes prior and after a given timestamp.
#### Base Command
`microsoft-atp-get-machine-by-ip`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| ip | The endpoint IP address. | Required |
| timestamp | The timestamp in witch the machines were seen with the internal ip address, 15 minutes before and after it. The given timestamp must be in the past 30 days. Timestamp format example- 2019-09-22T08:44:05Z. | Required |
| limit | Maximum number of results to return. Default is 50. | Optional |
| all_results | Whether to retrieve all results. If true, the "limit" argument will be ignored. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| MicrosoftATP.Machine.ID | String | The machine ID. |
| MicrosoftATP.Machine.ComputerDNSName | String | The machine DNS name. |
| MicrosoftATP.Machine.FirstSeen | Date | The first date and time the machine was observed by Microsoft Defender ATP. |
| MicrosoftATP.Machine.LastSeen | Date | The last date and time the machine was observed by Microsoft Defender ATP. |
| MicrosoftATP.Machine.OSPlatform | String | The operating system platform. |
| MicrosoftATP.Machine.OSVersion | String | The operating system version. |
| MicrosoftATP.Machine.OSProcessor | String | The operating system processor. |
| MicrosoftATP.Machine.LastIPAddress | String | The last IP on the machine. |
| MicrosoftATP.Machine.LastExternalIPAddress | String | The last machine IP to access the internet. |
| MicrosoftATP.Machine.OSBuild | Number | The operating system build number. |
| MicrosoftATP.Machine.HealthStatus | String | The machine health status. |
| MicrosoftATP.Machine.RBACGroupID | Number | The machine RBAC group ID. |
| MicrosoftATP.Machine.RBACGroupName | String | The machine RBAC group name. |
| MicrosoftATP.Machine.RiskScore | String | The machine risk score. |
| MicrosoftATP.Machine.ExposureLevel | String | The machine exposure score. |
| MicrosoftATP.Machine.IsAADJoined | Boolean | True if machine is AAD joined, False otherwise. |
| MicrosoftATP.Machine.AADDeviceID | String | The AAD Device ID. |
| MicrosoftATP.Machine.MachineTags | String | Set of machine tags. |
| MicrosoftATP.Machine.IPAddresses.ipAddress | String | The machine IP address. |
| MicrosoftATP.Machine.IPAddresses.MACAddress | String | The machine MAC address. |
| MicrosoftATP.Machine.IPAddresses.operationalStatus | String | The machine operational status. |
| MicrosoftATP.Machine.IPAddresses.type | String | The machine IP address type. |
| MicrosoftATP.Machine.AgentVersion | String | The machine Agent version. |
#### Command example
```!microsoft-atp-get-machine-by-ip ip=8.8.8.8 timestamp=2024-05-23T10:15:00Z```
#### Human Readable Output
>### Microsoft Defender ATP Machine
>
>|ID|ComputerDNSName|OSPlatform|LastIPAddress|LastExternalIPAddress|HealthStatus|RiskScore|ExposureLevel|
>|---|---|---|---|---|---|---|---|
>| f3bba49a | ec2amaz-ua9hieu | WindowsServer2016 | 1.2.3.4 | 127.0.0.1 | Active | None | High |
## Deprecation Details
| **Deprecated Commands** | **Replacement** |
|----------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `Fetch incidents` | Use `Fetch incidents` in the `Microsoft Graph Security` integration, and select `Graph Security Alert` under the `Alert type`. |
| `microsoft-atp-create-alert` | No available replacement. |
| `microsoft-atp-get-alert-by-id` | Use `msg-get-alert-details` in the `Microsoft Graph Security` integration instead. |
| `microsoft-atp-get-alert-related-files` | An alternative is to use the `msg-get-alert-details` command in the `Microsoft Graph Security` integration, which can retrieve `fileDetails` as part of the alert details. See Microsoft documentation [here](https://learn.microsoft.com/en-us/graph/api/resources/security-fileevidence?view=graph-rest-1.0). |
| `microsoft-atp-get-alert-related-ips` | An alternative is to use the `msg-get-alert-details` command in the `Microsoft Graph Security` integration, which can retrieve `IpAddress` as part of the alert details. See Microsoft documentation [here](https://learn.microsoft.com/en-us/graph/api/resources/security-ipevidence?view=graph-rest-1.0). |
| `microsoft-atp-get-alert-related-user` | An alternative is to use the `msg-get-alert-details` command in the `Microsoft Graph Security` integration, which can retrieve `userAccount` information as part of the alert details. See Microsoft documentation [here](https://learn.microsoft.com/en-us/graph/api/resources/security-userevidence?view=graph-rest-1.0). |
| `microsoft-atp-get-alert-related-domains` | An alternative is to use the `msg-get-alert-details` command in the `Microsoft Graph Security` integration to retrieve `DomainName` as part of the alert details. See Microsoft documentation [here](https://learn.microsoft.com/en-us/graph/api/resources/security-userevidence?view=graph-rest-1.0). |
| `microsoft-atp-get-domain-alerts` | No available replacement. |
| `microsoft-atp-get-file-alerts` | No available replacement. |
| `microsoft-atp-get-ip-alerts` | No available replacement. |
| `microsoft-atp-get-machine-alerts` | No available replacement. |
| `microsoft-atp-get-user-alerts` | No available replacement. |
| `microsoft-atp-list-alerts` | Use the `msg-search-alerts` command in the `Microsoft Graph Security` integration instead. |
| `microsoft-atp-update-alert` | Use the `msg-update-alert` command in the `Microsoft Graph Security` integration instead. |
| `microsoft-atp-advanced-hunting` | Use the `msg-advanced-hunting` command in the `Microsoft Graph Security` integration instead. |
### microsoft-atp-get-machine-vulnerabilities
***
Run this command to get the vulnerabilities from a specific machine.
#### Base Command
`microsoft-atp-get-machine-vulnerabilities`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| machine_id | Machine ID. Use the !microsoft-atp-get-machines command to get the ID. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| MicrosoftATP.PublicVulnerability.ID | String | The vulnerability ID. |
| MicrosoftATP.PublicVulnerability.Name | String | The vulnerability name. |
| MicrosoftATP.PublicVulnerability.CVESupportability | String | The CVE supportability. |
| MicrosoftATP.PublicVulnerability.CVSSV3 | Number | The CVSS V3. |
| MicrosoftATP.PublicVulnerability.CVSSVector | String | The CVSS vector. |
| MicrosoftATP.PublicVulnerability.Description | String | A description of this vulnerability. |
| MicrosoftATP.PublicVulnerability.EPSS | Number | The EPSS. |
| MicrosoftATP.PublicVulnerability.ExploitInKit | Boolean | Is this vulnerability in an exploit kit? |
| MicrosoftATP.PublicVulnerability.ExploitTypes | String | The type(s) of exploit(s). |
| MicrosoftATP.PublicVulnerability.ExploitUris | String | The exploit URIs. |
| MicrosoftATP.PublicVulnerability.ExploitVerified | Boolean | Is this exploit verified? |
| MicrosoftATP.PublicVulnerability.ExposedMachines | Number | The amount of machines exposed to this vulnerability. |
| MicrosoftATP.PublicVulnerability.FirstDetected | String | The date and time when this vulnerability was first detected. |
| MicrosoftATP.PublicVulnerability.PublicExploit | Boolean | Does this vulnerability have a public exploit? |
| MicrosoftATP.PublicVulnerability.PublishedOn | String | The date and time when this vulnerability was published. |
| MicrosoftATP.PublicVulnerability.Severity | String | The severity of this vulnerability. |
| MicrosoftATP.PublicVulnerability.Tags | String | The tags associated with this vulnerability. |
| MicrosoftATP.PublicVulnerability.UpdatedOn | String | The date and time when this vulnerability was last updated. |
#### Command example
```!microsoft-atp-get-machine-vulnerabilities machine_id="12342c13fef```
#### Context Example
```json
{
"MicrosoftATP": {
"PublicVulnerability": {
"@odata.context": "https://api.securitycenter.windows.com/api/$metadata#Collection(microsoft.windowsDefenderATP.api.PublicVulnerabilityDto)",
"CVESupportability": "Supported",
"CVSSV3": 3.7,
"CVSSVector": "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L/E:F/RL:O/RC:C",
"Description": "Summary: Foo is vulnerable to a denial of service due to improper server configuration validation.", # noqa: E501
"EPSS": 0,
"ExploitInKit": False,
"ExploitTypes": [
"Remote"
],
"ExploitUris": [],
"ExploitVerified": False,
"ExposedMachines": 1,
"FirstDetected": "20XX-MM-DDThh:mm:ssZ",
"ID": "CVE-20XX-1234",
"Name": "CVE-20XX-1234",
"PublicExploit": False,
"PublishedOn": "20XX-MM-DDThh:mm:ssZ",
"Severity": "Low",
"Tags": [],
"UpdatedOn": "20XX-MM-DDThh:mm:ssZ"
}
}
}
Human Readable Output
Microsoft Defender ATP Vulnerability
ID Name CVESupportability CVSSV3 CVSSVector Description EPSS ExploitInKit ExploitTypes ExploitVerified ExposedMachines FirstDetected PublicExploit PublishedOn Severity UpdatedOn CVE-20XX-1234 CVE-20XX-1234 Supported 3.7 CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L/E:F/RL:O/RC:C Summary: Foo is vulnerable to a denial of service due to improper server configuration validation. 0 false Remote false 1 20XX
microsoft-atp-get-machine-software
Run this command to get the sofware installed on a specific machine.
Base Command
microsoft-atp-get-machine-software
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | Machine ID. Use the !microsoft-atp-get-machines command to get the ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.Software.ID | String | The Software ID. |
| MicrosoftATP.Software.Name | String | The software name. |
| MicrosoftATP.Software.Vendor | String | The software vendor name. |
| MicrosoftATP.Software.Weaknesses | Number | The amount of weaknesses present in the software. |
| MicrosoftATP.Software.PublicExploit | Boolean | Does this software have a public exploit? |
| MicrosoftATP.Software.ActiveAlert | Boolean | Does this software have an active alert? |
| MicrosoftATP.Software.ExposedMachines | Number | The amount of machines exposed to this software. |
| MicrosoftATP.Software.InstalledMachines | Number | The amount of machines with this software installed. |
| MicrosoftATP.Software.ImpactScore | Number | The impact score of the software. |
| MicrosoftATP.Software.IsNormalized | Number | Is the software value normalized? |
| MicrosoftATP.Software.Category | String | The software category. |
| MicrosoftATP.Software.Distributions | String | The distributions on which this software is present. |
Command example
!microsoft-atp-get-machine-software machine_id="12342c13fef
Context Example
{
"MicrosoftATP": {
"Software": {
"@odata.context": "https://api.securitycenter.windows.com/api/$metadata#Software",
"ID": "some_id",
"Name": "some_name",
"Vendor": "some_vendor",
"Weaknesses": 0,
"PublicExploit": false,
"ActiveAlert": false,
"ExposedMachines": 0,
"InstalledMachines": 1,
"ImpactScore": 0,
"IsNormalized": false,
"Category": "",
"Distributions": []
}
}
}
Human Readable Output
Microsoft Defender ATP Software
ID Name Vendor PublicExploit ActiveAlert ExposedMachines InstalledMachines ImpactScore IsNormalized some_id some_name some_vendor false false 0 1 0 false another_id another_name another_vendor true true 0 1 0 false
microsoft-atp-get-machine-missing-kbs
Run this command to get the missing security updates (KBs) from a specific machine.
Base Command
microsoft-atp-get-machine-missing-kbs
Input
| Argument Name | Description | Required |
|---|---|---|
| machine_id | Machine ID. Use the !microsoft-atp-get-machines command to get the ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.PublicProductFix.ID | String | Software ID. |
| MicrosoftATP.PublicProductFix.Name | String | Software name. |
| MicrosoftATP.PublicProductFix.ProductsNames | String | The product names. |
| MicrosoftATP.PublicProductFix.URL | String | URL. |
| MicrosoftATP.PublicProductFix.MachineMissedOn | Number | Machine missed on. |
| MicrosoftATP.PublicProductFix.CVEAddressed | Number | CVE addressed. |
| MicrosoftATP.PublicProductFix.OSBuild | String | The OS Build version. |
Command example
!microsoft-atp-get-machine-missing-kbs machine_id="12342c13fef,12342c13fef8f06606
Context Example
{
"MicrosoftATP": {
"PublicProductFix": {
"@odata.context": "https://api.securitycenter.windows.com/api/$metadata#Collection(microsoft.windowsDefenderATP.api.PublicProductFixDto)",
"ID": "1234567",
"Name": "March 20XX Security Updates",
"ProductsNames": [
"windows_10",
"edge",
"internet_explorer"
],
"URL": "https://catalog.update.microsoft.com/v7/site/Search.aspx?q=KB1234567",
"MachineMissedOn": 1,
"CVEAddressed": 97,
"OSBuild": 12345
}
}
}
Human Readable Output
Microsoft Defender ATP Security Update
ID Name OSBuild URL MachineMissedOn CVEAddressed \n — — — — — — 1234567 March 20XX Security Updates 12345 https://catalog.update.microsoft.com/v7/site/Search.aspx?q=KB1234567 1 97
microsoft-atp-list-auth-permissions
This command gets the permissions from the currently configured credentials. Use for debugging and detecting permission issues.
Base Command
microsoft-atp-list-auth-permissions
Input
There are no input arguments for this command.
Context Output
There is no context output for this command.
file
Checks the file reputation of the specified hash.
Base Command
file
Input
| Argument Name | Description | Required |
|---|---|---|
| file | Hash of the file to query. Supports MD5, SHA1, and SHA256. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| MicrosoftATP.File.Sha1 | String | The SHA1 hash of the file. |
| MicrosoftATP.File.MD5 | String | The MD5 hash of the file. |
| MicrosoftATP.File.Sha256 | String | The SHA256 hash of the file. |
| MicrosoftATP.File.GlobalPrevalence | Number | The file prevalence across the organization. |
| MicrosoftATP.File.GlobalFirstObserved | Date | The first time the file was observed. |
| MicrosoftATP.File.GlobalLastObserved | Date | The last time the file was observed. |
| MicrosoftATP.File.Size | Number | The size of the file. |
| MicrosoftATP.File.FileType | String | The type of the file. |
| MicrosoftATP.File.IsPeFile | Boolean | True if the file is portable executable, False otherwise. |
| MicrosoftATP.File.FilePublisher | String | The file’s publisher. |
| MicrosoftATP.File.FileProductName | String | The file product name. |
| MicrosoftATP.File.Signer | String | The file signer. |
| MicrosoftATP.File.Issuer | String | The file issuer. |
| MicrosoftATP.File.SignerHash | String | The hash of the signing certificate. |
| MicrosoftATP.File.IsValidCertificate | Boolean | Was signing certificate successfully verified by Microsoft Defender ATP agent. |
| MicrosoftATP.File.DeterminationValue | String | The file determination value. |
| MicrosoftATP.File.DeterminationType | String | The file determination type. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.Type | String | The file type. |
| File.Size | Number | The file size. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
Command example
!file file="1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
Context Example
{
"MicrosoftATP": {
"File": {
"Sha1": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"MD5": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"Sha256": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"GlobalPrevalence": 1,
"GlobalFirstObserved": "2022-01-01T00:00:00Z",
"GlobalLastObserved": "2022-01-01T00:00:00Z",
"Size": 123456,
"FileType": "PE",
"IsPeFile": true,
"FilePublisher": "Microsoft Corporation",
"FileProductName": "Microsoft Windows",
"Signer": "Microsoft Corporation",
"Issuer": "Microsoft Corporation",
"SignerHash": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"IsValidCertificate": true,
"DeterminationValue": "Malicious",
"DeterminationType": "MachineLearning",
}
},
"File": {
"SHA1": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"SHA256": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"Type": "PE",
"Size": 123456,
},
"DBotScore": {
"Indicator": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"Type": "hash",
"Vendor": "Microsoft Defender ATP",
"Score": 3
}
}
Human Readable Output
Microsoft Defender ATP File
SHA1 MD5 SHA256 GlobalPrevalence GlobalFirstObserved GlobalLastObserved Size FileType IsPeFile FilePublisher FileProductName Signer Issuer SignerHash IsValidCertificate DeterminationValue DeterminationType 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef 1 2022-01-01T00:00:00Z 2022-01-01T00:00:00Z 123456 PE true Microsoft Corporation Microsoft Windows Microsoft Corporation Microsoft Corporation 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef true Malicious MachineLearning
Configuration parameters
endpoint_type— Endpoint Type_auth_id_encrypted—_tenant_id_encrypted—_auth_id— ID_tenant_id— Tokencredentials—creds_certificate— Certificate Thumbprintcertificate_thumbprint— Certificate Thumbprintprivate_key— Private Keyauth_type— Authentication Typeredirect_uri— Application redirect URI (for authorization code mode)auth_code— Authorization codemanaged_identities_client_id—Reliability— Source ReliabilityisFetch— Fetch incidentsincidentType— Incident typeincidentFetchInterval— Incidents Fetch Intervalfetch_status— Status for fetching alerts as incidents. Comma-separated lists are supported, e.g., New,Resolved.fetch_detectionsource— DetectionSource to filter out alerts for fetching as incidents.fetch_severity— Severity for fetching alerts as incidents. Comma-separated lists are supported, e.g., Medium,High.max_fetch— Maximum number of incidents to fetchurl— Server URL (e.g., https://api.securitycenter.microsoft.com)self_deployed— Use a self-deployed Azure Applicationinsecure— Trust any certificate (not secure)fetch_evidence— Fetch alert evidenceproxy— Use system proxy settingsfirst_fetch_timestamp— First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days)is_gcc— Using Microsoft GCC? (Deprecated)auth_id— ID (received from the admin consent - see Detailed Instructions (?) section) (Deprecated)tenant_id— Token (received from the admin consent - see Detailed Instructions (?) (Deprecated) section)enc_key— Key (received from the admin consent - see Detailed Instructions (?) section) (Deprecated)
Commands (81)
-
endpointGets machines that have communicated with Microsoft Defender for Endpoint cloud. At least one of the following arguments is required - IP, hostname, or ID. Otherwise, an error appears.
-
fileChecks the file reputation of the specified hash.
-
microsoft-atp-add-remove-machine-tagAdds or removes a tag on a specific machine.
-
microsoft-atp-advanced-huntingDeprecatedDeprecated. Use the 'msg-advanced-hunting' command in the 'Microsoft Graph Security' integration instead.
-
microsoft-atp-advanced-hunting-cover-upDetects cover up actions. When you select a “query_purpose” argument, a designated query template is used.
-
microsoft-atp-advanced-hunting-file-originIndicates how the file got on the machine. Possible details are "dropped_file" - Was the file dropped? From where? "created_file" - Created by another File (script, compiled binary). "network_shared" - Shared via network. "execution_chain" - What is the process execution chain.
-
microsoft-atp-advanced-hunting-lateral-movement-evidenceDetects evidence of attempted lateral movement. When you select a “query_purpose” argument, a designated query template is used.
-
microsoft-atp-advanced-hunting-network-connectionsDetects network connections. When you select a “query_purpose” argument, a designated query template is used.
-
microsoft-atp-advanced-hunting-persistence-evidenceDetects evidence of persistence. When you select a “query_purpose” argument, a designated query template is used.
-
microsoft-atp-advanced-hunting-privilege-escalationDetects evidence of privilege escalation.
-
microsoft-atp-advanced-hunting-process-detailsDetects process details. When you select a “query_purpose” argument, a designated query template is used.
-
microsoft-atp-advanced-hunting-tamperingDetects evidence of MSDE agent/sensor manipulation.
-
microsoft-atp-auth-resetRun this command if for some reason you need to rerun the authentication process.
-
microsoft-atp-collect-investigation-packageCollect an investigation package from a machine.
-
microsoft-atp-create-alertDeprecatedDeprecated. No available replacement.
-
microsoft-atp-generate-login-urlGenerate the login url used for Authorization code flow.
-
microsoft-atp-get-alert-by-idDeprecatedDeprecated. Use 'msg-get-alert-details' in the 'Microsoft Graph Security' integration instead.
-
microsoft-atp-get-alert-related-domainsDeprecatedDeprecated. An alternative is to use the 'msg-get-alert-details' command in the 'Microsoft Graph Security' integration to retrieve `DomainName` as part of the alert details.
-
microsoft-atp-get-alert-related-filesDeprecatedDeprecated. An alternative is to use the 'msg-get-alert-details' command in the 'Microsoft Graph Security' integration, which can retrieve `fileDetails` as part of the alert details.
-
microsoft-atp-get-alert-related-ipsDeprecatedDeprecated. An alternative is to use the 'msg-get-alert-details' command in the 'Microsoft Graph Security' integration, which can retrieve `IpAddress` as part of the alert details.
-
microsoft-atp-get-alert-related-userDeprecatedDeprecated. An alternative is to use the 'msg-get-alert-details' command in the 'Microsoft Graph Security' integration, which can retrieve `userAccount` information as part of the alert details.
-
microsoft-atp-get-domain-alertsDeprecatedDeprecated. No available replacement.
-
microsoft-atp-get-domain-machinesRetrieves a collection of machines that have communicated to or from a given domain address.
-
microsoft-atp-get-domain-statisticsRetrieves statistics on the given domain.
-
microsoft-atp-get-file-alertsDeprecatedDeprecated. No available replacement.
-
microsoft-atp-get-file-infoRetrieves file information by a file hash (SHA1 or SHA256).
-
microsoft-atp-get-file-related-machinesGets a collection of machines with a given file SHA1 hash.
-
microsoft-atp-get-file-statisticsRetrieves statistics for the given file.
-
microsoft-atp-get-investigation-package-sas-uriGets a URI that allows downloading an investigation package.
-
microsoft-atp-get-ip-alertsDeprecatedDeprecated. No available replacement.
-
microsoft-atp-get-ip-statisticsRetrieves statistics for a given IP.
-
microsoft-atp-get-machine-alertsDeprecatedDeprecated. No available replacement.
-
microsoft-atp-get-machine-by-ipFind Machines seen with the requested internal IP in the time range of 15 minutes prior and after a given timestamp.
-
microsoft-atp-get-machine-detailsGet a machine's details by its identity.
-
microsoft-atp-get-machine-missing-kbsGet the specific machine's missing security updates (KBs).
-
microsoft-atp-get-machine-softwareGet the specific machine's software details.
-
microsoft-atp-get-machine-usersRetrieves a collection of logged on users on a specific device.
-
microsoft-atp-get-machine-vulnerabilitiesGet the specific machine's vulnerabilities.
-
microsoft-atp-get-machinesRetrieves a collection of machines that communicated with WDATP cloud in the last 30 days. Note - only IP or hostname can be a comma-separated list. If both are given as lists, an error will appear.
-
microsoft-atp-get-user-alertsDeprecatedDeprecated. No available replacement.
-
microsoft-atp-get-user-machinesRetrieves a collection of machines related to a given user ID.
-
microsoft-atp-indicator-batch-updateUpdates a batch of indicators. If an indicator does not exist, a new indicator is created.
-
microsoft-atp-indicator-create-fileDeprecatedDeprecated. Use the microsoft-atp-sc-indicator-create command instead. Creates a file indicator.
-
microsoft-atp-indicator-create-networkDeprecatedDeprecated. Use the microsoft-atp-sc-indicator-create command instead. Creates a network indicator.
-
microsoft-atp-indicator-deleteDeprecatedDeprecated. Use the microsoft-atp-sc-indicator-delete command instead. Deletes the specified indicator.
-
microsoft-atp-indicator-get-by-idDeprecatedDeprecated. Use the microsoft-atp-sc-indicator-get-by-id command instead. Gets an indicator by its ID.
-
microsoft-atp-indicator-listDeprecatedDeprecated. Use the microsoft-atp-sc-indicator-list command instead. Lists all indicators by the ID that the system creates when the indicator is ingested.
-
microsoft-atp-indicator-updateDeprecatedDeprecated. Use the microsoft-atp-sc-indicator-update command instead. Updates the specified indicator.
-
microsoft-atp-isolate-machineIsolates a machine from accessing external networks.
-
microsoft-atp-list-alertsDeprecatedDeprecated. Use the 'msg-search-alerts' command in the 'Microsoft Graph Security' integration instead.
-
microsoft-atp-list-auth-permissionsThis command gets the permissions from the currently configured credentials. Use for debugging and detecting permission issues.
-
microsoft-atp-list-investigationsRetrieves a collection of investigations or retrieves a specific investigation by its ID.
-
microsoft-atp-list-machine-actions-detailsReturn the machine's actions. If you set an action ID, it returns the info on the specific action. Filtering can be done only on one argument.
-
microsoft-atp-list-machines-by-softwareRetrieve a list of device references that has this software installed.
-
microsoft-atp-list-machines-by-vulnerabilityRetrieves a list of machines affected by a vulnerability.
-
microsoft-atp-list-missing-kb-by-softwareRetrieves missing KBs (security updates) by software ID.
-
microsoft-atp-list-softwareRetrieves the organization software inventory.
-
microsoft-atp-list-software-version-distributionRetrieves a list of your organization's software version distribution.
-
microsoft-atp-list-vulnerabilitiesRetrieves a list of all vulnerabilities.
-
microsoft-atp-list-vulnerabilities-by-machineRetrieves a list of all the vulnerabilities affecting the organization per machine.
-
microsoft-atp-list-vulnerabilities-by-softwareRetrieves a list of all the vulnerabilities affecting the organization per software.
-
microsoft-atp-live-response-cancel-actionCancels an action with an unfinished status.
-
microsoft-atp-live-response-get-fileCollects a file from a device. Note: Backslashes in the path must be escaped.
-
microsoft-atp-live-response-put-filePuts a file from the library to the device. Files are saved in a working folder and are deleted when the device restarts by default.
-
microsoft-atp-live-response-resultGets a result file for a specified action.
-
microsoft-atp-live-response-run-scriptRuns a script from the library on a device. The Args parameter is passed to your script. Timeouts after 10 minutes.
-
microsoft-atp-offboard-machineOffboard a machine from Microsoft Defender for Endpoint.
-
microsoft-atp-remove-app-restrictionEnable the execution of any application on the machine.
-
microsoft-atp-request-and-download-investigation-packageCollect and download an investigation package from a machine.
-
microsoft-atp-restrict-app-executionRestricts the execution of all applications on the machine except for a predefined set.
-
microsoft-atp-run-antivirus-scanInitiate a Microsoft Defender Antivirus scan on a machine.
-
microsoft-atp-sc-indicator-createCreates a new indicator.
-
microsoft-atp-sc-indicator-deleteDeletes the specified indicator.
-
microsoft-atp-sc-indicator-get-by-idGets an indicator by its ID.
-
microsoft-atp-sc-indicator-listLists all indicators by the ID that the system creates when the indicator is ingested.
-
microsoft-atp-sc-indicator-updateUpdates the specified indicator.
-
microsoft-atp-start-investigationStarts an automated investigation on a machine.
-
microsoft-atp-stop-and-quarantine-fileStop the execution of a file on a machine and delete it.
-
microsoft-atp-testTests connectivity to Microsoft Defender for Endpoint.
-
microsoft-atp-unisolate-machineUndo an isolation of a machine.
-
microsoft-atp-update-alertDeprecatedDeprecated. Use the 'msg-update-alert' command in the 'Microsoft Graph Security' integration instead.
import copy import dataclasses from collections.abc import Callable from itertools import product from json import JSONDecodeError from typing import Any import urllib3 import jwt from CommonServerPython import * from dateutil.parser import parse from MicrosoftApiModule import * # noqa: E402 from requests import Response # Disable insecure warnings urllib3.disable_warnings() """ GLOBAL VARS """ APP_NAME = "ms-defender-atp" TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%fZ" """ HELPER FUNCTIONS """ # GCC High and DoD tenants do not have the 'windowsatpservice' resource principal # in their Azure AD, so the scope must use the API endpoint directly. GOVERNMENT_ENDPOINT_TYPES = {"gcc-high", "dod"} def get_defender_scope(endpoint_type: str) -> str: """Returns the correct OAuth scope for the given MDE endpoint type. For GCC High and DoD, the 'windowsatpservice' service principal does not exist in the government Azure AD tenant, so the scope uses the API endpoint directly. For all other endpoint types, the scope uses the APT service endpoint with '/windowsatpservice/.default'. Args: endpoint_type: The endpoint type key (e.g., 'com', 'gcc-high', 'dod'). Returns: The OAuth scope URL string. """ if endpoint_type in GOVERNMENT_ENDPOINT_TYPES: return urljoin(MICROSOFT_DEFENDER_FOR_ENDPOINT_API[endpoint_type], "/.default") return urljoin(MICROSOFT_DEFENDER_FOR_ENDPOINT_APT_SERVICE_ENDPOINTS[endpoint_type], "/windowsatpservice/.default") SEVERITY_TO_NUMBER = {"Informational": 0, "Low": 1, "MediumLow": 2, "MediumHigh": 3, "High": 4} NUMBER_TO_SEVERITY = {0: "Informational", 1: "Low", 2: "MediumLow", 3: "MediumHigh", 4: "High", 5: "Informational"} SC_INDICATORS_HEADERS = ( "id", "action", "indicatorValue", "indicatorType", "severity", "title", "description", ) INDICATOR_TYPE_TO_DBOT_TYPE = { "FileSha256": DBotScoreType.FILE, "FileSha1": DBotScoreType.FILE, "FileMd5": DBotScoreType.FILE, "Url": DBotScoreType.URL, "DomainName": DBotScoreType.DOMAIN, "IpAddress": DBotScoreType.IP, "CertificateThumbprint": None, } HEALTH_STATUS_TO_ENDPOINT_STATUS = { "Active": "Online", "Inactive": "Offline", "ImpairedCommunication": "Online", "NoSensorData": "Online", "NoSensorDataImpairedCommunication": "Online", "Unknown": None, } DETECTION_SOURCE_TO_API_VALUE = { # https://learn.microsoft.com/en-us/microsoft-365/security/defender-endpoint/alerts-queue "Third-party sensors": "ThirdPartySensors", "Antivirus": "WindowsDefenderAv", "Automated investigation": "AutomatedInvestigation", "Custom detection": "CustomDetection", "Custom TI": "CustomerTI", "EDR": "WindowsDefenderAtp", "Microsoft 365 Defender": "MTP", "Microsoft Defender for Office 365": "OfficeATP", "Microsoft Defender Experts": "ThreatExperts", "SmartScreen": "WindowsDefenderSmartScreen", } INTEGRATION_NAME = "Microsoft Defender ATP" @dataclasses.dataclass class FileStatisticsAPIParser: sha1: str org_prevalence: str organization_prevalence: int org_first_seen: str | None # same as 'org_prevalence', but as integer org_last_seen: str | None global_prevalence: str globally_prevalence: int # same as 'global_prevalence', but as integer global_first_observed: str global_last_observed: str top_file_names: list[str] @classmethod def from_raw_response(cls, raw_response: dict): """Creates an instance from the file stats API raw response body (ignores extra fields, if any). Args: raw_response (dict): File stats API response Returns: FileStatisticsAPIParser """ dataclass_field_names = {field.name for field in dataclasses.fields(cls)} snake_case_response = snakify(raw_response) return cls(**{key: value for key, value in snake_case_response.items() if key in dataclass_field_names}) def to_context_output(self) -> dict: """Generates context output from an instance of FileStatisticsAPIParser. Returns: dict: context output """ return { "Sha1": self.sha1, "Statistics": assign_params( **{camelize_string(key): value for key, value in dataclasses.asdict(self).items() if key != "sha1"} ), } def to_human_readable(self, file_hash: str) -> str: """Generates a human readable table from an instance of FileStatisticsAPIParser. Args: file_hash (str): The hash of the file Returns: str: human readable markdown table """ table_data = {self.format_for_table(key): value for key, value in dataclasses.asdict(self).items() if key != "sha1"} return tableToMarkdown(f"Statistics on {file_hash} file:", table_data, removeNull=True) def to_file_indicator(self, file_hash: str) -> Common.File: """Generates a File indicator object from an instance of FileStatisticsAPIParser. Args: file_hash (str): The hash of the file Returns: Common.File """ return Common.File( dbot_score=Common.DBotScore(file_hash, DBotScoreType.FILE, INTEGRATION_NAME, Common.DBotScore.NONE), sha1=self.sha1, organization_prevalence=self.organization_prevalence, global_prevalence=self.globally_prevalence, organization_first_seen=self.org_first_seen, organization_last_seen=self.org_last_seen, first_seen_by_source=self.global_first_observed, last_seen_by_source=self.global_last_observed, ) @staticmethod def format_for_table(field_name: str) -> str: """Replaces certain words and formats fields from 'snake_case' to 'Space Case'. Args: field_name (str): Name of field in snake_case. Returns: str: Formatted in Space Case with replacements. """ replacements = {"globally_": "global_", "org_": "organization_"} for old_value, new_value in replacements.items(): field_name = field_name.replace(old_value, new_value) return pascalToSpace(camelize_string(field_name)) class HuntingQueryBuilder: """ERROR MESSAGES""" FILE_ARGS_ERR = 'Please provide at least one file arguments: "file_name", "sha1", "sha256" or "md5".' DEVICES_ARGS_ERR = 'Please provide at least one devices arguments: "device_id" or "device_name".' ANY_ARGS_ERR = ( 'Please provide at least one of the query args: "device_name", "file_name", "sha1, "sha256", "md5" or "device_id".' ) @staticmethod def get_time_range_query(time_range: str | None) -> str: """ Given a human readable time_range returns the time_range query """ if not time_range: return "" parsed_time = dateparser.parse(time_range) if parsed_time: time_in_minutes = int((datetime.now() - parsed_time).total_seconds() // 60) return f"Timestamp > ago({time_in_minutes}m)" else: return "" @staticmethod def rebuild_query_with_time_range(query: str, time_range: str) -> str: """ Given a query and human readable time_range returns the query with a time_range query """ time_range_query = HuntingQueryBuilder.get_time_range_query(time_range) insert_pos = query.find("|") if insert_pos == -1: return f"{query} | where {time_range_query}" return f"{query[:insert_pos]}| where {time_range_query} {query[insert_pos:]}" @staticmethod def get_filter_values(list_values: list | str | None) -> str | None: """ creates a string of CSV values wrapped by parenthesis and brackets """ if isinstance(list_values, str): list_values = argToList(list_values) if not list_values or not isinstance(list_values, list): return None return '("' + '","'.join(list_values) + '")' @staticmethod def remove_last_expression(query, expression): """ Removes the last expression from the given query """ return query.rsplit(expression, 1)[0] @staticmethod def build_generic_query( query_prefix: str, query_suffix: str, query_dict: dict, query_operation: str, operator: str = "has_any" ): if not query_dict: return query_prefix + query_suffix query = query_prefix + " (" for key, val in query_dict.items(): if isinstance(val, tuple): # dict_val with special operator query += f" {key} {val[0]} {val[1]} {query_operation}" else: query += f" ({key} {operator} {val}) {query_operation}" query = HuntingQueryBuilder.remove_last_expression(query, query_operation) query += ")" if query_suffix: return query + query_suffix return query class LateralMovementEvidence: """QUERY PREFIX""" NETWORK_CONNECTIONS_QUERY_PREFIX = 'DeviceNetworkEvents\n| where (RemoteIP startswith "172.16" or RemoteIP startswith "192.168" or RemoteIP startswith "10.") and' # noqa: E501 SMB_CONNECTIONS_QUERY_PREFIX = "DeviceNetworkEvents\n| where RemotePort == 445 and InitiatingProcessId !in (0, 4) and" # noqa: E501 CREDENTIAL_DUMPING_QUERY_PREFIX = 'DeviceProcessEvents\n| where ((FileName has_any ("procdump.exe", "procdump64.exe") and ProcessCommandLine has "lsass") or (ProcessCommandLine has "lsass.exe" and (ProcessCommandLine has "-accepteula" or ProcessCommandLine contains "-ma")) ) and' # noqa: E501 MANAGEMENT_CONNECTION_QUERY_PREFIX = "DeviceNetworkEvents\n| where RemotePort in (22,3389,139,135,23,1433) and" """QUERY SUFFIX""" NETWORK_CONNECTIONS_QUERY_SUFFIX = "\n| summarize TotalConnections = count() by DeviceName, RemoteIP, RemotePort, InitiatingProcessFileName\n| order by TotalConnections\n| limit {}" # noqa: E501 SMB_CONNECTIONS_QUERY_SUFFIX = "\n| summarize RemoteIPCount=dcount(RemoteIP) by DeviceName, InitiatingProcessFileName, InitiatingProcessId, InitiatingProcessCreationTime\n|{} limit {}" # noqa: E501 CREDENTIAL_DUMPING_QUERY_SUFFIX = "\n| project Timestamp, DeviceName, ActionType, FileName, ProcessCommandLine, AccountName, InitiatingProcessIntegrityLevel, InitiatingProcessTokenElevation\n| limit {}" # noqa: E501 MANAGEMENT_CONNECTION_QUERY_SUFFIX = ( "\n| summarize TotalCount=count() by DeviceName,LocalIP,RemoteIP,RemotePort\n| order by TotalCount\n| limit {}" # noqa: E501 ) def __init__( self, limit: str, query_operation: str, page: str, device_name: str | None = None, file_name: str | None = None, sha1: str | None = None, sha256: str | None = None, md5: str | None = None, device_id: str | None = None, remote_ip_count: str | None = None, ): if not (device_name or file_name or sha1 or sha256 or md5 or device_id): raise DemistoException(HuntingQueryBuilder.ANY_ARGS_ERR) self._limit = limit * (int(page)) self._query_operation = query_operation self._device_name = HuntingQueryBuilder.get_filter_values(device_name) self._file_name = HuntingQueryBuilder.get_filter_values(file_name) self._sha1 = HuntingQueryBuilder.get_filter_values(sha1) self._sha256 = HuntingQueryBuilder.get_filter_values(sha256) self._md5 = HuntingQueryBuilder.get_filter_values(md5) self._device_id = HuntingQueryBuilder.get_filter_values(device_id) self._remote_ip_count = remote_ip_count def build_network_connections_query(self): query_dict = assign_params( InitiatingProcessFileName=self._file_name, InitiatingProcessSHA1=self._sha1, InitiatingProcessSHA256=self._sha256, InitiatingProcessMD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.NETWORK_CONNECTIONS_QUERY_PREFIX, query_suffix=self.NETWORK_CONNECTIONS_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_smb_connections_query(self): query_dict = assign_params( InitiatingProcessFileName=self._file_name, InitiatingProcessSHA1=self._sha1, InitiatingProcessSHA256=self._sha256, InitiatingProcessMD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) remote_ip_count_query = "" if not self._remote_ip_count else f" where RemoteIPCount > {self._remote_ip_count} |" query = HuntingQueryBuilder.build_generic_query( query_prefix=self.SMB_CONNECTIONS_QUERY_PREFIX, query_suffix=self.SMB_CONNECTIONS_QUERY_SUFFIX.format(remote_ip_count_query, self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_credential_dumping_query(self): query_dict = assign_params( FileName=self._file_name, SHA1=self._sha1, SHA256=self._sha256, MD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.CREDENTIAL_DUMPING_QUERY_PREFIX, query_suffix=self.CREDENTIAL_DUMPING_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_management_connection_query(self): query_dict = assign_params( InitiatingProcessFileName=self._file_name, InitiatingProcessSHA1=self._sha1, InitiatingProcessSHA256=self._sha256, InitiatingProcessMD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.MANAGEMENT_CONNECTION_QUERY_PREFIX, query_suffix=self.MANAGEMENT_CONNECTION_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query class PersistenceEvidence: """QUERY PREFIX""" SCHEDULE_JOB_QUERY_PREFIX = ( 'DeviceEvents | where ActionType == "ScheduledTaskCreated" and InitiatingProcessAccountSid != "S-1-5-18" and' # noqa: E501 ) REGISTRY_ENTRY_QUERY_PREFIX = 'DeviceRegistryEvents | where ActionType == "RegistryValueSet" and' STARTUP_FOLDER_CHANGES_QUERY_PREFIX = r"""DeviceFileEvents | where FolderPath contains @"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup" and ActionType == "FileCreated" and""" # noqa: E501 NEW_SERVICE_CREATED_QUERY_PREFIX = r"""DeviceRegistryEvents | where RegistryKey contains @"HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services" and ActionType == "RegistryKeyCreated" and""" # noqa: E501 SERVICE_UPDATED_QUERY_PREFIX = r"""DeviceRegistryEvents | where RegistryKey contains @"HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services" and ActionType has_any ("RegistryValueSet","RegistryKeyCreated") and""" # noqa: E501 FILE_REPLACED_QUERY_PREFIX = ( r"""DeviceFileEvents | where FolderPath contains @"C:\Program Files" and ActionType == "FileModified" and""" # noqa: E501 ) NEW_USER_QUERY_PREFIX = 'DeviceEvents | where ActionType == "UserAccountCreated" and' NEW_GROUP_QUERY_PREFIX = 'DeviceEvents | where ActionType == "SecurityGroupCreated" and' GROUP_USER_CHANGE_QUERY_PREFIX = 'DeviceEvents | where ActionType == "UserAccountAddedToLocalGroup" and' LOCAL_FIREWALL_CHANGE_QUERY_PREFIX = r"""DeviceRegistryEvents | where RegistryKey contains @"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy" and""" # noqa: E501 HOST_FILE_CHANGE_QUERY_PREFIX = r"""DeviceFileEvents | where FolderPath contains @"C:\Windows\System32\drivers\etc\hosts" and ActionType == "FileModified" and""" # noqa: E501 """QUERY SUFFIX""" SCHEDULE_JOB_QUERY_SUFFIX = "\n| project Timestamp, DeviceName, InitiatingProcessAccountDomain, InitiatingProcessAccountName, AdditionalFields\n| limit {}" # noqa: E501 REGISTRY_ENTRY_QUERY_SUFFIX = "\n| project Timestamp, DeviceName, RegistryKey, RegistryValueType, PreviousRegistryValueData, RegistryValueName, PreviousRegistryValueName, PreviousRegistryKey, InitiatingProcessFileName\n| limit {}" # noqa: E501 STARTUP_FOLDER_CHANGES_QUERY_SUFFIX = "\n| project Timestamp, DeviceName, FileName, FolderPath, InitiatingProcessFileName, InitiatingProcessVersionInfoProductName, InitiatingProcessVersionInfoOriginalFileName, InitiatingProcessCommandLine\n| limit {}" # noqa: E501 NEW_SERVICE_CREATED_QUERY_SUFFIX = "\n| project Timestamp, DeviceName, RegistryKey, RegistryValueName, RegistryValueType, RegistryValueData, InitiatingProcessFileName, InitiatingProcessVersionInfoProductName, InitiatingProcessVersionInfoOriginalFileName, InitiatingProcessCommandLine\n| limit {}" # noqa: E501 SERVICE_UPDATED_QUERY_SUFFIX = "\n| project Timestamp, DeviceName, ActionType, RegistryKey, PreviousRegistryKey, RegistryValueName, PreviousRegistryValueName, RegistryValueType, RegistryValueData, PreviousRegistryValueData, InitiatingProcessFileName, InitiatingProcessVersionInfoProductName, InitiatingProcessVersionInfoOriginalFileName, InitiatingProcessCommandLine\n| limit {}" # noqa: E501 FILE_REPLACED_QUERY_SUFFIX = "\n| project Timestamp, DeviceName, ActionType, FileName, FolderPath, InitiatingProcessFileName, InitiatingProcessVersionInfoProductName, InitiatingProcessVersionInfoOriginalFileName, InitiatingProcessCommandLine\n| limit {}" # noqa: E501 NEW_USER_QUERY_SUFFIX = "\n| project AccountName,DeviceName,Timestamp,AccountSid,AccountDomain,InitiatingProcessAccountName,InitiatingProcessLogonId\n| limit {}" # noqa: E501 NEW_GROUP_QUERY_SUFFIX = "\n| project AccountName,DeviceName,Timestamp,AccountSid,AccountDomain,InitiatingProcessAccountName,InitiatingProcessLogonId,AdditionalFields\n| limit {}" # noqa: E501 GROUP_USER_CHANGE_QUERY_SUFFIX = "\n| summarize by AccountSid\n| limit {}" LOCAL_FIREWALL_CHANGE_QUERY_SUFFIX = "\n| project Timestamp, DeviceName, ActionType, RegistryKey, PreviousRegistryKey, RegistryValueName, PreviousRegistryValueName, RegistryValueType, RegistryValueData, PreviousRegistryValueData, InitiatingProcessFileName, InitiatingProcessVersionInfoProductName, InitiatingProcessVersionInfoOriginalFileName, InitiatingProcessCommandLine\n| limit {}" # noqa: E501 HOST_FILE_CHANGE_QUERY_SUFFIX = "\n| project Timestamp, DeviceName, ActionType, FileName, FolderPath, SHA1, SHA256, MD5, InitiatingProcessFileName, InitiatingProcessVersionInfoProductName, InitiatingProcessVersionInfoOriginalFileName, InitiatingProcessCommandLine\n| limit {}" # noqa: E501 def __init__( self, limit: str, query_operation: str, query_purpose: str, page: str, device_name: str | None = None, file_name: str | None = None, sha1: str | None = None, sha256: str | None = None, md5: str | None = None, device_id: str | None = None, process_cmd: str | None = None, ): if query_purpose == "registry_entry" and not process_cmd: raise DemistoException('Cannot initiate "registry_entry" query without "process_cmd" argument.') elif not (device_name or file_name or sha1 or sha256 or md5 or device_id): raise DemistoException(HuntingQueryBuilder.ANY_ARGS_ERR) self._limit = limit * (int(page)) self._query_operation = query_operation self._device_name = HuntingQueryBuilder.get_filter_values(device_name) self._file_name = HuntingQueryBuilder.get_filter_values(file_name) self._sha1 = HuntingQueryBuilder.get_filter_values(sha1) self._sha256 = HuntingQueryBuilder.get_filter_values(sha256) self._md5 = HuntingQueryBuilder.get_filter_values(md5) self._device_id = HuntingQueryBuilder.get_filter_values(device_id) self._process_cmd = ("contains", f'"{process_cmd}"') if process_cmd else None def build_scheduled_job_query(self): query_dict = assign_params( FileName=self._file_name, SHA1=self._sha1, SHA256=self._sha256, MD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.SCHEDULE_JOB_QUERY_PREFIX, query_suffix=self.SCHEDULE_JOB_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_registry_entry_query(self): query_dict = assign_params( InitiatingProcessFileName=self._file_name, InitiatingProcessSHA1=self._sha1, InitiatingProcessSHA256=self._sha256, InitiatingProcessMD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, InitiatingProcessCommandLine=self._process_cmd, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.REGISTRY_ENTRY_QUERY_PREFIX, query_suffix=self.REGISTRY_ENTRY_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_startup_folder_changes_query(self): query_dict = assign_params( FileName=self._file_name, SHA1=self._sha1, SHA256=self._sha256, MD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.STARTUP_FOLDER_CHANGES_QUERY_PREFIX, query_suffix=self.STARTUP_FOLDER_CHANGES_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_new_service_created_query(self): query_dict = assign_params( InitiatingProcessFileName=self._file_name, InitiatingProcessSHA1=self._sha1, InitiatingProcessSHA256=self._sha256, InitiatingProcessMD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, InitiatingProcessCommandLine=self._process_cmd, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.NEW_SERVICE_CREATED_QUERY_PREFIX, query_suffix=self.NEW_SERVICE_CREATED_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_service_updated_query(self): query_dict = assign_params( InitiatingProcessFileName=self._file_name, InitiatingProcessSHA1=self._sha1, InitiatingProcessSHA256=self._sha256, InitiatingProcessMD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, InitiatingProcessCommandLine=self._process_cmd, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.SERVICE_UPDATED_QUERY_PREFIX, query_suffix=self.SERVICE_UPDATED_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_file_replaced_query(self): query_dict = assign_params( FileName=self._file_name, SHA1=self._sha1, SHA256=self._sha256, MD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.FILE_REPLACED_QUERY_PREFIX, query_suffix=self.FILE_REPLACED_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_new_user_query(self): query_dict = assign_params( FileName=self._file_name, SHA1=self._sha1, SHA256=self._sha256, MD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.NEW_USER_QUERY_PREFIX, query_suffix=self.NEW_USER_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_new_group_query(self): query_dict = assign_params( FileName=self._file_name, SHA1=self._sha1, SHA256=self._sha256, MD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.NEW_GROUP_QUERY_PREFIX, query_suffix=self.NEW_GROUP_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_group_user_change_query(self): query_dict = assign_params( FileName=self._file_name, SHA1=self._sha1, SHA256=self._sha256, MD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.GROUP_USER_CHANGE_QUERY_PREFIX, query_suffix=self.GROUP_USER_CHANGE_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_local_firewall_change_query(self): query_dict = assign_params( InitiatingProcessFileName=self._file_name, InitiatingProcessSHA1=self._sha1, InitiatingProcessSHA256=self._sha256, InitiatingProcessMD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, InitiatingProcessCommandLine=self._process_cmd, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.LOCAL_FIREWALL_CHANGE_QUERY_PREFIX, query_suffix=self.LOCAL_FIREWALL_CHANGE_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_host_file_change_query(self): query_dict = assign_params( InitiatingProcessFileName=self._file_name, InitiatingProcessSHA1=self._sha1, InitiatingProcessSHA256=self._sha256, InitiatingProcessMD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, InitiatingProcessCommandLine=self._process_cmd, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.HOST_FILE_CHANGE_QUERY_PREFIX, query_suffix=self.HOST_FILE_CHANGE_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query class FileOrigin: """QUERY PREFIX""" FILE_ORIGIN_QUERY_PREFIX = "DeviceFileEvents | where" """QUERY SUFFIX""" FILE_ORIGIN_QUERY_SUFFIX = "\n| project Timestamp,FileName,FolderPath, ActionType,DeviceName,MD5,SHA1,SHA256,FileSize,FileOriginUrl,FileOriginIP,InitiatingProcessCommandLine,InitiatingProcessFileName,InitiatingProcessParentFileName\n| limit {}" # noqa: E501 def __init__( self, limit: str, query_operation: str, page: str, device_name: str | None = None, file_name: str | None = None, sha1: str | None = None, sha256: str | None = None, md5: str | None = None, device_id: str | None = None, ): if not (device_name or file_name or sha1 or sha256 or md5 or device_id): raise DemistoException( 'Please provide at least one of the query args: "device_name", "file_name", "sha1, ' '"sha256", "md5" or "device_id".' ) self._limit = limit * (int(page)) self._query_operation = query_operation self._device_name = HuntingQueryBuilder.get_filter_values(device_name) self._file_name = HuntingQueryBuilder.get_filter_values(file_name) self._sha1 = HuntingQueryBuilder.get_filter_values(sha1) self._sha256 = HuntingQueryBuilder.get_filter_values(sha256) self._md5 = HuntingQueryBuilder.get_filter_values(md5) self._device_id = HuntingQueryBuilder.get_filter_values(device_id) def build_file_origin_query(self): query_dict = assign_params( FileName=self._file_name, SHA1=self._sha1, SHA256=self._sha256, MD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.FILE_ORIGIN_QUERY_PREFIX, query_suffix=self.FILE_ORIGIN_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query class ProcessDetails: """QUERY PREFIX""" GENERIC_PROCESS_DETAILS_QUERY_PREFIX = "DeviceProcessEvents | where" BECAONING_QUERY_PREFIX = "DeviceNetworkEvents | where" POWERSHELL_EXECUTION_PROCESS_QUERY_PREFIX = ( 'DeviceProcessEvents | where FileName in~ ("powershell.exe", "powershell_ise.exe",".ps") and' # noqa: E501 ) POWERSHELL_EXECUTION_PROCESS_UNSIGNED_QUERY_PREFIX = 'DeviceProcessEvents | where FileName in~ ("powershell.exe", "powershell_ise.exe",".ps") and ( InitiatingProcessFileName != "SenseIR.exe" and InitiatingProcessParentFileName != "MsSense.exe" and InitiatingProcessSignatureStatus != "Valid" ) and (InitiatingProcessFileName != "CompatTelRunner.exe" and InitiatingProcessParentFileName != "CompatTelRunner.exe")' # noqa: E501 """QUERY SUFFIX""" PARENT_PROCESS_QUERY_SUFFIX = "\n| project Timestamp, DeviceId, DeviceName, ActionType, ProcessId, ProcessCommandLine, ProcessCreationTime, AccountSid, AccountName, AccountDomain,InitiatingProcessAccountDomain, InitiatingProcessAccountDomain, InitiatingProcessAccountName, InitiatingProcessAccountSid, InitiatingProcessAccountSid, InitiatingProcessAccountUpn, InitiatingProcessAccountObjectId, InitiatingProcessLogonId, InitiatingProcessIntegrityLevel, InitiatingProcessTokenElevation, InitiatingProcessSHA1, InitiatingProcessSHA256, InitiatingProcessMD5, InitiatingProcessFileName, InitiatingProcessFileSize, InitiatingProcessVersionInfoCompanyName, InitiatingProcessVersionInfoProductName, InitiatingProcessVersionInfoProductVersion, InitiatingProcessVersionInfoInternalFileName, InitiatingProcessVersionInfoOriginalFileName, InitiatingProcessVersionInfoFileDescription, InitiatingProcessId, InitiatingProcessCommandLine, InitiatingProcessCreationTime, InitiatingProcessFolderPath, InitiatingProcessAccountDomain, InitiatingProcessAccountName, InitiatingProcessAccountSid\n| limit {}" # noqa: E501 GRANDPARENT_PROCESS_QUERY_SUFFIX = "\n| project Timestamp, DeviceId, DeviceName, ActionType, ProcessId, ProcessCommandLine, ProcessIntegrityLevel, ProcessCreationTime, AccountSid, AccountName, AccountDomain, AccountObjectId, AccountUpn, InitiatingProcessSHA1, InitiatingProcessSHA256, InitiatingProcessMD5, InitiatingProcessFileName, InitiatingProcessId, InitiatingProcessCreationTime, InitiatingProcessFolderPath, InitiatingProcessParentFileName, InitiatingProcessParentId, InitiatingProcessParentCreationTime\n| limit {}" # noqa: E501 PROCESS_DETAILS_QUERY_SUFFIX = "\n| summarize by SHA1,FileName,SHA256,MD5 | join DeviceFileCertificateInfo on SHA1 | summarize by FileName,SHA1,SHA256,IsSigned,Signer,SignatureType,Issuer,CertificateExpirationTime,IsTrusted,IsRootSignerMicrosoft\n| limit {}" # noqa: E501 BEACONING_EVIDENCE_QUERY_SUFFIX = "\n| project Timestamp, DeviceId, DeviceName, ActionType, RemoteIP, RemotePort, RemoteUrl, LocalIP, LocalPort, Protocol, LocalIPType, RemoteIPType, InitiatingProcessSHA1, InitiatingProcessSHA256, InitiatingProcessMD5, InitiatingProcessFileName\n| limit {}" # noqa: E501 POWERSHELL_EXECUTION_PROCESS_QUERY_SUFFIX = "| project Timestamp, FileName, FolderPath, ProcessVersionInfoProductName, ProcessCommandLine, ProcessCreationTime, InitiatingProcessFileName, InitiatingProcessVersionInfoProductName, InitiatingProcessVersionInfoOriginalFileName, InitiatingProcessCommandLine, InitiatingProcessFolderPath, InitiatingProcessSignerType, InitiatingProcessSignatureStatus,DeviceId,DeviceName\n| limit {}" # noqa: E501 POWERSHELL_EXECUTION_PROCESS_UNSIGNED_QUERY_SUFFIX = "\n| summarize by InitiatingProcessFolderPath,InitiatingProcessFileName,InitiatingProcessParentFileName,InitiatingProcessVersionInfoOriginalFileName, InitiatingProcessVersionInfoProductName,InitiatingProcessCommandLine,InitiatingProcessSignerType,InitiatingProcessSignatureStatus" # noqa: E501 def __init__( self, limit: str, query_operation: str, page: str, device_name: str | None = None, file_name: str | None = None, sha1: str | None = None, sha256: str | None = None, md5: str | None = None, device_id: str | None = None, query_purpose: str | None = None, ): if query_purpose == "process_excecution_powershell": if not (file_name or sha1 or sha256 or md5): raise DemistoException(HuntingQueryBuilder.FILE_ARGS_ERR) if not (device_id or device_name): raise DemistoException(HuntingQueryBuilder.DEVICES_ARGS_ERR) elif query_purpose != "powershell_execution_unsigned_files" and not ( device_name or file_name or sha1 or sha256 or md5 or device_id ): raise DemistoException(HuntingQueryBuilder.ANY_ARGS_ERR) self._limit = limit * (int(page)) self._query_operation = query_operation self._device_name = HuntingQueryBuilder.get_filter_values(device_name) self._file_name = HuntingQueryBuilder.get_filter_values(file_name) self._sha1 = HuntingQueryBuilder.get_filter_values(sha1) self._sha256 = HuntingQueryBuilder.get_filter_values(sha256) self._md5 = HuntingQueryBuilder.get_filter_values(md5) self._device_id = HuntingQueryBuilder.get_filter_values(device_id) def build_parent_process_query(self): query_dict = assign_params( FileName=self._file_name, SHA1=self._sha1, SHA256=self._sha256, MD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.GENERIC_PROCESS_DETAILS_QUERY_PREFIX, query_suffix=self.PARENT_PROCESS_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_grandparent_process_query(self): query_dict = assign_params( FileName=self._file_name, SHA1=self._sha1, SHA256=self._sha256, MD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.GENERIC_PROCESS_DETAILS_QUERY_PREFIX, query_suffix=self.GRANDPARENT_PROCESS_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_process_details_query(self): query_dict = assign_params( FileName=self._file_name, SHA1=self._sha1, SHA256=self._sha256, MD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.GENERIC_PROCESS_DETAILS_QUERY_PREFIX, query_suffix=self.PROCESS_DETAILS_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_beaconing_evidence_query(self): query_dict = assign_params( InitiatingProcessFileName=self._file_name, InitiatingProcessSHA1=self._sha1, InitiatingProcessSHA256=self._sha256, InitiatingProcessMD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.BECAONING_QUERY_PREFIX, query_suffix=self.BEACONING_EVIDENCE_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_process_excecution_powershell_query(self): query_dict = assign_params( InitiatingProcessFileName=self._file_name, InitiatingProcessSHA1=self._sha1, InitiatingProcessSHA256=self._sha256, InitiatingProcessMD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.POWERSHELL_EXECUTION_PROCESS_QUERY_PREFIX, query_suffix=self.POWERSHELL_EXECUTION_PROCESS_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_powershell_execution_unsigned_files_query(self): query_dict = assign_params( InitiatingProcessFileName=self._file_name, InitiatingProcessSHA1=self._sha1, InitiatingProcessSHA256=self._sha256, InitiatingProcessMD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = self.POWERSHELL_EXECUTION_PROCESS_UNSIGNED_QUERY_PREFIX if query_dict: query += " and" return HuntingQueryBuilder.build_generic_query( query_prefix=query, query_suffix=self.POWERSHELL_EXECUTION_PROCESS_UNSIGNED_QUERY_SUFFIX, query_dict=query_dict, query_operation=self._query_operation, ) class NetworkConnections: """QUERY PREFIX""" EXTERNAL_ADDRESSES_QUERY_PREFIX = 'DeviceNetworkEvents | where not(RemoteIP matches regex "(^10\\\\.)|(^172\\\\.1[6-9]\\\\.)|(^172\\\\.2[0-9]\\\\.)|(^172\\\\.3[0-1]\\\\.)|(^192\\\\.168\\\\.)") and' # noqa: E501 DNS_QUERY_PREFIX = "DeviceNetworkEvents | where RemotePort == 53 and" ENCODED_COMMANDS_QUERY_PREFIX = 'DeviceProcessEvents | where FileName in ("powershell.exe","powershell_ise.exe") and ProcessCommandLine contains "-encoded" and' # noqa: E501 """QUERY SUFFIX""" EXTERNAL_ADDRESSES_QUERY_SUFFIX = "\n| summarize TotalConnections = count() by DeviceName, RemoteIP, RemotePort, InitiatingProcessFileName,InitiatingProcessFolderPath | order by TotalConnections\n| limit {}" # noqa: E501 DNS_QUERY_SUFFIX = ( "| project Timestamp,DeviceName,ActionType,RemoteIP,Packetinfo = url_decode(AdditionalFields)\n| limit {}" # noqa: E501 ) ENCODED_COMMANDS_QUERY_SUFFIX = "\n| limit {}" def __init__( self, limit: str, query_operation: str, query_purpose: str, page: str, device_name: str | None = None, file_name: str | None = None, sha1: str | None = None, sha256: str | None = None, md5: str | None = None, device_id: str | None = None, ): if query_purpose == "encoded_commands": if not (device_id or device_name): raise DemistoException(HuntingQueryBuilder.DEVICES_ARGS_ERR) else: if not (device_name or file_name or sha1 or sha256 or md5 or device_id): raise DemistoException(HuntingQueryBuilder.ANY_ARGS_ERR) self._limit = limit * (int(page)) self._query_operation = query_operation self._device_name = HuntingQueryBuilder.get_filter_values(device_name) self._file_name = HuntingQueryBuilder.get_filter_values(file_name) self._sha1 = HuntingQueryBuilder.get_filter_values(sha1) self._sha256 = HuntingQueryBuilder.get_filter_values(sha256) self._md5 = HuntingQueryBuilder.get_filter_values(md5) self._device_id = HuntingQueryBuilder.get_filter_values(device_id) def build_external_addresses_query(self): query_dict = assign_params( InitiatingProcessFileName=self._file_name, InitiatingProcessSHA1=self._sha1, InitiatingProcessSHA256=self._sha256, InitiatingProcessMD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.EXTERNAL_ADDRESSES_QUERY_PREFIX, query_suffix=self.EXTERNAL_ADDRESSES_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_dns_query(self): query_dict = assign_params( InitiatingProcessFileName=self._file_name, InitiatingProcessSHA1=self._sha1, InitiatingProcessSHA256=self._sha256, InitiatingProcessMD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.DNS_QUERY_PREFIX, query_suffix=self.DNS_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_encoded_commands_query(self): query_dict = assign_params(DeviceName=self._device_name, DeviceId=self._device_id) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.ENCODED_COMMANDS_QUERY_PREFIX, query_suffix=self.ENCODED_COMMANDS_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query class PrivilegeEscalation: QUERY_PREFIX = "DeviceLogonEvents | where IsLocalAdmin == 1 and" QUERY_SUFFIX = " and AccountDomain == DeviceName | project Timestamp, DeviceId, DeviceName, ActionType, LogonType, AccountDomain, AccountName, IsLocalAdmin, InitiatingProcessFileName\n| limit {}" # noqa: E501 def __init__( self, limit: str, query_operation: str, page: str, device_name: str | None = None, device_id: str | None = None, ): if not (device_name or device_id): raise DemistoException(HuntingQueryBuilder.DEVICES_ARGS_ERR) self._limit = limit * (int(page)) self._query_operation = query_operation self._device_name = HuntingQueryBuilder.get_filter_values(device_name) self._device_id = HuntingQueryBuilder.get_filter_values(device_id) def build_query(self): query_dict = assign_params(DeviceName=self._device_name, DeviceId=self._device_id) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.QUERY_PREFIX, query_suffix=self.QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query class Tampering: QUERY_PREFIX = r"""let includeProc = dynamic(["sc.exe","net1.exe","net.exe", "taskkill.exe", "cmd.exe", "powershell.exe"]); let action = dynamic(["stop","disable", "delete"]); let service1 = dynamic(['sense', 'windefend', 'mssecflt']); let service2 = dynamic(['sense', 'windefend', 'mssecflt', 'healthservice']); let params1 = dynamic(["-DisableRealtimeMonitoring", "-DisableBehaviorMonitoring" ,"-DisableIOAVProtection"]); let params2 = dynamic(["sgrmbroker.exe", "mssense.exe"]); let regparams1 = dynamic(['reg add "HKLM\\SOFTWARE\\Policies\\Microsoft\\Windows Defender"', 'reg add "HKLM\\SOFTWARE\\Policies\\Microsoft\\Windows Advanced Threat Protection"']); let regparams2 = dynamic(['ForceDefenderPassiveMode', 'DisableAntiSpyware']); let regparams3 = dynamic(['sense', 'windefend']); let regparams4 = dynamic(['demand', 'disabled']); let timeframe = 1d; DeviceProcessEvents""" # noqa: E501 QUERY_SUFFIX = "\n| where InitiatingProcessFileName in~ (includeProc) | where (InitiatingProcessCommandLine has_any(action) and InitiatingProcessCommandLine has_any (service2) and InitiatingProcessParentFileName != 'cscript.exe') or (InitiatingProcessCommandLine has_any (params1) and InitiatingProcessCommandLine has 'Set-MpPreference' and InitiatingProcessCommandLine has '$true') or (InitiatingProcessCommandLine has_any (params2) and InitiatingProcessCommandLine has \"/IM\") or (InitiatingProcessCommandLine has_any (regparams1) and InitiatingProcessCommandLine has_any (regparams2) and InitiatingProcessCommandLine has '/d 1') or (InitiatingProcessCommandLine has_any(\"start\") and InitiatingProcessCommandLine has \"config\" and InitiatingProcessCommandLine has_any (regparams3) and InitiatingProcessCommandLine has_any (regparams4))| extend Account = iff(isnotempty(InitiatingProcessAccountUpn), InitiatingProcessAccountUpn, InitiatingProcessAccountName), Computer = DeviceName| project Timestamp, Computer, Account, AccountDomain, ProcessName = InitiatingProcessFileName, ProcessNameFullPath = FolderPath, Activity = ActionType, CommandLine = InitiatingProcessCommandLine, InitiatingProcessParentFileName\n| limit {}" # noqa: E501 def __init__( self, limit: str, query_operation: str, page: str, device_name: str | None = None, device_id: str | None = None, ): self._limit = limit * (int(page)) self._query_operation = query_operation self._device_name = HuntingQueryBuilder.get_filter_values(device_name) self._device_id = HuntingQueryBuilder.get_filter_values(device_id) def build_query(self): query_dict = assign_params(DeviceName=self._device_name, DeviceId=self._device_id) query = HuntingQueryBuilder.build_generic_query( query_prefix=f'{self.QUERY_PREFIX}{"| where" if query_dict else ""}', query_suffix=self.QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query class CoverUp: """ERRORS""" USERNAME_ERROR = 'Please provide the "username" argument.' """QUERY PREFIX""" FILE_DELETED_QUERY_PREFIX = 'DeviceFileEvents | where ActionType == "FileDeleted" and' EVENT_LOG_CLEARED_QUERY_PREFIX = 'DeviceProcessEvents | where (ProcessCommandLine has "WEVTUTIL" and ProcessCommandLine has_any ("CL","clear-log")) or (ProcessCommandLine contains "Clear-EventLog") and' # noqa: E501 ACCOUNT_QUERY_PREFIX = "union Device* | where" """QUERY SUFFIX""" FILE_DELETED_QUERY_SUFFIX = "\n| project Timestamp, DeviceId, DeviceName, FileName, FolderPath, InitiatingProcessFileName, InitiatingProcessVersionInfoProductName, InitiatingProcessCommandLine\n| limit {}" # noqa: E501 EVENT_LOG_CLEARED_QUERY_SUFFIX = "\n| summarize LogClearCount = dcount(ProcessCommandLine), ClearedLogList = make_set(ProcessCommandLine) by DeviceId,DeviceName, bin(Timestamp, 5m),FileName,InitiatingProcessFileName\n| limit {}" # noqa: E501 COMPROMISED_INFORMATION_QUERY_SUFFIX = "\n| project Timestamp, DeviceId, DeviceName, ActionType, FileName, FolderPath, SHA1, SHA256, MD5, InitiatingProcessFileName\n| limit {}" # noqa: E501 CONNECTED_DEVICES_QUERY_SUFFIX = "\n| summarize by DeviceName\n| limit {}" ACTION_TYPES_QUERY_SUFFIX = ( "\n| summarize Number_of_actions=count(ActionType) by ActionType,DeviceName | order by Number_of_actions\n| limit {}" # noqa: E501 ) COMMON_FILES_QUERY_SUFFIX = "\n| summarize Number_of_accoiated_events=count(FileName) by FileName, MD5, SHA1, SHA256 | order by Number_of_accoiated_events\n| limit {}" # noqa: E501 def __init__( self, limit: str, query_operation: str, query_purpose: str, page: str, device_name: str | None = None, file_name: str | None = None, sha1: str | None = None, sha256: str | None = None, md5: str | None = None, device_id: str | None = None, username: str | None = None, ): if query_purpose in ("compromised_information", "connected_devices", "action_types", "common_files"): if not username: raise DemistoException(self.USERNAME_ERROR) elif query_purpose == "event_log_cleared" and not (device_name or device_id): raise DemistoException(HuntingQueryBuilder.DEVICES_ARGS_ERR) elif not (device_name or file_name or sha1 or sha256 or md5 or device_id): raise DemistoException(HuntingQueryBuilder.ANY_ARGS_ERR) self._limit = limit * (int(page)) self._query_operation = query_operation self._device_name = HuntingQueryBuilder.get_filter_values(device_name) self._file_name = HuntingQueryBuilder.get_filter_values(file_name) self._sha1 = HuntingQueryBuilder.get_filter_values(sha1) self._sha256 = HuntingQueryBuilder.get_filter_values(sha256) self._md5 = HuntingQueryBuilder.get_filter_values(md5) self._device_id = HuntingQueryBuilder.get_filter_values(device_id) self._username = HuntingQueryBuilder.get_filter_values(username) def build_file_deleted_query(self): query_dict = assign_params( FileName=self._file_name, SHA1=self._sha1, SHA256=self._sha256, MD5=self._md5, DeviceName=self._device_name, DeviceId=self._device_id, ) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.FILE_DELETED_QUERY_PREFIX, query_suffix=self.FILE_DELETED_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_event_log_cleared_query(self): query_dict = assign_params(DeviceName=self._device_name, DeviceId=self._device_id) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.EVENT_LOG_CLEARED_QUERY_PREFIX, query_suffix=self.EVENT_LOG_CLEARED_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_compromised_information_query(self): query_dict = assign_params(AccountName=self._username) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.ACCOUNT_QUERY_PREFIX, query_suffix=self.COMPROMISED_INFORMATION_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_connected_devices_query(self): query_dict = assign_params(AccountName=self._username) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.ACCOUNT_QUERY_PREFIX, query_suffix=self.CONNECTED_DEVICES_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_action_types_query(self): query_dict = assign_params(AccountName=self._username) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.ACCOUNT_QUERY_PREFIX, query_suffix=self.ACTION_TYPES_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def build_common_files_query(self): query_dict = assign_params(AccountName=self._username) query = HuntingQueryBuilder.build_generic_query( query_prefix=self.ACCOUNT_QUERY_PREFIX, query_suffix=self.COMMON_FILES_QUERY_SUFFIX.format(self._limit), query_dict=query_dict, query_operation=self._query_operation, ) return query def file_standard(observable: dict) -> Common.File: """Gets a file observable and returns a context key Args: observable: APT's file observable Returns: Context standard """ file_obj = Common.File( Common.DBotScore.NONE, name=observable.get("fileName"), size=observable.get("fileSize"), path=observable.get("filePath") ) hash_type = observable.get("fileHashType", "").lower() if hash_type and hash_type in INDICATOR_TYPE_TO_CONTEXT_KEY: hash_value = observable.get("fileHashValue") if hash_type == "md5": file_obj.md5 = hash_value elif hash_type == "sha256": file_obj.sha256 = hash_value elif hash_type == "sha1": file_obj.sha1 = hash_value return file_obj def network_standard(observable: dict) -> Common.Domain | Common.IP | Common.URL | None: """Gets a network observable and returns a context key Args: observable: APT's network observable Returns: Context standard or None of not supported """ domain_name = observable.get("domainName") url = observable.get("url") ip = observable.get("networkIPv4", observable.get("networkIPv6")) if domain_name: return Common.Domain(domain_name, Common.DBotScore.NONE) elif ip: return Common.IP(ip, Common.DBotScore(ip, DBotScoreType.IP, "Microsoft Defender Advanced Threat Protection", 0)) elif url: return Common.URL(url, Common.DBotScore.NONE) return None def standard_output(observable: dict) -> Common.Domain | Common.IP | Common.URL | Common.File | None: """Gets an observable and returns a context standard object. Args: observable: File or network observable from API. Links: File observable: https://docs.microsoft.com/en-us/graph/api/resources/tiindicator?view=graph-rest-beta#indicator-observables---file Network observable: https://docs.microsoft.com/en-us/graph/api/resources/tiindicator?view=graph-rest-beta#indicator-observables---network Returns: File, IP, URL or Domain object. If observable is not supported, will return None. """ # noqa: E501 file_keys = {"fileHashType", "fileHashValue", "fileName", "filePath", "fileSize", "fileType"} # Must be file key if any(key in observable for key in file_keys): return file_standard(observable) # Else it's a network return network_standard(observable) def build_std_output(indicators: dict | list) -> dict: """ Args: indicators: Network or File observable Returns: Dict of standard outputs. """ if isinstance(indicators, dict): indicators = [indicators] outputs = {} for indicator in indicators: output = standard_output(indicator) if output: for key, value in output.to_context().items(): if key not in outputs: outputs[key] = [value] else: outputs[key].append(value) return outputs def get_future_time(expiration_time: str) -> str: """Gets a time and returns a string of the future time of it. Args: expiration_time: (3 days, 1 hour etc) Returns: time now + the expiration time Examples: time now: 20:00 function get expiration_time=1 hour returns: 21:00 (format '%Y-%m-%dT%H:%M:%SZ') """ start, end = parse_date_range(expiration_time) future_time: datetime = end + (end - start) return future_time.strftime("%Y-%m-%dT%H:%M:%SZ") def alert_to_incident(alert, alert_creation_time): incident = { "rawJSON": json.dumps(alert), "name": "Microsoft Defender ATP Alert " + alert["id"], "occurred": alert_creation_time.isoformat() + "Z", } return incident class MsClient: """ Microsoft Client enables authorized access to Microsoft Defender Advanced Threat Protection (ATP) """ def __init__( self, tenant_id, auth_id, enc_key, app_name, base_url, verify, proxy, self_deployed, alert_severities_to_fetch, alert_status_to_fetch, alert_time_to_fetch, max_fetch, auth_type, endpoint_type, redirect_uri, auth_code, certificate_thumbprint: str | None = None, private_key: str | None = None, managed_identities_client_id: str | None = None, alert_detectionsource_to_fetch: str | None = None, ): self.endpoint_type = endpoint_type if auth_type == "Authorization Code": token_retrieval_url = urljoin( MICROSOFT_DEFENDER_FOR_ENDPOINT_TOKEN_RETRIVAL_ENDPOINTS.get(endpoint_type), "/organizations/oauth2/v2.0/token" ) grant_type = AUTHORIZATION_CODE else: token_retrieval_url = None grant_type = None client_args = assign_params( self_deployed=self_deployed, auth_id=auth_id, endpoint=endpoint_type, token_retrieval_url=token_retrieval_url, grant_type=grant_type, base_url=base_url, verify=verify, proxy=proxy, scope=get_defender_scope(self.endpoint_type), ok_codes=(200, 201, 202, 204), redirect_uri=redirect_uri, auth_code=auth_code, tenant_id=tenant_id, app_name=app_name, enc_key=enc_key, certificate_thumbprint=certificate_thumbprint, private_key=private_key, retry_on_rate_limit=True, managed_identities_client_id=managed_identities_client_id, managed_identities_resource_uri=MICROSOFT_DEFENDER_FOR_ENDPOINT_API[self.endpoint_type], command_prefix="microsoft-atp", ) self.ms_client = MicrosoftClient(**client_args) self.alert_detectionsource_to_fetch = alert_detectionsource_to_fetch self.alert_severities_to_fetch = alert_severities_to_fetch self.alert_status_to_fetch = alert_status_to_fetch self.alert_time_to_fetch = alert_time_to_fetch self.max_alerts_to_fetch = max_fetch def indicators_http_request(self, *args, **kwargs): """Wraps the ms_client.http_request with scope=Scopes.graph should_use_security_center (bool): whether to use the security center's scope and resource """ if kwargs.pop("should_use_security_center", None): kwargs["scope"] = get_defender_scope(self.endpoint_type) kwargs["resource"] = MICROSOFT_DEFENDER_FOR_ENDPOINT_API[self.endpoint_type] else: kwargs["scope"] = self.get_graph_scope() return self.ms_client.http_request(*args, **kwargs) def get_graph_scope(self): return ( "graph" if self.ms_client.auth_type == OPROXY_AUTH_TYPE else urljoin(MICROSOFT_DEFENDER_FOR_ENDPOINT_GRAPH_ENDPOINTS[self.endpoint_type], "/.default") ) def get_graph_indicator_endpoint(self): return urljoin(MICROSOFT_DEFENDER_FOR_ENDPOINT_GRAPH_ENDPOINTS[self.endpoint_type], "/beta/security/tiIndicators") def get_security_center_indicator_endpoint(self): return urljoin(MICROSOFT_DEFENDER_FOR_ENDPOINT_API[self.endpoint_type], "/api/indicators") def get_security_center_indicator_endpoint_batch(self): return urljoin(MICROSOFT_DEFENDER_FOR_ENDPOINT_API[self.endpoint_type], "/api/indicators/import") def offboard_machine(self, machine_id, comment): """Offboard machine from defender. Args: machine_id (str): Machine ID comment (str): Comment to associate with the """ cmd_url = f"/machines/{machine_id}/offboard" json_data = {"Comment": comment} response = self.ms_client.http_request(method="POST", url_suffix=cmd_url, json_data=json_data) return response def isolate_machine(self, machine_id, comment, isolation_type): """Isolates a machine from accessing external network. Args: machine_id (str): Machine ID comment (str): Comment to associate with the action. isolation_type (str): Type of the isolation. Notes: Machine action is a collection of actions you can apply on the machine, for more info https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/machineaction Returns: dict. Machine action """ cmd_url = f"/machines/{machine_id}/isolate" json_data = {"Comment": comment, "IsolationType": isolation_type} response = self.ms_client.http_request(method="POST", url_suffix=cmd_url, json_data=json_data) return response def unisolate_machine(self, machine_id, comment): """Undo isolation of a machine. Args: machine_id (str): Machine ID comment (str): Comment to associate with the action. Notes: Machine action is a collection of actions you can apply on the machine, for more info https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/machineaction Returns: dict. Machine action """ cmd_url = f"/machines/{machine_id}/unisolate" json_data = {"Comment": comment} return self.ms_client.http_request(method="POST", url_suffix=cmd_url, json_data=json_data) def get_machines(self, filter_req, page_size="", page_num=""): """Retrieves a collection of Machines that have communicated with Microsoft Defender ATP cloud on the last 30 days. Returns: dict. Machine's info """ cmd_url = "/machines" params = {"$filter": filter_req} if filter_req else {} if page_size and page_num: page_size = arg_to_number(page_size) page_size = min(page_size, 10000) page_num = arg_to_number(page_num) page_num = 0 if not page_num else (page_num - 1) skip = page_num * page_size params["$skip"] = str(skip) params["$top"] = str(page_size) return self.ms_client.http_request(method="GET", url_suffix=cmd_url, params=params) def get_machines_for_get_machine_by_ip_command(self, filter_req): """ Args: filter_req string: a query request to use to filter machines, for example: "(ip='8.8.8.8',timestamp=2024-05-19T01:00:05Z)". Link to documentation: https://learn.microsoft.com/en-us/defender-endpoint/api/find-machines-by-ip?view=o365-worldwide Returns: dict: Machines info """ demisto.debug(f"current request is: api/machines/findbyip{filter_req}") cmd_url = "machines/findbyip" + filter_req return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_file_related_machines(self, file): """Retrieves a collection of Machines related to a given file hash. Args: file (str): File's hash Returns: dict. Related machines """ cmd_url = f"/files/{file}/machines" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_machine_details(self, machine_id): """Retrieves specific Machine by its machine ID. Args: machine_id (str): Machine ID Returns: dict. Machine's info """ cmd_url = f"/machines/{machine_id}" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_list_machines_by_vulnerability(self, cve_id): """Retrieves a list of devices affected by a vulnerability. https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-machines-by-vulnerability?view=o365-worldwide#http-request Args: cve_id (str): Vulnerability ID Returns: dict. Machine's info """ cmd_url = f"/vulnerabilities/{cve_id}/machineReferences" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def run_antivirus_scan(self, machine_id, comment, scan_type): """Initiate Windows Defender Antivirus scan on a machine. Args: machine_id (str): Machine ID comment (str): Comment to associate with the action scan_type (str): Defines the type of the Scan (Quick, Full) Notes: Machine action is a collection of actions you can apply on the machine, for more info https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/machineaction Returns: dict. Machine action """ cmd_url = f"/machines/{machine_id}/runAntiVirusScan" json_data = {"Comment": comment, "ScanType": scan_type} return self.ms_client.http_request(method="POST", url_suffix=cmd_url, json_data=json_data) def list_alerts_by_params(self, filter_req=None, params=None, overwrite_rate_limit_retry=False): """Retrieves a collection of Alerts. overwrite_rate_limit_retry - Skip retry mechanism, True for fetch incidents Returns: dict. Alerts info """ cmd_url = "/alerts" if not params: params = {"$filter": filter_req} if filter_req else None return self.ms_client.http_request( method="GET", url_suffix=cmd_url, params=params, overwrite_rate_limit_retry=overwrite_rate_limit_retry ) def list_alerts(self, filter_req=None, limit=None, evidence=False, creation_time=None): """Retrieves a collection of Alerts. Returns: dict. Alerts info """ cmd_url = "/alerts" params = {} if evidence: params["$expand"] = "evidence" if filter_req: if creation_time: filter_req += f"and {create_filter_alerts_creation_time(creation_time)}" params["$filter"] = filter_req if limit: params["$top"] = limit return self.ms_client.http_request(method="GET", url_suffix=cmd_url, params=params) def update_alert(self, alert_id, json_data): """Updates properties of existing Alert. Returns: dict. Alerts info """ cmd_url = f"/alerts/{alert_id}" return self.ms_client.http_request(method="PATCH", url_suffix=cmd_url, json_data=json_data) def get_advanced_hunting(self, query: str, timeout: int, time_range: str | None = None) -> dict[str, Any]: """Retrieves results according to query. Args: query (str): Query to do advanced hunting on timeout (int): Connection timeout time_range (Optional[int]): Time range in minutes given in timespan format Returns: dict. Advanced hunting results """ cmd_url = "/advancedqueries/run" if time_range: query = HuntingQueryBuilder.rebuild_query_with_time_range(query, time_range) json_data = {"Query": query} return self.ms_client.http_request(method="POST", url_suffix=cmd_url, json_data=json_data, timeout=timeout) def create_alert(self, machine_id, severity, title, description, event_time, report_id, rec_action, category): """Creates new Alert on top of Event. Args: machine_id (str): ID of the machine on which the event was identified severity (str): Severity of the alert title (str): Title for the alert description (str): Description of the alert event_time (str): The precise time of the event as string report_id (str): The reportId of the event rec_action (str): Action that is recommended to be taken by security officer when analyzing the alert category (Str): Category of the alert Returns: dict. Related domains """ cmd_url = "/alerts/CreateAlertByReference" json_data = { "machineId": machine_id, "severity": severity, "title": title, "description": description, "eventTime": event_time, "reportId": report_id, "recommendedAction": rec_action, "category": category, } return self.ms_client.http_request(method="POST", url_suffix=cmd_url, json_data=json_data) def get_alert_related_domains(self, alert_id): """Retrieves all domains related to a specific alert. Args: alert_id (str): Alert ID Returns: dict. Related domains """ cmd_url = f"/alerts/{alert_id}/domains" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_alert_related_files(self, alert_id): """Retrieves all files related to a specific alert. Args: alert_id (str): Alert ID Returns: dict. Related files """ cmd_url = f"/alerts/{alert_id}/files" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_alert_related_ips(self, alert_id): """Retrieves all IPs related to a specific alert. Args: alert_id (str): Alert ID Returns: dict. Related IPs """ cmd_url = f"/alerts/{alert_id}/ips" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_alert_related_user(self, alert_id): """Retrieves the User related to a specific alert. Args: alert_id (str): Alert ID Returns: dict. Related user """ cmd_url = f"/alerts/{alert_id}/user" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_machine_action_by_id(self, action_id, overwrite_rate_limit_retry=False): """Retrieves specific Machine Action by its ID. Args: action_id (str): Action ID Notes: Machine action is a collection of actions you can apply on the machine, for more info https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/machineaction Returns: dict. Machine Action entity """ cmd_url = f"/machineactions/{action_id}" return self.ms_client.http_request( method="GET", url_suffix=cmd_url, overwrite_rate_limit_retry=overwrite_rate_limit_retry ) def get_machine_actions(self, filter_req, limit): """Retrieves all Machine Actions. Notes: Machine action is a collection of actions you can apply on the machine, for more info https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/machineaction Returns: dict. Machine Action entity """ cmd_url = "/machineactions" params = {"$top": limit} if filter_req: params["$filter"] = filter_req return self.ms_client.http_request(method="GET", url_suffix=cmd_url, params=params) def get_investigation_package(self, machine_id, comment, overwrite_rate_limit_retry=False): """Collect investigation package from a machine. Args: machine_id (str): Machine ID comment (str): Comment to associate with the action Returns: dict. Machine's investigation_package """ cmd_url = f"/machines/{machine_id}/collectInvestigationPackage" json_data = {"Comment": comment} return self.ms_client.http_request( method="POST", url_suffix=cmd_url, json_data=json_data, overwrite_rate_limit_retry=overwrite_rate_limit_retry ) def get_investigation_package_sas_uri(self, action_id, overwrite_rate_limit_retry=False): """Get a URI that allows downloading of an Investigation package. Args: action_id (str): Action ID Returns: dict. An object that holds the link for the package """ cmd_url = f"/machineactions/{action_id}/getPackageUri" return self.ms_client.http_request( method="GET", url_suffix=cmd_url, overwrite_rate_limit_retry=overwrite_rate_limit_retry ) def restrict_app_execution(self, machine_id, comment): """Restrict execution of all applications on the machine except a predefined set. Args: machine_id (str): Machine ID comment (str): Comment to associate with the action Notes: Machine action is a collection of actions you can apply on the machine, for more info https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/machineaction Returns: dict. Machine action """ cmd_url = f"/machines/{machine_id}/restrictCodeExecution" json_data = {"Comment": comment} return self.ms_client.http_request(method="POST", url_suffix=cmd_url, json_data=json_data) def remove_app_restriction(self, machine_id, comment): """Enable execution of any application on the machine. Args: machine_id (str): Machine ID comment (str): Comment to associate with the action Notes: Machine action is a collection of actions you can apply on the machine, for more info https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/machineaction Returns: dict. Machine action """ cmd_url = f"/machines/{machine_id}/unrestrictCodeExecution" json_data = {"Comment": comment} return self.ms_client.http_request("POST", cmd_url, json_data=json_data) def stop_and_quarantine_file(self, machine_id, file_sha1, comment): """Stop execution of a file on a machine and delete it. Args: machine_id (str): Machine ID file_sha1: (str): File's hash comment (str): Comment to associate with the action Notes: Machine action is a collection of actions you can apply on the machine, for more info https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/machineaction Returns: dict. Machine action """ cmd_url = f"/machines/{machine_id}/stopAndQuarantineFile" json_data = {"Comment": comment, "Sha1": file_sha1} return self.ms_client.http_request("POST", cmd_url, json_data=json_data) def get_investigation_by_id(self, investigation_id): """Get the investigation ID and return the investigation details. Args: investigation_id (str): The investigation ID Returns: dict. Investigations entity """ cmd_url = f"/investigations/{investigation_id}" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_alert_by_id(self, alert_id): """Get the alert ID and return the alert details. Args: alert_id (str): The alert ID Returns: dict. Alert's entity """ cmd_url = f"/alerts/{alert_id}" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_investigation_list( self, ): """Retrieves a collection of Investigations. Returns: dict. A collection of Investigations entities. """ cmd_url = "/investigations" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def start_investigation(self, machine_id, comment, timeout): """Start automated investigation on a machine. Args: machine_id (str): The Machine ID comment (str): Comment to associate with the action timeout (int): Connection timeout Returns: dict. Investigation's entity """ cmd_url = f"/machines/{machine_id}/startInvestigation" json_data = { "Comment": comment, } return self.ms_client.http_request(method="POST", url_suffix=cmd_url, json_data=json_data, timeout=timeout) def get_domain_statistics(self, domain): """Retrieves the statistics on the given domain. Args: domain (str): The Domain's address Returns: dict. Domain's statistics """ cmd_url = f"/domains/{domain}/stats" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_file_statistics(self, file_sha1): """Retrieves the statistics on the given file. Args: file_sha1 (str): The file's hash Returns: dict. File's statistics """ cmd_url = f"/files/{file_sha1}/stats" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_ip_statistics(self, ip): """Retrieves the statistics on the given IP. Args: ip (str): The IP address Returns: dict. IP's statistics """ cmd_url = f"/ips/{ip}/stats" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_domain_alerts(self, domain): """Retrieves a collection of Alerts related to a given domain address. Args: domain (str): The Domain's address Returns: dict. Alerts entities """ cmd_url = f"/domains/{domain}/alerts" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_file_alerts(self, file_sha1): """Retrieves a collection of Alerts related to a given file hash. Args: file_sha1 (str): The file's hash Returns: dict. Alerts entities """ cmd_url = f"/files/{file_sha1}/alerts" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_ip_alerts(self, ip): """Retrieves a collection of Alerts related to a given IP. Args: ip (str): The IP address Returns: dict. Alerts entities """ cmd_url = f"/ips/{ip}/alerts" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_user_alerts(self, username): """Retrieves a collection of Alerts related to a given user ID. Args: username (str): The user ID Returns: dict. Alerts entities """ cmd_url = f"/users/{username}/alerts" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_domain_machines(self, domain): """Retrieves a collection of Machines that have communicated to or from a given domain address. Args: domain (str): The Domain's address Returns: dict. Machines entities """ cmd_url = f"/domains/{domain}/machines" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_user_machines(self, username): """Retrieves a collection of machines related to a given user ID. Args: username (str): The user name Returns: dict. Machines entities """ cmd_url = f"/users/{username}/machines" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def add_remove_machine_tag(self, machine_id, action, tag): """Retrieves a collection of machines related to a given user ID. Args: machine_id (str): The machine ID action (str): Add or Remove action tag (str): The tag name Returns: dict. Updated machine's entity """ cmd_url = f"/machines/{machine_id}/tags" new_tags = {"Value": tag, "Action": action} return self.ms_client.http_request(method="POST", url_suffix=cmd_url, json_data=new_tags) def get_file_data(self, file_hash): """Retrieves a File by identifier SHA1 or SHA256. For more details, see the docs: https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-file-information?view=o365-worldwide#http-request Args: file_hash(str): The file hash. Returns: dict. File entities """ cmd_url = f"/files/{file_hash}" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def sc_list_indicators( self, indicator_id: str | None = None, limit: int = 50, skip: int = 0, indicator_title: str | None = None, indicator_value: str | None = None, indicator_type: str | None = None, ) -> list: """Lists indicators. if indicator_id supplied, will get only that indicator. Args: indicator_id: if provided, will get only this specific id. limit: Limit the returned results. skip: The number of indicators that are to be skipped and not included in the result. indicator_title: The title of the indicator to get. indicator_value: The value of the indicator to get. indicator_type: The type of the indicator to get. Returns: List of responses. """ cmd_url = ( urljoin(self.get_security_center_indicator_endpoint(), indicator_id) if indicator_id else self.get_security_center_indicator_endpoint() ) params: dict = {"$top": limit, "$skip": skip} if indicator_title: params.setdefault("$filter", []).append(f"contains(title,'{indicator_title}')") if indicator_value: params.setdefault("$filter", []).append(f"contains(indicatorValue,'{indicator_value}')") if indicator_type: params.setdefault("$filter", []).append(f"indicatorType eq '{indicator_type}'") if params.get("$filter"): params["$filter"] = " and ".join(params["$filter"]) resp = self.indicators_http_request( "GET", full_url=cmd_url, url_suffix=None, params=params, timeout=1000, ok_codes=(200, 204, 206, 404), resp_type="response", should_use_security_center=True, ) # 404 - No indicators found, an empty list. if resp.status_code == 404: return [] resp = resp.json() values_list = resp.get("value", []) # value list appears only when requesting indicators list return [assign_params(**item) for item in values_list] if values_list else [resp] def list_indicators( self, indicator_id: str | None = None, page_size: str = "50", limit: int = 50, should_use_security_center: bool = False ) -> list: """Lists indicators. if indicator_id supplied, will get only that indicator. Args: indicator_id: if provided, will get only this specific id. page_size: specify the page size of the result set. limit: Limit the returned results. should_use_security_center: whether to use the security center's scope and resource. Returns: List of responses. """ results = {} cmd_url = ( urljoin(self.get_graph_indicator_endpoint(), indicator_id) if indicator_id else self.get_graph_indicator_endpoint() ) # For getting one indicator # TODO: check in the future if the filter is working. Then remove the filter function. # params = {'$filter': 'targetProduct=\'Microsoft Defender ATP\''} params = {"$top": page_size} resp = self.indicators_http_request( "GET", full_url=cmd_url, url_suffix=None, params=params, timeout=1000, ok_codes=(200, 204, 206, 404), resp_type="response", should_use_security_center=should_use_security_center, ) # 404 - No indicators found, an empty list. if resp.status_code == 404: return [] resp = resp.json() results.update(resp) while next_link := resp.get("@odata.nextLink"): resp = self.indicators_http_request( "GET", full_url=next_link, url_suffix=None, timeout=1000, should_use_security_center=should_use_security_center ) results["value"].extend(resp.get("value")) if len(results["value"]) >= limit: break # If 'value' is in the response, should filter and limit. The '@odata.context' key is in the root which we're # not returning if "value" in results: results["value"] = list( filter(lambda item: item.get("targetProduct") == "Microsoft Defender ATP", results.get("value", [])) ) results = results["value"] # If a single object - should remove the '@odata.context' key. elif not isinstance(results, list): results.pop("@odata.context") results = [results] # type: ignore return [assign_params(values_to_ignore=[None], **item) for item in results] def create_indicator(self, body: dict) -> dict: """Creates indicator from the given body. Args: body: Body represents an indicator. Returns: A response from the API. """ resp = self.indicators_http_request( "POST", full_url=self.get_graph_indicator_endpoint(), json_data=body, url_suffix=None, should_use_security_center=False, ) # A single object - should remove the '@odata.context' key. resp.pop("@odata.context") return assign_params(values_to_ignore=[None], **resp) def create_update_indicator_security_center_api( self, indicator_value: str, indicator_type: str, action: str, indicator_title: str, description: str, expiration_date_time: str | None = None, severity: str | None = None, indicator_application: str | None = None, recommended_actions: str | None = None, rbac_group_names: list | None = None, generate_alert: bool | None = True, ) -> dict: """creates or updates (if already exists) a given indicator Args: indicator_value: Value of the indicator to update. expiration_date_time: Expiration time of the indicator. description: A Brief description of the indicator. severity: The severity of the indicator. indicator_type: The type of the indicator. action: The action that will be taken if the indicator will be discovered. indicator_title: Indicator alert title. indicator_application: The application associated with the indicator. recommended_actions: TI indicator alert recommended actions. rbac_group_names: Comma-separated list of RBAC group names the indicator would be. generate_alert: Whether to generate an alert for the indicator. Returns: A response from the API. """ body = { # required params "indicatorValue": indicator_value, "indicatorType": indicator_type, "action": action, "title": indicator_title, "description": description, "generateAlert": generate_alert, } body.update( assign_params( # optional params severity=severity, application=indicator_application, expirationTime=expiration_date_time, recommendedActions=recommended_actions, rbacGroupNames=rbac_group_names, ) ) resp = self.indicators_http_request( "POST", full_url=self.get_security_center_indicator_endpoint(), json_data=body, url_suffix=None, should_use_security_center=True, ) return assign_params(values_to_ignore=[None], **resp) def create_update_indicator_batch_security_center_api(self, body): """ https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/import-ti-indicators?view=o365-worldwide """ resp = self.indicators_http_request( "POST", full_url=self.get_security_center_indicator_endpoint_batch(), json_data=body, url_suffix=None, should_use_security_center=True, ) return resp def update_indicator( self, indicator_id: str, expiration_date_time: str, description: str | None, severity: int | None ) -> dict: """Updates a given indicator Args: indicator_id: ID of the indicator to update. expiration_date_time: Expiration time of the indicator. description: A Brief description of the indicator. severity: The severity of the indicator. Returns: A response from the API. """ cmd_url = urljoin(self.get_graph_indicator_endpoint(), indicator_id) header = {"Prefer": "return=representation"} body = {"targetProduct": "Microsoft Defender ATP", "expirationDateTime": expiration_date_time} body.update(assign_params(description=description, severity=severity)) resp = self.indicators_http_request( "PATCH", full_url=cmd_url, json_data=body, url_suffix=None, headers=header, should_use_security_center=False ) # A single object - should remove the '@odata.context' key. resp.pop("@odata.context") return assign_params(values_to_ignore=[None], **resp) def delete_indicator(self, indicator_id: str, indicators_endpoint: str, use_security_center: bool = False) -> Response: """Deletes a given indicator Args: indicator_id: ID of the indicator to delete. indicators_endpoint: The indicator endpoint to use. use_security_center: whether to use the security center's scope and resource. Returns: A response from the API. """ cmd_url = urljoin(indicators_endpoint, indicator_id) return self.indicators_http_request( "DELETE", None, full_url=cmd_url, resp_type="response", should_use_security_center=use_security_center ) def get_live_response_result(self, machine_action_id, command_index=0, overwrite_rate_limit_retry=False): cmd_url = f"machineactions/{machine_action_id}/GetLiveResponseResultDownloadLink(index={command_index})" response = self.ms_client.http_request( method="GET", url_suffix=cmd_url, overwrite_rate_limit_retry=overwrite_rate_limit_retry ) return response def create_action(self, machine_id, request_body, overwrite_rate_limit_retry=False): cmd_url = f"machines/{machine_id}/runliveresponse" response = self.ms_client.http_request( method="POST", url_suffix=cmd_url, json_data=request_body, overwrite_rate_limit_retry=overwrite_rate_limit_retry ) return response def download_file(self, url_link): try: response = requests.get(url=url_link, verify=self.ms_client.verify, timeout=300) except Exception as e: raise Exception(f"Could not download file. {url_link=}. error: {e!s}") return response def cancel_action(self, action_id, request_body): cmd_url = f"machineactions/{action_id}/cancel" response = self.ms_client.http_request(method="POST", url_suffix=cmd_url, json_data=request_body) return response def get_machine_users(self, machine_id): """Retrieves a collection of users related to a given machine ID (logon users). https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-machine-log-on-users?view=o365-worldwide Args: machine_id (str): The machine ID Returns: dict. User entities """ cmd_url = f"/machines/{machine_id}/logonusers" try: response = self.ms_client.http_request(method="GET", url_suffix=cmd_url) except Exception: raise Exception(f"Machine {machine_id} was not found") return response def get_machine_alerts(self, machine_id): """Retrieves a collection of alerts related to a given machine ID. https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-machine-related-alerts?view=o365-worldwide Args: machine_id (str): The machine ID Returns: dict. Alert entities """ cmd_url = f"/machines/{machine_id}/alerts" try: response = self.ms_client.http_request(method="GET", url_suffix=cmd_url) except Exception: raise Exception(f"Machine {machine_id} not found") return response def get_list_machines_by_software(self, software_id: str) -> dict: """Retrieve a list of device references that has this software installed. Args: software_id (str): Software ID. Returns: dict: Machines list. """ cmd_url = f"/Software/{software_id}/machineReferences" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_list_software_version_distribution(self, software_id: str) -> dict: """Retrieves a list of your organization's software version distribution. Args: software_id (str): Software ID. Returns: dict: Version distribution list. """ cmd_url = f"/Software/{software_id}/distributions" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_list_missing_kb_by_software(self, software_id: str) -> dict: """Retrieves missing KBs (security updates) by software ID. Args: software_id (str): Software ID. Returns: dict: Missing kb by software list. """ cmd_url = f"/Software/{software_id}/getmissingkbs" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_list_vulnerabilities_by_software(self, software_id: str) -> dict: """Retrieve a list of vulnerabilities in the installed software. Args: software_id (str): Software ID. Returns: dict: list vulnerabilities by software. """ cmd_url = f"/Software/{software_id}/vulnerabilities" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_list_software(self, filter_req: str, limit: str, offset: str) -> dict: """Retrieves the organization software inventory. Returns: dict. software inventory. """ cmd_url = "/Software" params = {"$top": limit, "$skip": offset} if filter_req: params["$filter"] = filter_req return self.ms_client.http_request(method="GET", url_suffix=cmd_url, params=params) def get_missing_kbs_by_machine_id(self, machine_id: str) -> dict: """Retrieves a list of missing security updates (KBs) by machine id. https://learn.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-missing-kbs-machine?view=o365-worldwide Args: machine_id (str): Machine ID Returns: dict. Machine's info """ cmd_url = f"/machines/{machine_id}/getmissingkbs" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_software_by_machine_id(self, machine_id: str) -> dict: """Retrieve a list of the installed software from the defined machine_id . Args: machine_id (str): Machine ID. Returns: dict: machine specific software inventory. """ cmd_url = f"/machines/{machine_id}/software" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_list_vulnerabilities_by_machine(self, filter_req: str, limit: str, offset: str) -> dict: """Retrieves a list of all the vulnerabilities affecting the organization per machine. Returns: dict: list of all the vulnerabilities affecting the organization per machine. """ cmd_url = "/vulnerabilities/machinesVulnerabilities" params = {"$top": limit, "$skip": offset} if filter_req: params["$filter"] = filter_req return self.ms_client.http_request(method="GET", url_suffix=cmd_url, params=params) def get_vulnerabilities_by_machine_id(self, machine_id: str) -> dict: """Retrieves a list of vulnerabilities affected by a machine id. https://learn.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-discovered-vulnerabilities?view=o365-worldwide Args: machine_id (str): Machine ID Returns: dict. Machine's info """ cmd_url = f"/machines/{machine_id}/vulnerabilities" return self.ms_client.http_request(method="GET", url_suffix=cmd_url) def get_list_vulnerabilities(self, filter_req: str, limit: str, offset: str) -> dict: """Retrieves a list of all vulnerabilities. Returns: dict: list of all the vulnerabilities. """ cmd_url = "/vulnerabilities" params = {"$top": limit, "$skip": offset} if filter_req: params["$filter"] = filter_req return self.ms_client.http_request(method="GET", url_suffix=cmd_url, params=params) def get_decoded_token(self) -> dict: """Retrieves the decoded JWT that contains auth information (including permissions). Returns: dict: Decoded JWT information. """ access_token = self.ms_client.get_access_token() # Verifying signature is not needed here since there is no integration logic that depends on the access permissions return jwt.decode(access_token, options={"verify_signature": False}) """ Commands """ def get_alert_related_user_command(client: MsClient, args: dict): """Retrieves the User related to a specific alert. Returns: (str, dict, dict). Human readable, context, raw response """ alert_id = args.get("id") response = client.get_alert_related_user(alert_id) user_data = get_user_data(response) context_output = {"AlertID": alert_id, "User": user_data} ec = {"MicrosoftATP.AlertUser(val.AlertID === obj.AlertID)": context_output} hr = tableToMarkdown("Alert Related User:", user_data, removeNull=True) return hr, ec, response def get_user_data(user_response): """Get the user raw response and returns the user info in context and human readable format Returns: dict. User data """ user_data = { "ID": user_response.get("id"), "AccountName": user_response.get("accountName"), "AccountDomain": user_response.get("accountDomain"), "AccountSID": user_response.get("accountSid"), "FirstSeen": user_response.get("firstSeen"), "LastSeen": user_response.get("lastSeen"), "MostPrevalentMachineID": user_response.get("mostPrevalentMachineId"), "LeastPrevalentMachineID": user_response.get("leastPrevalentMachineId"), "LogonTypes": user_response.get("logonTypes"), "LogonCount": user_response.get("logOnMachinesCount"), "DomainAdmin": user_response.get("isDomainAdmin"), "NetworkUser": user_response.get("isOnlyNetworkUser"), } return user_data def offboard_machine_command(client: MsClient, args: dict): """Offboard machine from defender. Returns: CommandResults. Human readable, context, raw response """ if not args.get("machine_id") or not args.get("comment"): raise ValueError("Not all mandatory arguments are provided. Provide both machine_id and comment.") headers = ["ID", "Type", "Requestor", "RequestorComment", "Status", "MachineID", "ComputerDNSName"] machine_ids = remove_duplicates_from_list_arg(args, "machine_id") comment = args.get("comment") machines_action_data = [] raw_response = [] failed_machines = {} # if we got an error, we will return the machine ids that failed for machine_id in machine_ids: try: machine_action_response = client.offboard_machine(machine_id, comment) raw_response.append(machine_action_response) machines_action_data.append(get_machine_action_data(machine_action_response)) except Exception as e: # if we got an error for a machine, we want to get result for the other ones failed_machines[machine_id] = e continue human_readable = tableToMarkdown( "The offboard request has been submitted successfully:", machines_action_data, headers=headers, removeNull=True ) human_readable += add_error_message(failed_machines, machine_ids) return CommandResults( outputs=machines_action_data, outputs_prefix="MicrosoftATP.OffboardMachine", outputs_key_field=["ID", "MachineID"], readable_output=human_readable, raw_response=raw_response, ) def isolate_machine_command(client: MsClient, args: dict): """Isolates a machine from accessing external network. Returns: (str, dict, dict). Human readable, context, raw response """ headers = ["ID", "Type", "Requestor", "RequestorComment", "Status", "MachineID", "ComputerDNSName"] machine_ids = remove_duplicates_from_list_arg(args, "machine_id") comment = args.get("comment") isolation_type = args.get("isolation_type") machines_action_data = [] raw_response = [] failed_machines = {} # if we got an error, we will return the machine ids that failed for machine_id in machine_ids: try: machine_action_response = client.isolate_machine(machine_id, comment, isolation_type) raw_response.append(machine_action_response) machines_action_data.append(get_machine_action_data(machine_action_response)) except Exception as e: # if we got an error for a machine, we want to get result for the other ones failed_machines[machine_id] = e continue entry_context = {"MicrosoftATP.MachineAction(val.ID === obj.ID)": machines_action_data} human_readable = tableToMarkdown( "The isolation request has been submitted successfully:", machines_action_data, headers=headers, removeNull=True ) human_readable += add_error_message(failed_machines, machine_ids) return human_readable, entry_context, raw_response def unisolate_machine_command(client: MsClient, args: dict): """Undo isolation of a machine. Returns: (str, dict, dict). Human readable, context, raw response """ headers = ["ID", "Type", "Requestor", "RequestorComment", "Status", "MachineID", "ComputerDNSName"] machine_ids = remove_duplicates_from_list_arg(args, "machine_id") comment = args.get("comment") machines_action_data = [] raw_response = [] failed_machines = {} # if we got an error, we will return the machine ids that failed for machine_id in machine_ids: try: machine_action_response = client.unisolate_machine(machine_id, comment) raw_response.append(machine_action_response) machines_action_data.append(get_machine_action_data(machine_action_response)) except Exception as e: # if we got an error for a machine, we want to get result for the other ones failed_machines[machine_id] = e continue entry_context = {"MicrosoftATP.MachineAction(val.ID === obj.ID)": machines_action_data} human_readable = tableToMarkdown( "The request to stop the isolation has been submitted successfully.", machines_action_data, headers=headers, removeNull=True, ) human_readable += add_error_message(failed_machines, machine_ids) return human_readable, entry_context, raw_response def add_error_message(failed_devices, all_requested_devices): human_readable = "" if failed_devices: if len(all_requested_devices) == len(failed_devices): raise DemistoException(f"{INTEGRATION_NAME} The command was failed with the errors: {failed_devices}") human_readable = "Note: you don't see the following IDs in the results as the request was failed for them. \n" for device_id in failed_devices: human_readable += f"ID {device_id} failed with the error: {failed_devices[device_id]} \n" return human_readable def not_found_message(not_found_devices): human_readable = "" if not_found_devices: human_readable = f"\n You don't see the following IDs in the results as they were not found: {not_found_devices}." return human_readable def get_machines_command(client: MsClient, args: dict): """Retrieves a collection of machines that have communicated with WDATP cloud on the last 30 days New: now the hostname and ip args can be from type list, but only one can be given as a list (not both). Returns: (str, dict, dict). Human readable, context, raw response """ headers = [ "ID", "ComputerDNSName", "OSPlatform", "LastIPAddress", "LastExternalIPAddress", "HealthStatus", "RiskScore", "ExposureLevel", ] hostname = remove_duplicates_from_list_arg(args, "hostname") ip = remove_duplicates_from_list_arg(args, "ip") risk_score = args.get("risk_score", "") health_status = args.get("health_status", "") os_platform = args.get("os_platform", "") page_num = args.get("page_num", "") page_size = args.get("page_size", "") more_than_one_hostname = len(hostname) > 1 more_than_one_ip = len(ip) > 1 if more_than_one_hostname and more_than_one_ip: raise DemistoException("Error: only hostname or ip can be an array, not both.") if more_than_one_hostname: ip = "" if not ip else ip[0] field_with_multiple_values = "computerDnsName" elif more_than_one_ip: hostname = "" if not hostname else hostname[0] field_with_multiple_values = "lastIpAddress" else: # both hostname and ip are not lists (each one is empty or includes only one value) field_with_multiple_values = "" ip = "" if not ip else ip[0] hostname = "" if not hostname else hostname[0] fields_to_filter_by = { "computerDnsName": hostname, "lastIpAddress": ip, "riskScore": risk_score, "healthStatus": health_status, "osPlatform": os_platform, } if field_with_multiple_values: filter_req = reformat_filter_with_list_arg(fields_to_filter_by, field_with_multiple_values) else: filter_req = reformat_filter(fields_to_filter_by) machines_response = client.get_machines(filter_req, page_num=page_num, page_size=page_size) machines_list = get_machines_list(machines_response) entry_context = {"MicrosoftATP.Machine(val.ID === obj.ID)": machines_list} human_readable = tableToMarkdown(f"{INTEGRATION_NAME} Machines:", machines_list, headers=headers, removeNull=True) return human_readable, entry_context, machines_response def get_machines_list(machines_response): """Get a raw response of machines list Args: machines_response (dict): The raw response with the machines list in it Returns: list. Machines list """ machines_list = [] for machine in machines_response["value"]: machine_data = get_machine_data(machine) machines_list.append(machine_data) return machines_list def get_machine_softwares_list(machine_softwares_response): """Get a raw response of machines softwares Args: Machine_softwares_response (dict): The raw response with the machines software list in it Returns: list. Machines list """ machine_softwares_list = [] for machine_software in machine_softwares_response["value"]: machine_software_data = get_machine_software_data(machine_software) machine_softwares_list.append(machine_software_data) return machine_softwares_list def get_machine_missing_kbs_list(missing_kbs_response): """Get a raw response of a machine's missing kbs Args: missing_kbs_response (dict): The raw response with the machines missing kbs list in it Returns: list. Machines list """ missing_kbs_list = [] for kb in missing_kbs_response["value"]: missing_kb_data = get_machine_missing_kb_data(kb) missing_kbs_list.append(missing_kb_data) return missing_kbs_list def get_machine_vulnerabilities_list(vulnerabilities_response): """Get a raw response of machine vulnerabilities Args: missing_kbs_response (dict): The raw response with the machines vulnerability list in it Returns: list. Machines list """ vulnerabilities_list = [] for vuln in vulnerabilities_response["value"]: missing_kb_data = get_machine_vulnerability_data(vuln) vulnerabilities_list.append(missing_kb_data) return vulnerabilities_list def get_machine_mac_address(machine): """ return the machine MAC address where “ipAddresses[].ipAddress” = “lastIpAddress” """ ip_addresses = machine.get("ipAddresses", []) last_ip_address = machine.get("lastIpAddress", "") for ip_object in ip_addresses: if last_ip_address and ip_object.get("ipAddress") == last_ip_address: return ip_object.get("macAddress", "") return None def reformat_filter(fields_to_filter_by): """Get a dictionary with all of the fields to filter Args: fields_to_filter_by (dict): Dictionary with all the fields to filter Returns: string. Filter to send in the API request """ filter_req = " and ".join( f"{field_key} eq '{field_value}'" for field_key, field_value in fields_to_filter_by.items() if field_value ) return filter_req def reformat_filter_with_list_arg(fields_to_filter_by, field_key_from_type_list): """Get a dictionary with all of the fields to filter when one field is a list and create a DNF query. Args: fields_to_filter_by (dict): Dictionary with all the fields to filter field_key_from_type_list (str): The arg field name from type list Returns: string. Filter to send in the API request For example, when we get: fields_to_filter_by: { 'status': 'Succeeded', 'machineId': [100,200] , 'type': 'RunAntiVirusScan', 'requestor': '' } and field_key_from_type_list: 'machineId' we build a query looks like: " (machineId eq 100 and status eq Succeeded and type eq RunAntiVirusScan and requestor eq '') or (machineId eq 200 and status eq Succeeded and type eq RunAntiVirusScan and requestor eq '') " note: we have "or" operator between each clause in order to create a DNF query. """ field_value_from_type_list = fields_to_filter_by.get(field_key_from_type_list) if not field_value_from_type_list: fields_to_filter_by[field_key_from_type_list] = "" return reformat_filter(fields_to_filter_by) elif len(field_value_from_type_list) == 1: # in case the list is empty or includes only one item fields_to_filter_by[field_key_from_type_list] = field_value_from_type_list[0] return reformat_filter(fields_to_filter_by) filter_conditions = [] for item in field_value_from_type_list: current_fields_to_filter = {key: value for (key, value) in fields_to_filter_by.items() if key != field_key_from_type_list} current_fields_to_filter.update({field_key_from_type_list: item}) filter_conditions.append(reformat_filter(current_fields_to_filter)) return " or ".join(f"({condition})" for condition in filter_conditions) def get_file_related_machines_command(client: MsClient, args: dict) -> CommandResults: """Retrieves a collection of Machines related to a given file hash. Returns: CommandResults. Human readable, context, raw response """ headers = [ "ID", "ComputerDNSName", "OSPlatform", "LastIPAddress", "LastExternalIPAddress", "HealthStatus", "RiskScore", "ExposureLevel", ] files = remove_duplicates_from_list_arg(args, "file_hash") raw_response = [] context_outputs = [] all_machines_outputs = [] failed_files = {} # if we got an error, we will return the file that failed for file in files: try: machines_response = client.get_file_related_machines(file) raw_response.append(machines_response) for machine in machines_response["value"]: all_machines_outputs.append(get_machine_data(machine)) context_outputs.append({"File": file, "Machines": get_machines_list(machines_response)}) except Exception as e: failed_files[file] = e continue human_readable = tableToMarkdown( f"{INTEGRATION_NAME} machines related to files {files}", all_machines_outputs, headers=headers, removeNull=True ) human_readable += add_error_message(failed_files, files) return CommandResults( readable_output=human_readable, outputs=context_outputs, outputs_prefix="MicrosoftATP.FileMachine", raw_response=raw_response, ) def parse_ip_addresses(ip_addresses: list[dict]) -> list[dict]: """ Creates new dict with readable keys and concat all the ip addresses with the same MAC address. Args: ip_addresses (List[Dict]): List of ip addresses dictionaries as recieved from the api. Returns: List of dicts """ mac_addresses = dict.fromkeys([item.get("macAddress") for item in ip_addresses]) for item in ip_addresses: current_mac = item.get("macAddress") if not mac_addresses[current_mac]: mac_addresses[current_mac] = { "MACAddress": item["macAddress"], "IPAddresses": [item["ipAddress"]], "Type": item["type"], "Status": item["operationalStatus"], } else: mac_addresses[current_mac]["IPAddresses"].append(item["ipAddress"]) # type: ignore return list(mac_addresses.values()) # type: ignore def print_ip_addresses(parsed_ip_addresses: list[dict]) -> str: """ Converts the given list of ip addresses to ascii table. Args: parsed_ip_addresses (List[Dict]): Returns: ascii table without headers """ rows = [] for i, entry in enumerate(parsed_ip_addresses, start=1): rows.append( [ f"{i}.", f"MAC : {entry['MACAddress']}", f"IP Addresses : {','.join(entry['IPAddresses'])}", f"Type : {entry['Type']}", f"Status : {entry['Status']}", ] ) max_lengths = [len(max(col, key=lambda x: len(x))) for col in zip(*rows)] # to make sure the table is pretty string_rows = [" | ".join([cell.ljust(max_len_col) for cell, max_len_col in zip(row, max_lengths)]) for row in rows] return "\n".join(string_rows) def get_machine_details_command(client: MsClient, args: dict) -> CommandResults: """Retrieves specific Machine by its machine ID or computer name. Returns: CommandResults. Human readable, context, raw response """ headers = [ "ID", "ComputerDNSName", "OSPlatform", "LastIPAddress", "LastExternalIPAddress", "HealthStatus", "RiskScore", "ExposureLevel", "IPAddresses", ] machine_ids = remove_duplicates_from_list_arg(args, "machine_id") raw_response = [] machines_outputs = [] machines_readable_outputs = [] failed_machines = {} # if we got an error, we will return the machine ids that failed for machine_id in machine_ids: try: machine_response = client.get_machine_details(machine_id) machine_data = get_machine_data(machine_response) machine_data_to_readable_outputs = copy.deepcopy(machine_data) raw_ip_addresses = machine_data_to_readable_outputs.get("IPAddresses", []) parsed_ip_address = parse_ip_addresses(raw_ip_addresses) human_readable_ip_addresses = print_ip_addresses(parsed_ip_address) machine_data_to_readable_outputs["IPAddresses"] = human_readable_ip_addresses machines_outputs.append(machine_data) machines_readable_outputs.append(machine_data_to_readable_outputs) raw_response.append(machine_response) except Exception as e: failed_machines[machine_id] = e continue human_readable = tableToMarkdown( f"{INTEGRATION_NAME} machines {machine_ids} details:", machines_readable_outputs, headers=headers, removeNull=True ) human_readable += add_error_message(failed_machines, machine_ids) return CommandResults( outputs_prefix="MicrosoftATP.Machine", outputs_key_field="ID", outputs=machines_outputs, readable_output=human_readable, raw_response=raw_response, ) def get_machine_software_command(client: MsClient, args: dict) -> CommandResults: """Retrieves a collection of installed software on a specific device. https://learn.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-installed-software?view=o365-worldwide Args: client: MsClient args: arguments from CortexSOAR. May include 'machine_id'. Returns: CommandResults. """ headers = [ "ID", "Name", "Vendor", "Weakness", "PublicExploit", "ActiveAlert", "ExposedMachines", "InstalledMachines", "ImpactScore", "IsNormalized", "Category", ] machine_id = args.get("machine_id", "") raw_response = client.get_software_by_machine_id(machine_id) software_outputs = get_machine_softwares_list(raw_response) human_readable = tableToMarkdown( f"{INTEGRATION_NAME} software on machine: {machine_id}", software_outputs, headers=headers, removeNull=True ) return CommandResults( outputs_prefix="MicrosoftATP.Software", outputs_key_field="ID", outputs=software_outputs, readable_output=human_readable, raw_response=raw_response, ) def get_machine_vulnerabilities_command(client: MsClient, args: dict) -> CommandResults: """Retrieves a collection of vulnerabilities related to specific device. Args: client: MsClient args: arguments from CortexSOAR. May include 'machine_id'. Returns: CommandResults. """ headers = [ "ID", "Name", "CVESupportability", "CVSSV3", "CVSSVector", "Description", "EPSS", "ExploitInKit", "ExploitTypes", "ExploitURIs", "ExploitVerified", "ExposedMachines", "FirstDetected", "PublicExploit", "PublishedOn", "Severity", "Tags", "UpdatedOn", ] # noqa: E501 machine_id = args.get("machine_id", "") raw_response = client.get_vulnerabilities_by_machine_id(machine_id) vulns_outputs = get_machine_vulnerabilities_list(raw_response) human_readable = tableToMarkdown( f"{INTEGRATION_NAME} Vulnerabilities for machine: {machine_id}", vulns_outputs, headers=headers, removeNull=True ) return CommandResults( outputs_prefix="MicrosoftATP.PublicVulnerability", outputs_key_field="ID", outputs=vulns_outputs, readable_output=human_readable, raw_response=raw_response, ) def get_machine_missing_kbs_command(client: MsClient, args: dict) -> CommandResults: """Retrieves a collection of missing security updates on a specific device. Args: client: MsClient args: arguments from CortexSOAR. May include 'machine_id'. Returns: CommandResults. """ headers = ["ID", "Name", "OSBuild", "URL", "MachineMissedOn", "CVEAddressed", "ProductNames"] machine_id = args.get("machine_id", "") raw_response = client.get_missing_kbs_by_machine_id(machine_id) missing_kbs_output = get_machine_missing_kbs_list(raw_response) human_readable = tableToMarkdown( f"Missing Security Updates (KBs) for machine: {machine_id}", missing_kbs_output, headers=headers, removeNull=True, ) return CommandResults( outputs_prefix="MicrosoftATP.PublicProductFix", outputs=missing_kbs_output, outputs_key_field="ID", readable_output=human_readable, raw_response=raw_response, ) def run_antivirus_scan_command(client: MsClient, args: dict): """Initiate Windows Defender Antivirus scan on a machine. Returns: (str, dict, dict). Human readable, context, raw response """ headers = ["ID", "Type", "Requestor", "RequestorComment", "Status", "MachineID", "ComputerDNSName"] machine_ids = remove_duplicates_from_list_arg(args, "machine_id") scan_type = args.get("scan_type") comment = args.get("comment") machine_actions_data = [] raw_response = [] failed_machines = {} # if we got an error, we will return the machine ids that failed for machine_id in machine_ids: try: machine_action_response = client.run_antivirus_scan(machine_id, comment, scan_type) machine_actions_data.append(get_machine_action_data(machine_action_response)) raw_response.append(machine_action_response) except Exception as e: failed_machines[machine_id] = e continue entry_context = {"MicrosoftATP.MachineAction(val.ID === obj.ID)": machine_actions_data} human_readable = tableToMarkdown( "Antivirus scan successfully triggered", machine_actions_data, headers=headers, removeNull=True ) human_readable += add_error_message(failed_machines, machine_ids) return human_readable, entry_context, raw_response def list_alerts_command(client: MsClient, args: dict): """Initiate Windows Defender Antivirus scan on a machine. Returns: (str, dict, dict). Human readable, context, raw response """ headers = [ "ID", "Title", "Description", "IncidentID", "Severity", "Status", "Classification", "Category", "ThreatFamilyName", "MachineID", ] severity = args.get("severity") status = args.get("status") category = args.get("category") limit = arg_to_number(args.get("limit", 50)) creation_time = arg_to_datetime(args.get("creation_time"), required=False) fields_to_filter_by = { "severity": severity, "status": status, "category": category, } filter_req = reformat_filter(fields_to_filter_by) alerts_response = client.list_alerts(filter_req, limit, creation_time=creation_time, evidence=True) alerts_list = get_alerts_list(alerts_response) entry_context = {"MicrosoftATP.Alert(val.ID === obj.ID)": alerts_list} human_readable = tableToMarkdown( f"{INTEGRATION_NAME} alerts with limit of {limit}:", alerts_list, headers=headers, removeNull=True ) return human_readable, entry_context, alerts_response def get_alerts_list(alerts_response): """Get a raw response of alerts list Args: alerts_response (dict): The raw response with the alerts list in it Returns: list. Alerts list """ alerts_list = [] for alert in alerts_response["value"]: alert_data = get_alert_data(alert) alerts_list.append(alert_data) return alerts_list def update_alert_command(client: MsClient, args: dict): """Updates properties of existing Alert. Returns: (str, dict, dict). Human readable, context, raw response """ alert_id = args.get("alert_id") assigned_to = args.get("assigned_to") status = args.get("status") classification = args.get("classification") determination = args.get("determination") comment = args.get("comment") args_list = [assigned_to, status, classification, determination, comment] check_given_args_update_alert(args_list) json_data, context = add_args_to_json_and_context(alert_id, assigned_to, status, classification, determination, comment) alert_response = client.update_alert(alert_id, json_data) entry_context = {"MicrosoftATP.Alert(val.ID === obj.ID)": context} human_readable = f"The alert {alert_id} has been updated successfully" return human_readable, entry_context, alert_response def check_given_args_update_alert(args_list): """Gets an arguments list and returns an error if all of them are empty""" if all(v is None for v in args_list): raise Exception("No arguments were given to update the alert") def add_args_to_json_and_context(alert_id, assigned_to, status, classification, determination, comment): """Gets arguments and returns the json and context with the arguments inside""" json_data = {} context = {"ID": alert_id} if assigned_to: json_data["assignedTo"] = assigned_to context["AssignedTo"] = assigned_to if status: json_data["status"] = status context["Status"] = status if classification: json_data["classification"] = classification context["Classification"] = classification if determination: json_data["determination"] = determination context["Determination"] = determination if comment: json_data["comment"] = comment context["Comment"] = comment return json_data, context def get_advanced_hunting_command(client: MsClient, args: dict): """Get results of advanced hunting according to user query. Returns: (str, dict, dict). Human readable, context, raw response """ query = args.get("query", "") query_batch = args.get("query_batch", "") if query and query_batch: raise DemistoException("Both query and query_batch were given, please provide just one") if not query and not query_batch: raise DemistoException("Both query and query_batch were not given, please provide one") queries: list[dict[str, str]] = [] if query: queries.append( { "timeout": args.get("timeout", "10"), "time_range": args.get("time_range", ""), "name": args.get("name", ""), "query": query, } ) else: query = safe_load_json(query_batch) queries.extend(query) if len(queries) > 10: raise DemistoException("Please provide only up to 10 queries.") human_readable = "" outputs = [] for query_details in queries: query = query_details.get("query") name = query_details.get("name") timeout = int(query_details.get("timeout", "") or args.get("timeout", 10)) time_range = query_details.get("time_range") or args.get("time_range", "") response = client.get_advanced_hunting(query, timeout, time_range) results: dict[str, Any] = response.get("Results", {}) if isinstance(results, list) and len(results) == 1: report_id = results[0].get("ReportId") if report_id: results[0]["ReportId"] = str(report_id) if name: outputs.append({name: results}) else: outputs = [results] human_readable += tableToMarkdown(f"Hunt results for {name} query:", results, removeNull=True) if len(outputs) == 1: entry_context: dict[str, Any] = {"MicrosoftATP.Hunt.Result": outputs[0]} else: entry_context = {"MicrosoftATP.Hunt.Result": outputs} return human_readable, entry_context, response def create_alert_command(client: MsClient, args: dict): """Creates new Alert on top of Event. Returns: (str, dict, dict). Human readable, context, raw response """ headers = [ "ID", "Title", "Description", "IncidentID", "Severity", "Status", "Classification", "Category", "ThreatFamilyName", "MachineID", ] alert_response = client.create_alert( args.get("machine_id"), args.get("severity"), args.get("title"), args.get("description"), args.get("event_time"), args.get("report_id"), args.get("recommended_action"), args.get("category"), ) alert_data = get_alert_data(alert_response) entry_context = {"MicrosoftATP.Alert(val.ID === obj.ID)": alert_data} human_readable = tableToMarkdown("Alert created:", alert_data, headers=headers, removeNull=True) return human_readable, entry_context, alert_response def get_alert_related_files_command(client: MsClient, args: dict): """Retrieves all files related to a specific alert. Returns: (str, dict, dict). Human readable, context, raw response """ headers = ["Sha1", "Sha256", "SizeInBytes", "FileType", "FilePublisher", "FileProductName"] alert_id = args.get("id") limit = args.get("limit") offset = args.get("offset") limit, offset = check_limit_and_offset_values(limit, offset) response = client.get_alert_related_files(alert_id) response_files_list = response["value"] files_data_list = [] from_index = min(offset, len(response_files_list)) to_index = min(offset + limit, len(response_files_list)) for file_obj in response_files_list[from_index:to_index]: files_data_list.append(get_file_data(file_obj)) context_output = {"AlertID": alert_id, "Files": files_data_list} entry_context = {"MicrosoftATP.AlertFile(val.AlertID === obj.AlertID)": context_output} human_readable = tableToMarkdown(f"Alert {alert_id} Related Files:", files_data_list, headers=headers, removeNull=True) return human_readable, entry_context, response_files_list def check_limit_and_offset_values(limit, offset): """Gets the limit and offset values and return an error if the values are invalid""" if not limit.isdigit(): raise Exception("Error: You can only enter a positive integer or zero to limit argument.") elif not offset.isdigit(): raise Exception("Error: You can only enter a positive integer to offset argument.") else: limit_int = int(limit) offset_int = int(offset) if limit_int == 0: raise Exception("Error: The value of the limit argument must be a positive integer.") return limit_int, offset_int def get_file_data(file_response): """Get file raw response and returns the file's info for context and human readable. Returns: dict. File's info """ file_data = assign_params( Sha1=file_response.get("sha1"), Size=file_response.get("size"), Sha256=file_response.get("sha256"), Md5=file_response.get("md5"), GlobalPrevalence=file_response.get("globalPrevalence"), GlobalFirstObserved=file_response.get("globalFirstObserved"), GlobalLastObserved=file_response.get("globalLastObserved"), SizeInBytes=file_response.get("size"), FileType=file_response.get("fileType"), IsPeFile=file_response.get("isPeFile"), FilePublisher=file_response.get("filePublisher"), FileProductName=file_response.get("fileProductName"), Signer=file_response.get("signer"), Issuer=file_response.get("issuer"), SignerHash=file_response.get("signerHash"), IsValidCertificate=file_response.get("isValidCertificate"), DeterminationType=file_response.get("determinationType"), DeterminationValue=file_response.get("determinationValue"), ) return file_data def get_alert_related_ips_command(client: MsClient, args: dict): """Retrieves all IPs related to a specific alert. Returns: (str, dict, dict). Human readable, context, raw response """ alert_id = args.get("id") limit = args.get("limit") offset = args.get("offset") limit, offset = check_limit_and_offset_values(limit, offset) response = client.get_alert_related_ips(alert_id) response_ips_list = response["value"] ips_list = [] from_index = min(offset, len(response_ips_list)) to_index = min(offset + limit, len(response_ips_list)) for ip in response_ips_list[from_index:to_index]: ips_list.append(ip["id"]) context_output = {"AlertID": alert_id, "IPs": ips_list} entry_context = {"MicrosoftATP.AlertIP(val.AlertID === obj.AlertID)": context_output} human_readable = f"Alert {alert_id} Related IPs: {ips_list}" return human_readable, entry_context, response_ips_list def get_alert_related_domains_command(client: MsClient, args: dict): """Retrieves all domains related to a specific alert. Returns: (str, dict, dict). Human readable, context, raw response """ alert_id = args.get("id") limit = args.get("limit") offset = args.get("offset") limit, offset = check_limit_and_offset_values(limit, offset) response = client.get_alert_related_domains(alert_id) response_domains_list = response["value"] domains_list = [] from_index = min(offset, len(response_domains_list)) to_index = min(offset + limit, len(response_domains_list)) for domain in response_domains_list[from_index:to_index]: domains_list.append(domain["host"]) context_output = {"AlertID": alert_id, "Domains": domains_list} entry_context = {"MicrosoftATP.AlertDomain(val.AlertID === obj.AlertID)": context_output} human_readable = f"Alert {alert_id} Related Domains: {domains_list}" return human_readable, entry_context, response_domains_list def get_machine_action_by_id_command(client: MsClient, args: dict): """Returns machine's actions, if action ID is None, return all actions. Returns: (str, dict, dict). Human readable, context, raw response """ headers = ["ID", "Type", "Requestor", "RequestorComment", "Status", "MachineID", "ComputerDNSName"] action_id = args.get("id", "") status = args.get("status", "") machine_id = remove_duplicates_from_list_arg(args, "machine_id") type = args.get("type", "") requestor = args.get("requestor", "") filters = args.get("filters", "") limit = arg_to_number(args.get("limit", 50)) if action_id: for index in range(3): try: response = client.get_machine_action_by_id(action_id) demisto.debug(f"The response for get machine action details: {response}") if response: break except Exception as e: if "ResourceNotFound" in str(e) and index < 3: time.sleep(1) else: raise Exception(f"Machine action {action_id} was not found") response = client.get_machine_action_by_id(action_id) action_data = get_machine_action_data(response) human_readable = tableToMarkdown(f"Action {action_id} Info:", action_data, headers=headers, removeNull=True) context_output = action_data else: # A dictionary that contains all of the fields the user want to filter results by. # It will be sent in the request so the requested filters are applied on the results fields_to_filter_by = {"status": status, "machineId": machine_id, "type": type, "requestor": requestor} filter_req = filters or reformat_filter_with_list_arg(fields_to_filter_by, "machineId") response = client.get_machine_actions(filter_req, limit) machine_actions_list = [] for machine_action in response["value"]: machine_actions_list.append(get_machine_action_data(machine_action)) human_readable = tableToMarkdown( f"Machine actions Info with limit of {limit}:", machine_actions_list, headers=headers, removeNull=True ) context_output = machine_actions_list entry_context = {"MicrosoftATP.MachineAction(val.ID === obj.ID)": context_output} demisto.debug(f"The final entry context for get machine details: {entry_context}") return human_readable, entry_context, response def get_machine_investigation_package(client: MsClient, args: dict): machine_id = args.get("machine_id") comment = args.get("comment") res = client.get_investigation_package(machine_id, comment, overwrite_rate_limit_retry=True) human_readable = tableToMarkdown("Processing action. This may take a few minutes.", res["id"], headers=["id"]) return CommandResults( outputs_prefix="MicrosoftATP.MachineAction", readable_output=human_readable, outputs={"action_id": res["id"]} ) def request_download_investigation_package_command(client: MsClient, args: dict): return run_polling_command( client, args, "microsoft-atp-request-and-download-investigation-package", get_machine_investigation_package, get_machine_action_command, download_file_after_successful_status, ) def generate_login_url_command(client: MsClient): return generate_login_url(client.ms_client, MICROSOFT_DEFENDER_FOR_ENDPOINT_TOKEN_RETRIVAL_ENDPOINTS[client.endpoint_type]) def list_auth_permissions_command(client: MsClient) -> CommandResults: """Lists the auth permissions using the decoded JWT. Args: client (MsClient): Client to access Microsoft Defender Advanced Threat Protection (ATP) API. Raises: TypeError: If the decoded JWT is not a dictionary. Returns: CommandResults: Command results containing human-readable output. """ decoded_token = client.get_decoded_token() if not isinstance(decoded_token, dict): raise TypeError(f"Expected decoded token dict. Got type: {type(decoded_token).__name__}.") permissions = "\n".join(sorted(decoded_token.get("roles", []))) human_readable = f"### Permissions\n{permissions}" return CommandResults(readable_output=human_readable) def download_file_after_successful_status(client, res): demisto.debug("post polling - download file") machine_action_id = res["id"] # get file uri from action: file_uri = client.get_investigation_package_sas_uri(machine_action_id, overwrite_rate_limit_retry=True)["value"] demisto.debug(f"Got file for downloading: {file_uri}") # download link, create file result. File comes back as compressed gz file. f_data = client.download_file(file_uri) md_results = { "Machine Action Id": res.get("id"), "MachineId": res.get("machineId"), "Status": res.get("status"), } return [ fileResult("Response Result.gz", f_data.content), CommandResults( outputs_prefix="MicrosoftATP.MachineAction", outputs=res, readable_output=tableToMarkdown("Machine Action:", md_results), ), ] def get_machine_action_data(machine_action_response): """Get machine raw response and returns the machine action info in context and human readable format. Notes: Machine action is a collection of actions you can apply on the machine, for more info https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/machineaction Returns: dict. Machine action's info """ action_data = { "ID": machine_action_response.get("id"), "Type": machine_action_response.get("type"), "Scope": machine_action_response.get("scope"), "Requestor": machine_action_response.get("requestor"), "RequestorComment": machine_action_response.get("requestorComment"), "Status": machine_action_response.get("status"), "MachineID": machine_action_response.get("machineId"), "ComputerDNSName": machine_action_response.get("computerDnsName"), "CreationDateTimeUtc": machine_action_response.get("creationDateTimeUtc"), "LastUpdateTimeUtc": machine_action_response.get("lastUpdateDateTimeUtc"), "RelatedFileInfo": { "FileIdentifier": (machine_action_response.get("relatedFileInfo") or {}).get("fileIdentifier"), "FileIdentifierType": (machine_action_response.get("relatedFileInfo") or {}).get("fileIdentifierType"), }, "Commands": machine_action_response.get("commands"), } return action_data def get_machine_investigation_package_command(client: MsClient, args: dict): """Collect investigation package from a machine. Returns: (str, dict, dict). Human readable, context, raw response """ headers = ["ID", "Type", "Requestor", "RequestorComment", "Status", "MachineID", "ComputerDNSName"] machine_id = args.get("machine_id") comment = args.get("comment") machine_action_response = client.get_investigation_package(machine_id, comment) action_data = get_machine_action_data(machine_action_response) human_readable = tableToMarkdown( f"Initiating collect investigation package from {machine_id} machine :", action_data, headers=headers, removeNull=True ) entry_context = {"MicrosoftATP.MachineAction(val.ID === obj.ID)": action_data} return human_readable, entry_context, machine_action_response def get_investigation_package_sas_uri_command(client: MsClient, args: dict): """Returns a URI that allows downloading an Investigation package. Returns: (str, dict, dict). Human readable, context, raw response """ action_id = args.get("action_id") response = client.get_investigation_package_sas_uri(action_id) link = {"Link": response["value"]} human_readable = ( f'Success. This link is valid for a very short time and should be used immediately for' f' downloading the package to a local storage{link["Link"]}' ) entry_context = {"MicrosoftATP.InvestigationURI(val.Link === obj.Link)": link} return human_readable, entry_context, response def restrict_app_execution_command(client: MsClient, args: dict): """Restrict execution of all applications on the machine except a predefined set. Returns: (str, dict, dict). Human readable, context, raw response """ headers = ["ID", "Type", "Requestor", "RequestorComment", "Status", "MachineID", "ComputerDNSName"] machine_id = args.get("machine_id") comment = args.get("comment") machine_action_response = client.restrict_app_execution(machine_id, comment) action_data = get_machine_action_data(machine_action_response) human_readable = tableToMarkdown( f"Initiating Restrict execution of all applications on the machine {machine_id} except a predefined set:", action_data, headers=headers, removeNull=True, ) entry_context = {"MicrosoftATP.MachineAction(val.ID === obj.ID)": action_data} return human_readable, entry_context, machine_action_response def remove_app_restriction_command(client: MsClient, args: dict): """Enable execution of any application on the machine. Returns: (str, dict, dict). Human readable, context, raw response """ headers = ["ID", "Type", "Requestor", "RequestorComment", "Status", "MachineID", "ComputerDNSName"] machine_id = args.get("machine_id") comment = args.get("comment") machine_action_response = client.remove_app_restriction(machine_id, comment) action_data = get_machine_action_data(machine_action_response) human_readable = tableToMarkdown( f"Removing applications restriction on the machine {machine_id}:", action_data, headers=headers, removeNull=True ) entry_context = {"MicrosoftATP.MachineAction(val.ID === obj.ID)": action_data} return human_readable, entry_context, machine_action_response @polling_function( name="microsoft-atp-stop-and-quarantine-file", interval=arg_to_number(demisto.args().get("interval_in_seconds", 10)), timeout=arg_to_number(demisto.args().get("timeout_in_seconds", 600)), requires_polling_arg=True, # If user provides polling arg as false, dont poll ) def stop_and_quarantine_file_command_polling(args: dict, client: MsClient): """ Stops the execution of files on machines and quarantines them. This command is asynchronous and polls for completion. Args: machine_id (list | str): A comma-separated list or a single machine ID. file_hash (list | str): A comma-separated list or a single SHA1 file hash. comment (str): A comment to associate with the action. polling (bool): If true, the command will poll for completion. Default is true. interval_in_seconds (int): The interval between polling attempts. timeout_in_seconds (int): The timeout for the polling. Returns: In case of polling: PollResult: An object containing the results and polling status. In case of non-polling: CommandResult: An object containing the results. """ demisto.debug("Stop and Quarantine File command polling started") headers = ["ID", "Type", "Requestor", "RequestorComment", "Status", "MachineID", "ComputerDNSName"] def _initial_call(): demisto.debug("First run: Initiating quarantine actions.") machine_ids = argToList(args.get("machine_id")) file_sha1s = argToList(args.get("file_hash")) comment = args.get("comment") action_ids_to_poll = [] all_context_outputs = [] all_api_raw_responses = [] for machine_id, file_sha1 in product(machine_ids, file_sha1s): machine_action_response = {} try: demisto.debug(f"Initiating quarantine for file {file_sha1} on machine {machine_id}.") machine_action_response = client.stop_and_quarantine_file(machine_id, file_sha1, comment) machine_action_response["machineId"] = machine_id context_output = get_machine_action_data(machine_action_response) demisto.debug(f"Successfully initiated quarantine for file {file_sha1} on machine {machine_id}.") action_ids_to_poll.append(context_output.get("ID")) except Exception as e: demisto.debug(f"Failed to initiate quarantine for file {file_sha1} on machine {machine_id}: {e}") machine_action_response = { "requestorComment": comment, "status": "Failed", "machineId": machine_id, "id": None, "type": None, "scope": None, "requestor": None, "computerDnsName": None, "creationDateTimeUtc": None, "lastUpdateTimeUtc": None, "relatedFileInfo": { "fileIdentifier": file_sha1, "fileIdentifierType": None, }, "commands": None, } context_output = get_machine_action_data(machine_action_response) finally: all_context_outputs.append(context_output) all_api_raw_responses.append(machine_action_response) human_readable = tableToMarkdown( name="Stopping and quarantine", t=all_context_outputs, headers=headers, removeNull=True, ) command_results = CommandResults( outputs_prefix="MicrosoftATP.MachineAction", outputs_key_field="ID", readable_output=human_readable, outputs=all_context_outputs, raw_response=all_api_raw_responses, ) demisto.debug(f"Initiated {len(action_ids_to_poll)} quarantine actions. Polling for status...") demisto.debug(f"args: {args}") if not argToBoolean(args.get("polling", False)) or not action_ids_to_poll: demisto.debug("No quarantine actions were initiated or polling is disabled. ") continue_to_poll = False else: command_results.readable_output = "Quarantine operations are still in progress..." continue_to_poll = True return PollResult( partial_result=command_results, continue_to_poll=continue_to_poll, args_for_next_run={"action_ids": action_ids_to_poll, "polling": argToBoolean(args.get("polling", False)), **args}, response=command_results, ) def _polling_call(): all_context_outputs = [] all_api_raw_responses = [] action_ids = argToList(args.get("action_ids")) action_statuses = [] for action_id in action_ids: _, context, _ = get_machine_action_by_id_command(client, {"id": action_id}) all_api_raw_responses.append(context) context_output = context.get("MicrosoftATP.MachineAction(val.ID === obj.ID)") all_context_outputs.append(context_output) action_statuses.append(context_output.get("Status", "Unknown")) human_readable = tableToMarkdown( name="Completed Quarantine", t=all_context_outputs, headers=headers, removeNull=True, ) command_results = CommandResults( outputs_prefix="MicrosoftATP.MachineAction", outputs_key_field="ID", readable_output=human_readable, outputs=all_context_outputs, raw_response=all_api_raw_responses, ) continue_to_poll = any(status in ["Pending", "InProgress"] for status in action_statuses) # Return poll result with args for next poll and also return the results in case polling is disabled return PollResult( partial_result=command_results, continue_to_poll=continue_to_poll, args_for_next_run=args, response=command_results ) if not args.get("action_ids"): return _initial_call() else: return _polling_call() def get_investigations_by_id_command(client: MsClient, args: dict): """Returns the investigation info, if investigation ID is None, return all investigations. Returns: (str, dict, dict). Human readable, context, raw response """ headers = [ "ID", "StartTime", "EndTime", "CancelledBy", "InvestigationState", "StatusDetails", "MachineID", "ComputerDNSName", "TriggeringAlertID", ] investigation_id = args.get("id", "") limit = args.get("limit") offset = args.get("offset") limit, offset = check_limit_and_offset_values(limit, offset) if investigation_id: response = client.get_investigation_by_id(investigation_id) investigation_data = get_investigation_data(response) human_readable = tableToMarkdown( f"Investigation {investigation_id} Info:", investigation_data, headers=headers, removeNull=True ) context_output = investigation_data else: response = client.get_investigation_list()["value"] investigations_list = [] from_index = min(offset, len(response)) to_index = min(offset + limit, len(response)) for investigation in response[from_index:to_index]: investigations_list.append(get_investigation_data(investigation)) human_readable = tableToMarkdown("Investigations Info:", investigations_list, headers=headers, removeNull=True) context_output = investigations_list entry_context = {"MicrosoftATP.Investigation(val.ID === obj.ID)": context_output} return human_readable, entry_context, response def get_investigation_data(investigation_response): """Get investigation raw response and returns the investigation info for context and human readable. Args: investigation_response: The investigation raw response Returns: dict. Investigation's info """ investigation_data = { "ID": investigation_response.get("id"), "StartTime": investigation_response.get("startTime"), "EndTime": investigation_response.get("endTime"), "InvestigationState": investigation_response.get("state"), "CancelledBy": investigation_response.get("cancelledBy"), "StatusDetails": investigation_response.get("statusDetails"), "MachineID": investigation_response.get("machineId"), "ComputerDNSName": investigation_response.get("computerDnsName"), "TriggeringAlertID": investigation_response.get("triggeringAlertId"), } return investigation_data def start_investigation_command(client: MsClient, args: dict): """Start automated investigation on a machine. Returns: (str, dict, dict). Human readable, context, raw response """ headers = [ "ID", "StartTime", "EndTime", "CancelledBy", "InvestigationState", "StatusDetails", "MachineID", "ComputerDNSName", "TriggeringAlertID", ] machine_id = args.get("machine_id") comment = args.get("comment") timeout = int(args.get("timeout", 50)) response = client.start_investigation(machine_id, comment, timeout) investigation_id = response["id"] investigation_data = get_investigation_data(response) human_readable = tableToMarkdown( f"Starting investigation {investigation_id} on {machine_id} machine:", investigation_data, headers=headers, removeNull=True, ) entry_context = {"MicrosoftATP.Investigation(val.ID === obj.ID)": investigation_data} return human_readable, entry_context, response def get_domain_statistics_command(client: MsClient, args: dict): """Retrieves the statistics on the given domain. Returns: (str, dict, dict). Human readable, context, raw response """ domain = args.get("domain") response = client.get_domain_statistics(domain) domain_statistics = get_domain_statistics_context(response) human_readable = tableToMarkdown(f"Statistics on {domain} domain:", domain_statistics, removeNull=True) context_output = {"Domain": domain, "Statistics": domain_statistics} entry_context = {"MicrosoftATP.DomainStatistics(val.Domain === obj.Domain)": context_output} return human_readable, entry_context, response def get_domain_statistics_context(domain_stat_response): """Gets the domain statistics response and returns it in context format. Returns: (dict). domain statistics context """ domain_statistics = assign_params( Host=domain_stat_response.get("host"), OrgPrevalence=domain_stat_response.get("orgPrevalence"), OrgFirstSeen=domain_stat_response.get("orgFirstSeen"), OrgLastSeen=domain_stat_response.get("orgLastSeen"), ) return domain_statistics def get_domain_alerts_command(client: MsClient, args: dict): """Retrieves a collection of Alerts related to a given domain address. Returns: (str, dict, dict). Human readable, context, raw response """ headers = [ "ID", "Title", "Description", "IncidentID", "Severity", "Status", "Classification", "Category", "ThreatFamilyName", "MachineID", ] domain = args.get("domain") response = client.get_domain_alerts(domain) alerts_list = get_alerts_list(response) human_readable = tableToMarkdown(f"Domain {domain} related alerts Info:", alerts_list, headers=headers, removeNull=True) context_output = {"Domain": domain, "Alerts": alerts_list} entry_context = {"MicrosoftATP.DomainAlert(val.Domain === obj.Domain)": context_output} return human_readable, entry_context, response def get_alert_data(alert_response): """Get alert raw response and returns the alert info in context and human readable format. Returns: dict. Alert info """ alert_data = { "ID": alert_response.get("id"), "IncidentID": alert_response.get("incidentId"), "InvestigationID": alert_response.get("investigationId"), "InvestigationState": alert_response.get("investigationState"), "AssignedTo": alert_response.get("assignedTo"), "Severity": alert_response.get("severity"), "Status": alert_response.get("status"), "Classification": alert_response.get("classification"), "Determination": alert_response.get("determination"), "DetectionSource": alert_response.get("detectionSource"), "Category": alert_response.get("category"), "ThreatFamilyName": alert_response.get("threatFamilyName"), "Title": alert_response.get("title"), "Description": alert_response.get("description"), "AlertCreationTime": alert_response.get("alertCreationTime"), "FirstEventTime": alert_response.get("firstEventTime"), "LastEventTime": alert_response.get("lastEventTime"), "LastUpdateTime": alert_response.get("lastUpdateTime"), "ResolvedTime": alert_response.get("resolvedTime"), "MachineID": alert_response.get("machineId"), "ComputerDNSName": alert_response.get("computerDnsName"), "AADTenantID": alert_response.get("aadTenantId"), "Comments": [ { "Comment": alert_response.get("comment"), "CreatedBy": alert_response.get("createdBy"), "CreatedTime": alert_response.get("createdTime"), } ], "Evidence": alert_response.get("evidence"), "DetectorID": alert_response.get("detectorId"), "ThreatName": alert_response.get("threatName"), "RelatedUser": alert_response.get("relatedUser"), "MitreTechniques": alert_response.get("mitreTechniques"), "RBACGroupName": alert_response.get("rbacGroupName"), } return alert_data def get_domain_machine_command(client: MsClient, args: dict): """Retrieves a collection of Machines that have communicated to or from a given domain address. Returns: (str, dict, dict). Human readable, context, raw response """ headers = [ "ID", "ComputerDNSName", "OSPlatform", "LastIPAddress", "LastExternalIPAddress", "HealthStatus", "RiskScore", "ExposureLevel", ] domain = args.get("domain") response = client.get_domain_machines(domain) machines_list = get_machines_list(response) human_readable = tableToMarkdown( f"Machines that have communicated with {domain} domain:", machines_list, headers=headers, removeNull=True ) context_output = {"Domain": domain, "Machines": machines_list} entry_context = {"MicrosoftATP.DomainMachine(val.Domain === obj.Domain)": context_output} return human_readable, entry_context, response def get_machine_data(machine): """Get machine raw response and returns the machine's info in context and human readable format. Returns: dict. Machine's info """ machine_data = assign_params( ID=machine.get("id"), ComputerDNSName=machine.get("computerDnsName"), FirstSeen=machine.get("firstSeen"), LastSeen=machine.get("lastSeen"), OSPlatform=machine.get("osPlatform"), OSVersion=machine.get("version"), OSProcessor=machine.get("osProcessor"), LastIPAddress=machine.get("lastIpAddress"), LastExternalIPAddress=machine.get("lastExternalIpAddress"), AgentVersion=machine.get("agentVersion"), OSBuild=machine.get("osBuild"), HealthStatus=machine.get("healthStatus"), RBACGroupID=machine.get("rbacGroupId"), RBACGroupName=machine.get("rbacGroupName"), RiskScore=machine.get("riskScore"), ExposureLevel=machine.get("exposureLevel"), AADDeviceID=machine.get("aadDeviceId"), IsAADJoined=machine.get("isAadJoined"), MachineTags=machine.get("machineTags"), IPAddresses=machine.get("ipAddresses"), ) return machine_data def get_machine_software_data(machine_software): """Get machine raw response and returns the machine's software info in context and human readable format. Returns: dict. Machine's software info """ machine_software_data = assign_params( ID=machine_software.get("id"), Name=machine_software.get("name"), Vendor=machine_software.get("vendor"), Weakness=machine_software.get("weakness"), PublicExploit=machine_software.get("publicExploit"), ActiveAlerts=machine_software.get("activeAlert"), ExposedMachines=machine_software.get("exposedMachines"), InstalledMachines=machine_software.get("installedMachines"), ImpactScore=machine_software.get("impactScore"), IsNormalized=machine_software.get("isNormalized"), Category=machine_software.get("category"), ) return machine_software_data def get_machine_missing_kb_data(missing_kb): """Get machine missing KB raw response and returns the machine's missing KB info in context and human readable format. Returns: dict. Machine's missing KB info """ missing_kb_data = assign_params( ID=missing_kb.get("id"), Name=missing_kb.get("name"), OSBuild=missing_kb.get("osBuild"), URL=missing_kb.get("url"), MachinesMissedOn=missing_kb.get("machinesMissedOn"), CVEAddressed=missing_kb.get("cveAddressed"), ProductNames=missing_kb.get("productNames"), ) return missing_kb_data def get_machine_vulnerability_data(vulnerabiliy): """Get machine vulnerability raw response and returns the machine's vulnerability info in context and human readable format. Returns: dict. Machine's vulnerability info """ vulnerability_data = assign_params( ID=vulnerabiliy.get("id"), Name=vulnerabiliy.get("name"), CVESupportability=vulnerabiliy.get("cveSupportability"), CVSSV3=vulnerabiliy.get("cvssV3"), CVSSVector=vulnerabiliy.get("cvssVector"), Description=vulnerabiliy.get("description"), EPSS=vulnerabiliy.get("epss"), ExploitInKit=vulnerabiliy.get("exploitInKit"), ExploitTypes=vulnerabiliy.get("exploitTypes"), ExploitURIs=vulnerabiliy.get("exploitURIs"), ExploitVerified=vulnerabiliy.get("exploitVerified"), ExposedMachines=vulnerabiliy.get("exposedMachines"), FirstDetected=vulnerabiliy.get("firstDetected"), PublicExploit=vulnerabiliy.get("publicExploit"), PublishedOn=vulnerabiliy.get("publishedOn"), Severity=vulnerabiliy.get("severity"), Tags=vulnerabiliy.get("tags"), UpdatedOn=vulnerabiliy.get("updatedOn"), ) return vulnerability_data def get_file_statistics_command(client: MsClient, args: dict) -> CommandResults: """Retrieves the statistics on the given file. Returns: CommandResults. """ file_hash = args.get("file_hash", "") response = client.get_file_statistics(file_hash) file_stats = FileStatisticsAPIParser.from_raw_response(response) return CommandResults( outputs_prefix="MicrosoftATP.FileStatistics", outputs_key_field="Sha1", indicator=file_stats.to_file_indicator(file_hash), readable_output=file_stats.to_human_readable(file_hash), outputs=file_stats.to_context_output(), raw_response=response, ) def get_file_alerts_command(client: MsClient, args: dict): """Retrieves a collection of Alerts related to a given file hash. Returns: (str, dict, dict). Human readable, context, raw response """ headers = [ "ID", "Title", "Description", "IncidentID", "Severity", "Status", "Classification", "Category", "ThreatFamilyName", "MachineID", ] file_sha1 = args.get("file_hash") response = client.get_file_alerts(file_sha1) alerts_list = get_alerts_list(response) hr = tableToMarkdown(f"File {file_sha1} related alerts Info:", alerts_list, headers=headers, removeNull=True) context_output = {"Sha1": file_sha1, "Alerts": alerts_list} ec = {"MicrosoftATP.FileAlert(val.Sha1 === obj.Sha1)": context_output} return hr, ec, response def get_ip_statistics_command(client: MsClient, args: dict): """Retrieves the statistics on the given IP. Returns: (str, dict, dict). Human readable, context, raw response """ ip = args.get("ip") response = client.get_ip_statistics(ip) ip_statistics = get_ip_statistics_context(response) hr = tableToMarkdown(f"Statistics on {ip} IP:", ip_statistics, removeNull=True) context_output = {"IPAddress": ip, "Statistics": ip_statistics} ec = {"MicrosoftATP.IPStatistics(val.IPAddress === obj.IPAddress)": context_output} return hr, ec, response def get_ip_statistics_context(ip_statistics_response): """Gets the IP statistics response and returns it in context format. Returns: (dict). IP statistics context """ ip_statistics = assign_params( OrgPrevalence=ip_statistics_response.get("orgPrevalence"), OrgFirstSeen=ip_statistics_response.get("orgFirstSeen"), OrgLastSeen=ip_statistics_response.get("orgLastSeen"), ) return ip_statistics def get_ip_alerts_command(client: MsClient, args: dict): """Retrieves a collection of Alerts related to a given IP. Returns: (str, dict, dict). Human readable, context, raw response """ headers = [ "ID", "Title", "Description", "IncidentID", "Severity", "Status", "Classification", "Category", "ThreatFamilyName", "MachineID", ] ip = args.get("ip") response = client.get_ip_alerts(ip) alerts_list = get_alerts_list(response) human_readable = tableToMarkdown(f"IP {ip} related alerts Info:", alerts_list, headers=headers, removeNull=True) context_output = {"IPAddress": ip, "Alerts": alerts_list} entry_context = {"MicrosoftATP.IPAlert(val.IPAddress === obj.IPAddress)": context_output} return human_readable, entry_context, response def get_user_alerts_command(client: MsClient, args: dict): """Retrieves a collection of Alerts related to a given user ID. Returns: (str, dict, dict). Human readable, context, raw response """ headers = [ "ID", "Title", "Description", "IncidentID", "Severity", "Status", "Classification", "Category", "ThreatFamilyName", "MachineID", ] username = args.get("username") response = client.get_user_alerts(username) alerts_list = get_alerts_list(response) human_readable = tableToMarkdown(f"User {username} related alerts Info:", alerts_list, headers=headers, removeNull=True) context_output = {"Username": username, "Alerts": alerts_list} entry_context = {"MicrosoftATP.UserAlert(val.Username === obj.Username)": context_output} return human_readable, entry_context, response def get_alert_by_id_command(client: MsClient, args: dict) -> CommandResults: """Retrieves a specific alert by the given ID. Returns: CommandResults. """ headers = [ "ID", "Title", "Description", "IncidentID", "Severity", "Status", "Classification", "Category", "ThreatFamilyName", "MachineID", ] alert_ids = remove_duplicates_from_list_arg(args, "alert_ids") raw_response = [] alert_outputs = [] failed_alerts = {} # if we got an error, we will return the machine ids that failed not_found_ids = [] for alert in alert_ids: try: alert_response = client.get_alert_by_id(alert) alerts_data = get_alert_data(alert_response) raw_response.append(alert_response) alert_outputs.append(alerts_data) except NotFoundError: # in case the error is not found alert id, we want to return "No entries" not_found_ids.append(alert) continue except Exception as e: failed_alerts[alert] = e continue human_readable = tableToMarkdown( f"{INTEGRATION_NAME} Alerts Info for IDs {alert_ids}:", alert_outputs, headers=headers, removeNull=True ) human_readable += add_error_message(failed_alerts, alert_ids) human_readable += not_found_message(not_found_ids) return CommandResults( outputs_prefix="MicrosoftATP.Alert", outputs=alert_outputs, readable_output=human_readable, raw_response=raw_response, outputs_key_field="ID", ) def get_user_machine_command(client: MsClient, args: dict): """Retrieves a collection of machines related to a given user ID. Returns: (str, dict, dict). Human readable, context, raw response """ headers = [ "ID", "ComputerDNSName", "OSPlatform", "LastIPAddress", "LastExternalIPAddress", "HealthStatus", "RiskScore", "ExposureLevel", ] username = args.get("username") response = client.get_user_machines(username) machines_list = get_machines_list(response) human_readable = tableToMarkdown( f"Machines that are related to user {username}:", machines_list, headers=headers, removeNull=True ) context_output = {"Username": username, "Machines": machines_list} entry_context = {"MicrosoftATP.UserMachine(val.Username === obj.Username)": context_output} return human_readable, entry_context, response def add_remove_machine_tag_command(client: MsClient, args: dict): """Adds or remove tag to a specific Machine. Returns: (str, dict, dict). Human readable, context, raw response """ headers = [ "ID", "ComputerDNSName", "OSPlatform", "LastIpAddress", "LastExternalIPAddress", "HealthStatus", "RiskScore", "ExposureLevel", "MachineTags", ] machine_id = args.get("machine_id") action = args.get("action") tag = args.get("tag") response = client.add_remove_machine_tag(machine_id, action, tag) machine_data = get_machine_data(response) human_readable = tableToMarkdown(f"Succeed to {action} tag to {machine_id}:", machine_data, headers=headers, removeNull=True) entry_context = {"MicrosoftATP.Machine(val.ID === obj.ID)": machine_data} return human_readable, entry_context, response def fetch_incidents(client: MsClient, last_run, fetch_evidence): demisto.debug("Microsoft-ATP - Start fetching") first_fetch_time = dateparser.parse( client.alert_time_to_fetch, settings={"RETURN_AS_TIMEZONE_AWARE": True, "TIMEZONE": "UTC"} ) demisto.debug(f"First fetch time: {first_fetch_time}") if last_run: demisto.debug(f"Microsoft-ATP - Last run: {json.dumps(last_run)}") last_fetch_time = last_run.get("last_alert_fetched_time") last_fetch_time = datetime.strftime(parse_date_string(last_fetch_time) + timedelta(milliseconds=1), TIME_FORMAT) # handling old version of time format: if not last_fetch_time.endswith("Z"): last_fetch_time = last_fetch_time + "Z" else: last_fetch_time = datetime.strftime(first_fetch_time, TIME_FORMAT) # type: ignore demisto.debug(f"Microsoft-ATP - Last run: {last_fetch_time}") latest_created_time = dateparser.parse(last_fetch_time, settings={"RETURN_AS_TIMEZONE_AWARE": True, "TIMEZONE": "UTC"}) demisto.debug(f"latest_created_time: {latest_created_time}") params = _get_incidents_query_params(client, fetch_evidence, last_fetch_time) demisto.debug(f"Microsoft-ATP - Query sent to the server: {params}") incidents = [] # get_alerts: try: alerts = client.list_alerts_by_params(params=params, overwrite_rate_limit_retry=True)["value"] except DemistoException as err: big_query_err_msg = ( "Verify that the server URL parameter is correct and that you have access to the server from your host." ) if str(err).startswith(big_query_err_msg): demisto.debug(f"Query crashed API, probably due to a big response. Params sent to query: {params}") raise Exception( f"Failed to fetch {client.max_alerts_to_fetch} alerts. This may caused due to large amount of alert. " f"Try using a lower limit." ) demisto.debug(f"Query crashed API. Params sent to query: {params}") raise err skipped_incidents = 0 for alert in alerts: alert_time = dateparser.parse(alert["alertCreationTime"], settings={"RETURN_AS_TIMEZONE_AWARE": True, "TIMEZONE": "UTC"}) # to prevent duplicates, adding incidents with creation_time > last fetched incident if last_fetch_time: parsed = dateparser.parse(last_fetch_time, settings={"RETURN_AS_TIMEZONE_AWARE": True, "TIMEZONE": "UTC"}) demisto.debug(f'Checking alert {alert["id"]} with parsed time {parsed}. last alert time is {alert_time}') if alert_time <= parsed: # type: ignore skipped_incidents += 1 demisto.debug( f'Microsoft - ATP - Skipping incident with id={alert["id"]} with time {alert_time} because its' ' creation time is smaller than the last fetch.' ) continue demisto.debug(f'Adding alert {alert["id"]}') incidents.append( { "rawJSON": json.dumps(alert), "name": f'{INTEGRATION_NAME} Alert {alert["id"]}', "occurred": alert["alertCreationTime"], "dbotMirrorId": alert["id"], } ) # Update last run and add incident if the incident is newer than last fetch if alert_time > latest_created_time: # type: ignore demisto.debug(f"Updating last created time to {alert_time}") latest_created_time = alert_time # type: ignore # last alert is the newest as we ordered by it ascending demisto.debug(f"Microsoft-ATP - Next run after incidents fetching: {latest_created_time}") demisto.debug(f"Microsoft-ATP - Number of incidents before filtering: {len(alerts)}") demisto.debug(f"Microsoft-ATP - Number of incidents after filtering: {len(incidents)}") demisto.debug(f"Microsoft-ATP - Number of incidents skipped: {skipped_incidents}") last_run["last_alert_fetched_time"] = datetime.strftime(latest_created_time, TIME_FORMAT) # type: ignore return incidents, last_run def _get_incidents_query_params(client, fetch_evidence, last_fetch_time): filter_query = f"alertCreationTime+gt+{last_fetch_time}" if client.alert_detectionsource_to_fetch: sources = argToList(client.alert_detectionsource_to_fetch) source_filter_list = [f"detectionSource+eq+'{DETECTION_SOURCE_TO_API_VALUE[source]}'" for source in sources] if len(source_filter_list) > 1: source_filter_list = [f"({x})" for x in source_filter_list] filter_query = filter_query + " and (" + " or ".join(source_filter_list) + ")" if client.alert_status_to_fetch: statuses = argToList(client.alert_status_to_fetch) status_filter_list = [f"status+eq+'{status}'" for status in statuses] if len(status_filter_list) > 1: status_filter_list = [f"({x})" for x in status_filter_list] filter_query = filter_query + " and (" + " or ".join(status_filter_list) + ")" if client.alert_severities_to_fetch: severities = argToList(client.alert_severities_to_fetch) severities_filter_list = [f"severity+eq+'{severity}'" for severity in severities] if len(severities_filter_list) > 1: severities_filter_list = [f"({x})" for x in severities_filter_list] filter_query = filter_query + " and (" + " or ".join(severities_filter_list) + ")" params = {"$filter": filter_query} params["$orderby"] = "alertCreationTime asc" if fetch_evidence: params["$expand"] = "evidence" params["$top"] = client.max_alerts_to_fetch return params def create_filter_alerts_creation_time(last_alert_fetched_time): """Create filter with the last alert fetched time to send in the request. Args: last_alert_fetched_time(date): Last date and time of alert that been fetched Returns: (str). The filter of alerts creation time that will be send in the alerts list API request """ filter_alerts_creation_time = f"alertCreationTime+gt+{last_alert_fetched_time.isoformat()}" if not filter_alerts_creation_time.endswith("Z"): filter_alerts_creation_time = filter_alerts_creation_time + "Z" return filter_alerts_creation_time def all_alerts_to_incidents(alerts, latest_creation_time, existing_ids, alert_status_to_fetch, alert_severities_to_fetch): """Gets the alerts list and convert it to incidents. Args: alerts(list): List of alerts filtered by the first_fetch_timestamp parameter latest_creation_time(date): Last date and time of alert that been fetched existing_ids(list): List of alerts IDs that already been fetched alert_status_to_fetch(str): Status to filter out alerts for fetching as incidents. alert_severities_to_fetch(str): Severity to filter out alerts for fetching as incidents. Returns:(list, list, date). Incidents list, new alerts IDs list, latest alert creation time """ incidents = [] new_ids = [] for alert in alerts: alert_creation_time_for_incident = parse(alert["alertCreationTime"]) reformatted_alert_creation_time_for_incident = aware_timestamp_to_naive_timestamp(alert_creation_time_for_incident) if should_fetch_alert(alert, existing_ids, alert_status_to_fetch, alert_severities_to_fetch): incident = alert_to_incident(alert, reformatted_alert_creation_time_for_incident) incidents.append(incident) if reformatted_alert_creation_time_for_incident == latest_creation_time: new_ids.append(alert["id"]) if reformatted_alert_creation_time_for_incident > latest_creation_time: latest_creation_time = reformatted_alert_creation_time_for_incident new_ids = [alert["id"]] if not new_ids: new_ids = existing_ids return incidents, new_ids, latest_creation_time def aware_timestamp_to_naive_timestamp(aware_timestamp): """Gets aware timestamp and reformatting it to naive timestamp Args: aware_timestamp(date): The alert creation time after parse to aware timestamp Returns:(date). Naive timestamp for alert creation time """ iso_aware = aware_timestamp.isoformat() # Deal with timestamp like: 2020-03-26T17:24:58.441093 if "." in iso_aware: iso_aware = iso_aware.split(".")[0] # Deal with timestamp like: 2020-03-14T22:11:20+0000 elif "+" in iso_aware: iso_aware = iso_aware.split("+")[0] return datetime.strptime(iso_aware, "%Y-%m-%dT%H:%M:%S") def should_fetch_alert(alert, existing_ids, alert_status_to_fetch, alert_severities_to_fetch): """Check the alert to see if it's data stands by the conditions. Args: alert (dict): The alert data existing_ids (list): The existing alert's ids list alert_status_to_fetch(str): Status to filter out alerts for fetching as incidents. alert_severities_to_fetch(str): Severity to filter out alerts for fetching as incidents. Returns: True - if the alert is according to the conditions, else False """ alert_status = alert["status"] alert_severity = alert["severity"] return ( alert_status in alert_status_to_fetch and alert_severity in str(alert_severities_to_fetch) and alert["id"] not in existing_ids ) def get_last_alert_fetched_time(last_run, alert_time_to_fetch): """Gets fetch last run and returns the last alert fetch time. Returns: (date). The date and time of the last alert that been fetched """ if last_run and last_run["last_alert_fetched_time"]: last_alert_fetched_time = datetime.strptime(last_run["last_alert_fetched_time"], "%Y-%m-%dT%H:%M:%S") else: last_alert_fetched_time, _ = parse_date_range( date_range=alert_time_to_fetch, date_format="%Y-%m-%dT%H:%M:%S", utc=False, to_timestamp=False ) last_alert_fetched_time = datetime.strptime(str(last_alert_fetched_time), "%Y-%m-%dT%H:%M:%S") return last_alert_fetched_time def list_indicators_command(client: MsClient, args: dict[str, str]) -> tuple[str, dict | None, list | None]: """ Args: client: MsClient args: arguments from CortexSOAR. May include 'indicator_id' and 'page_size' Returns: human_readable, outputs. """ limit = int(args.get("limit", 50)) raw_response = client.list_indicators(args.get("indicator_id"), args.get("page_size", "50"), limit) raw_response = raw_response[:limit] if raw_response: indicators = [] for item in raw_response: item["severity"] = NUMBER_TO_SEVERITY.get(item["severity"]) indicators.append(item) human_readable = tableToMarkdown( "Microsoft Defender ATP Indicators:", indicators, headers=[ "id", "action", "threatType", "severity", "fileName", "fileHashType", "fileHashValue", "domainName", "networkIPv4", "url", ], removeNull=True, ) outputs = {"MicrosoftATP.Indicators(val.id == obj.id)": indicators} std_outputs = build_std_output(indicators) outputs.update(std_outputs) return human_readable, outputs, indicators else: return "No indicators found", None, None def create_indicator_command(client: MsClient, args: dict, specific_args: dict) -> dict: """Adds required arguments to indicator (arguments that must be in every create call). Args: client: MsClient args: arguments from CortexSOAR. Must include the following keys: - action - description - expiration_time - threat_type specific_args: file, email or network object. Returns: A response from API. Raises: AssertionError: For some arguments. Documentation: https://docs.microsoft.com/en-us/graph/api/resources/tiindicator?view=graph-rest-beta#properties """ action = args.get("action", "") description = args.get("description", "") assert 1 <= len(description) <= 100, "The description argument must contain at least 1 character and not more than 100" expiration_time = get_future_time(args.get("expiration_time", "")) threat_type = args.get("threat_type", "") tlp_level = args.get("tlp_level", "") confidence = args.get("confidence", None) try: if confidence is not None: confidence = int(confidence) assert 0 <= confidence <= 100, "The confidence argument must be between 0 and 100" except ValueError: raise DemistoException("The confidence argument must be an integer.") severity = SEVERITY_TO_NUMBER.get(args.get("severity", "Informational")) tags = argToList(args.get("tags")) body = assign_params( action=action, description=description, expirationDateTime=expiration_time, targetProduct="Microsoft Defender ATP", threatType=threat_type, tlpLevel=tlp_level, confidence=confidence, severity=severity, tags=tags, ) body.update(specific_args) return client.create_indicator(body) def create_file_indicator_command(client: MsClient, args: dict) -> tuple[str, dict, dict]: """Creates a file indicator Args: client: MsClient args: arguments from CortexSOAR. Should contain a file observable: - https://docs.microsoft.com/en-us/graph/api/resources/tiindicator?view=graph-rest-beta#indicator-observables---file Returns: human readable, outputs, raw response Raises: AssertionError: If no file arguments. """ file_object = assign_params( fileCompileDateTime=args.get("file_compile_date_time"), fileCreatedDateTime=args.get("file_created_date_time"), fileHashType=args.get("file_hash_type"), fileHashValue=args.get("file_hash_value"), fileMutexName=args.get("file_mutex_name"), fileName=args.get("file_name"), filePacker=args.get("file_packer"), filePath=args.get("file_path"), fileSize=args.get("file_size"), fileType=args.get("file_type"), ) assert file_object, "Must supply at least one file attribute." raw_response = create_indicator_command(client, args, file_object) indicator = raw_response.copy() indicator["severity"] = NUMBER_TO_SEVERITY.get(indicator["severity"]) human_readable = tableToMarkdown( f'Indicator {indicator.get("id")} was successfully created:', indicator, headers=[ "id", "action", "threatType", "severity", "fileName", "fileHashType", "fileHashValue", "domainName", "networkIPv4", "url", ], removeNull=True, ) outputs = {"MicrosoftATP.Indicators(val.id == obj.id)": indicator} std_outputs = build_std_output(indicator) outputs.update(std_outputs) return human_readable, outputs, raw_response def create_network_indicator_command(client, args) -> tuple[str, dict, dict]: """Creates a network indicator Args: client: MsClient args: arguments from CortexSOAR. Should contain a network observable: - https://docs.microsoft.com/en-us/graph/api/resources/tiindicator?view=graph-rest-betaindicator-observables---network Returns: human readable, outputs, raw response Raises: AssertionError: If no file arguments. """ # noqa: E501 network_object = assign_params( domainName=args.get("domain_name"), networkCidrBlock=args.get("network_cidr_block"), networkDestinationAsn=args.get("network_destination_asn"), networkDestinationCidrBlock=args.get("network_destination_cidr_block"), networkDestinationIPv4=args.get("network_destination_ipv4"), networkDestinationIPv6=args.get("network_destination_ipv6"), networkDestinationPort=args.get("network_destination_port"), networkIPv4=args.get("network_ipv4"), networkIPv6=args.get("network_ipv6"), networkPort=args.get("network_port"), networkProtocol=args.get("network_protocol"), networkSourceAsn=args.get("network_source_asn"), networkSourceCidrBlock=args.get("network_source_cidr_block"), networkSourceIPv4=args.get("network_source_ipv4"), networkSourceIPv6=args.get("network_source_ipv6"), networkSourcePort=args.get("network_source_port"), userAgent=args.get("user_agent"), url=args.get("url"), ) assert network_object, "Must supply at least one network attribute." raw_response = create_indicator_command(client, args, network_object) indicator = raw_response.copy() indicator["severity"] = NUMBER_TO_SEVERITY.get(indicator["severity"]) human_readable = tableToMarkdown( f'Indicator {indicator.get("id")} was successfully created:', indicator, headers=[ "id", "action", "threatType", "severity", "fileName", "fileHashType", "fileHashValue", "domainName", "networkIPv4", "url", ], removeNull=True, ) outputs = {"MicrosoftATP.Indicators(val.id == obj.id)": indicator} std_outputs = build_std_output(indicator) outputs.update(std_outputs) return human_readable, outputs, raw_response def update_indicator_command(client: MsClient, args: dict) -> tuple[str, dict, dict]: """Updates an indicator Args: client: MsClient args: arguments from CortexSOAR. Must contains 'indicator_id' and 'expiration_time' Returns: human readable, outputs """ indicator_id = args.get("indicator_id", "") severity = SEVERITY_TO_NUMBER.get(args.get("severity", "Informational")) expiration_time = get_future_time(args.get("expiration_time", "")) description = args.get("description") if description is not None: assert 1 <= len(description) <= 100, "The description argument must contain at least 1 character and not more than 100" raw_response = client.update_indicator( indicator_id=indicator_id, expiration_date_time=expiration_time, description=description, severity=severity ) indicator = raw_response.copy() indicator["severity"] = NUMBER_TO_SEVERITY.get(indicator["severity"]) human_readable = tableToMarkdown(f"Indicator ID: {indicator_id} was updated successfully.", indicator, removeNull=True) outputs = {"MicrosoftATP.Indicators(val.id == obj.id)": indicator} std_outputs = build_std_output(indicator) outputs.update(std_outputs) return human_readable, outputs, raw_response def delete_indicator_command(client: MsClient, args: dict) -> str: """Deletes an indicator Args: client: MsClient args: arguments from CortexSOAR. Must contains 'indicator_id' Returns: human readable """ indicator_id = args.get("indicator_id", "") client.delete_indicator(indicator_id, client.get_graph_indicator_endpoint()) return f"Indicator ID: {indicator_id} was successfully deleted" def sc_delete_indicator_command(client: MsClient, args: dict[str, str]) -> CommandResults: """Deletes an indicator https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/delete-ti-indicator-by-id?view=o365-worldwide Args: client: MsClient args: arguments from CortexSOAR. Must contains 'indicator_id' Returns: An indication of whether the indicator was deleted successfully. """ indicator_id = args["indicator_id"] client.delete_indicator(indicator_id, client.get_security_center_indicator_endpoint(), use_security_center=True) return CommandResults(readable_output=f"Indicator ID: {indicator_id} was successfully deleted") def sc_create_update_indicator_command(client: MsClient, args: dict[str, str]) -> CommandResults: """Updates an indicator if exists, if does not exist, create new one Note: CIDR notation for IPs is not supported. Args: client: MsClient args: arguments from CortexSOAR. Must contains 'indicator_value', 'indicator_type','indicator_description', 'indicator_title', and 'action'. """ indicator_value = args["indicator_value"] indicator_type = args["indicator_type"] action = args["action"] severity = args.get("severity") expiration_time = get_future_time(args["expiration_time"]) if args.get("expiration_time") else None indicator_description = args["indicator_description"] indicator_title = args["indicator_title"] indicator_application = args.get("indicator_application", "") recommended_actions = args.get("recommended_actions", "") rbac_group_names = argToList(args.get("rbac_group_names", [])) generate_alert = argToBoolean(args.get("generate_alert", True)) indicator = client.create_update_indicator_security_center_api( indicator_value=indicator_value, expiration_date_time=expiration_time, description=indicator_description, severity=severity, indicator_type=indicator_type, action=action, indicator_title=indicator_title, indicator_application=indicator_application, recommended_actions=recommended_actions, rbac_group_names=rbac_group_names, generate_alert=generate_alert, ) if indicator: indicator_value = indicator.get("indicatorValue") # type:ignore dbot_indicator = get_indicator_dbot_object(indicator) human_readable = tableToMarkdown( f"Indicator {indicator_value} was updated successfully.", indicator, headers=list(SC_INDICATORS_HEADERS), removeNull=True, ) return CommandResults( outputs=indicator, indicator=dbot_indicator, readable_output=human_readable, outputs_key_field="id", outputs_prefix="MicrosoftATP.Indicators", ) else: return CommandResults(readable_output=f"Indicator {indicator_value} was NOT updated.") def sc_update_batch_indicators_command(client: MsClient, args: dict[str, str]): # -> CommandResults: """Updates batch of indicators. If an indicator exists it will be updated. Otherwise, will create new one Note: CIDR notation for IPs is not supported. Args: client: MsClient args: arguments from CortexSOAR. Must contains 'indicator_batch' as a JSON file. """ indicator_batch = args.get("indicator_batch", "") headers = ["ID", "Value", "IsFailed", "FailureReason"] try: batch_json = json.loads(indicator_batch) except JSONDecodeError as e: raise DemistoException(f"{INTEGRATION_NAME}: The `indicator_batch` argument is not a valid json, {e}.") all_indicators = client.create_update_indicator_batch_security_center_api({"Indicators": batch_json}) outputs = parse_indicator_batch_response(all_indicators) if outputs: human_readable = tableToMarkdown("Indicators updated successfully.", outputs, headers=headers, removeNull=True) return CommandResults( outputs=outputs, readable_output=human_readable, outputs_key_field="id", outputs_prefix="MicrosoftATP.Indicators" ) return CommandResults(readable_output="Indicators were not updated.") def parse_indicator_batch_response(indicators_response): parsed_response = [] if indicators_response and indicators_response.get("value"): indicators = indicators_response.get("value") for indicator in indicators: parsed_response.append( { "ID": indicator.get("id"), "Value": indicator.get("indicator"), "IsFailed": indicator.get("isFailed"), "FailureReason": indicator.get("failureReason"), } ) return parsed_response def sc_list_indicators_command(client: MsClient, args: dict[str, str]) -> CommandResults | list[CommandResults]: """ https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/get-ti-indicators-collection?view=o365-worldwide Args: client: MsClient args: arguments from CortexSOAR. May include 'indicator_id' and 'page_size' Returns: human_readable, outputs. """ limit = arg_to_number(args.get("limit", 50)) or 50 skip = arg_to_number(args.get("skip", 0)) or 0 raw_response = client.sc_list_indicators( args.get("indicator_id"), limit, skip, args.get("indicator_title"), args.get("indicator_value"), args.get("indicator_type"), ) if raw_response: command_results = [] for indicator in raw_response: indicator_value = indicator.get("indicatorValue") dbot_indicator = get_indicator_dbot_object(indicator) human_readable = tableToMarkdown( f"Results found in {INTEGRATION_NAME} SC for value: {indicator_value}", indicator, headers=list(SC_INDICATORS_HEADERS), removeNull=True, ) command_results.append( CommandResults( outputs=indicator, indicator=dbot_indicator, readable_output=human_readable, outputs_key_field="id", outputs_prefix="MicrosoftATP.Indicators", ) ) return command_results else: return CommandResults(readable_output="No indicators found") def lateral_movement_evidence_command(client, args): # pragma: no cover # prepare query timeout = int(args.pop("timeout", 10)) time_range = args.pop("time_range", None) query_purpose = args.pop("query_purpose") page = int(args.get("page", 1)) limit = int(args.get("limit", 50)) show_query = argToBoolean(args.pop("show_query", False)) query_args = assign_params( limit=args.get("limit"), query_operation=args.get("query_operation"), page=args.get("page"), device_name=args.get("device_name"), file_name=args.get("file_name"), sha1=args.get("sha1"), sha256=args.get("sha256"), md5=args.get("md5"), device_id=args.get("device_id"), remote_ip_count=args.get("remote_ip_count"), ) query_builder = HuntingQueryBuilder.LateralMovementEvidence(**query_args) query_options = { "network_connections": query_builder.build_network_connections_query, "smb_connections": query_builder.build_smb_connections_query, "credential_dumping": query_builder.build_credential_dumping_query, "management_connection": query_builder.build_management_connection_query, } if query_purpose not in query_options: raise DemistoException(f"Unsupported query_purpose: {query_purpose}.") query = query_options[query_purpose]() # send request + handle result response = client.get_advanced_hunting(query, timeout, time_range) results = response.get("Results") if isinstance(results, list) and page > 1: results = results[(page - 1) * limit : limit * page] readable_output = tableToMarkdown(f"Lateral Movement Evidence Hunt ({query_purpose}) Results", results, removeNull=True) if show_query: readable_output = f"### The Query:\n{query}\n{readable_output}" return CommandResults( readable_output=readable_output, outputs_prefix=f"MicrosoftATP.HuntLateralMovementEvidence.Result.{query_purpose}", outputs=results, ) def persistence_evidence_command(client, args): # pragma: no cover # prepare query timeout = int(args.pop("timeout", 10)) time_range = args.pop("time_range", None) query_purpose = args.get("query_purpose") show_query = argToBoolean(args.pop("show_query", False)) quey_args = assign_params( limit=args.get("limit"), query_operation=args.get("query_operation"), query_purpose=args.get("query_purpose"), page=args.get("page"), device_name=args.get("device_name"), file_name=args.get("file_name"), sha1=args.get("sha1"), sha256=args.get("sha256"), md5=args.get("md5"), device_id=args.get("device_id"), process_cmd=args.get("process_cmd"), ) query_builder = HuntingQueryBuilder.PersistenceEvidence(**quey_args) query_options = { "scheduled_job": query_builder.build_scheduled_job_query, "registry_entry": query_builder.build_registry_entry_query, "startup_folder_changes": query_builder.build_startup_folder_changes_query, "new_service_created": query_builder.build_new_service_created_query, "service_updated": query_builder.build_service_updated_query, "file_replaced": query_builder.build_file_replaced_query, "new_user": query_builder.build_new_user_query, "new_group": query_builder.build_new_group_query, "group_user_change": query_builder.build_group_user_change_query, "local_firewall_change": query_builder.build_local_firewall_change_query, "host_file_change": query_builder.build_host_file_change_query, } if query_purpose not in query_options: raise DemistoException(f"Unsupported query_purpose: {query_purpose}.") query = query_options[query_purpose]() # send request + handle result response = client.get_advanced_hunting(query, timeout, time_range) results = response.get("Results") readable_output = tableToMarkdown(f"Persistence EvidenceHunt Hunt ({query_purpose}) Results", results, removeNull=True) if show_query: readable_output = f"### The Query:\n{query}\n{readable_output}" return CommandResults( readable_output=readable_output, outputs_prefix=f"MicrosoftATP.HuntPersistenceEvidence.Result.{query_purpose}", outputs=results, ) def file_origin_command(client, args): # pragma: no cover # prepare query timeout = int(args.pop("timeout", 10)) time_range = args.pop("time_range", None) page = int(args.get("page", 1)) limit = int(args.get("limit", 50)) show_query = argToBoolean(args.pop("show_query", False)) quey_params = assign_params( limit=args.get("limit"), query_operation=args.get("query_operation"), page=args.get("page"), device_name=args.get("device_name"), file_name=args.get("file_name"), sha1=args.get("sha1"), sha256=args.get("sha256"), md5=args.get("md5"), device_id=args.get("device_id"), ) query_builder = HuntingQueryBuilder.FileOrigin(**quey_params) query = query_builder.build_file_origin_query() # send request + handle result response = client.get_advanced_hunting(query, timeout, time_range) results = response.get("Results") if isinstance(results, list) and page > 1: results = results[(page - 1) * limit : limit * page] readable_output = tableToMarkdown("File Origin Hunt Results", results, removeNull=True) if show_query: readable_output = f"### The Query:\n{query}\n{readable_output}" return CommandResults(readable_output=readable_output, outputs_prefix="MicrosoftATP.HuntFileOrigin.Result", outputs=results) def process_details_command(client, args): # pragma: no cover # prepare query timeout = int(args.pop("timeout", 10)) time_range = args.pop("time_range", None) query_purpose = args.get("query_purpose") page = int(args.get("page", 1)) limit = int(args.get("limit", 50)) show_query = argToBoolean(args.pop("show_query", False)) query_params = assign_params( limit=args.get("limit"), query_operation=args.get("query_operation"), page=args.get("page"), device_name=args.get("device_name"), file_name=args.get("file_name"), sha1=args.get("sha1"), sha256=args.get("sha256"), md5=args.get("md5"), device_id=args.get("device_id"), query_purpose=args.get("query_purpose"), ) query_builder = HuntingQueryBuilder.ProcessDetails(**query_params) query_options = { "parent_process": query_builder.build_parent_process_query, "grandparent_process": query_builder.build_grandparent_process_query, "process_details": query_builder.build_process_details_query, "beaconing_evidence": query_builder.build_beaconing_evidence_query, "powershell_execution_unsigned_files": query_builder.build_powershell_execution_unsigned_files_query, "process_excecution_powershell": query_builder.build_process_excecution_powershell_query, } if query_purpose not in query_options: raise DemistoException(f"Unsupported query_purpose: {query_purpose}.") query = query_options[query_purpose]() # send request + handle result response = client.get_advanced_hunting(query, timeout, time_range) results = response.get("Results") if isinstance(results, list) and page > 1: results = results[(page - 1) * limit : limit * page] readable_output = tableToMarkdown(f"Process Details Hunt ({query_purpose}) Results", results, removeNull=True) if show_query: readable_output = f"### The Query:\n{query}\n{readable_output}" return CommandResults( readable_output=readable_output, outputs_prefix=f"MicrosoftATP.HuntProcessDetails.Result.{query_purpose}", outputs=results ) def network_connections_command(client, args): # pragma: no cover # prepare query timeout = int(args.pop("timeout", 10)) time_range = args.pop("time_range", None) query_purpose = args.get("query_purpose") page = int(args.get("page", 1)) limit = int(args.get("limit", 50)) show_query = argToBoolean(args.pop("show_query", False)) query_params = assign_params( limit=args.get("limit"), query_operation=args.get("query_operation"), query_purpose=args.get("query_purpose"), page=args.get("page"), device_name=args.get("device_name"), file_name=args.get("file_name"), sha1=args.get("sha1"), sha256=args.get("sha256"), md5=args.get("md5"), device_id=args.get("device_id"), ) query_builder = HuntingQueryBuilder.NetworkConnections(**query_params) query_options = { "external_addresses": query_builder.build_external_addresses_query, "dns_query": query_builder.build_dns_query, "encoded_commands": query_builder.build_encoded_commands_query, } if query_purpose not in query_options: raise DemistoException(f"Unsupported query_purpose: {query_purpose}.") query = query_options[query_purpose]() # send request + handle result response = client.get_advanced_hunting(query, timeout, time_range) results = response.get("Results") if isinstance(results, list) and page > 1: results = results[(page - 1) * limit : limit * page] readable_output = tableToMarkdown(f"Network Connections Hunt ({query_purpose}) Results", results, removeNull=True) if show_query: readable_output = f"### The Query:\n{query}\n{readable_output}" return CommandResults( readable_output=readable_output, outputs_prefix=f"MicrosoftATP.HuntNetworkConnections.Result.{query_purpose}", outputs=results, ) def privilege_escalation_command(client, args): # pragma: no cover # prepare query timeout = int(args.pop("timeout", 10)) time_range = args.pop("time_range", None) page = int(args.get("page", 1)) limit = int(args.get("limit", 50)) show_query = argToBoolean(args.pop("show_query", False)) quey_args = assign_params( limit=args.get("limit"), query_operation=args.get("query_operation"), page=args.get("page"), device_name=args.get("device_name"), device_id=args.get("device_id"), ) query_builder = HuntingQueryBuilder.PrivilegeEscalation(**quey_args) query = query_builder.build_query() # send request + handle result response = client.get_advanced_hunting(query, timeout, time_range) results = response.get("Results") if isinstance(results, list) and page > 1: results = results[(page - 1) * limit : limit * page] readable_output = tableToMarkdown("Privilege Escalation Hunt Results", results, removeNull=True) if show_query: readable_output = f"### The Query:\n{query}\n{readable_output}" return CommandResults( readable_output=readable_output, outputs_prefix="MicrosoftATP.HuntPrivilegeEscalation.Result", outputs=results ) def tampering_command(client, args): # pragma: no cover # prepare query timeout = int(args.pop("timeout", 10)) time_range = args.pop("time_range", None) page = int(args.get("page", 1)) limit = int(args.get("limit", 50)) show_query = argToBoolean(args.pop("show_query", False)) quey_args = assign_params( limit=args.get("limit"), query_operation=args.get("query_operation"), page=args.get("page"), device_name=args.get("device_name"), device_id=args.get("device_id"), ) query_builder = HuntingQueryBuilder.Tampering(**quey_args) query = query_builder.build_query() # send request + handle result response = client.get_advanced_hunting(query, timeout, time_range) results = response.get("Results") if isinstance(results, list) and page > 1: results = results[(page - 1) * limit : limit * page] readable_output = tableToMarkdown("Tampering Hunt Results", results, removeNull=True) if show_query: readable_output = f"### The Query:\n{query}\n{readable_output}" return CommandResults(readable_output=readable_output, outputs_prefix="MicrosoftATP.HuntTampering.Result", outputs=results) def cover_up_command(client, args): # pragma: no cover # prepare query timeout = int(args.pop("timeout", 10)) time_range = args.pop("time_range", None) query_purpose = args.get("query_purpose") page = int(args.get("page", 1)) limit = int(args.get("limit", 50)) show_query = argToBoolean(args.pop("show_query", False)) quey_args = assign_params( limit=args.get("limit"), query_operation=args.get("query_operation"), query_purpose=args.get("query_purpose"), page=args.get("page"), device_name=args.get("device_name"), file_name=args.get("file_name"), sha1=args.get("sha1"), sha256=args.get("sha256"), md5=args.get("md5"), device_id=args.get("device_id"), username=args.get("username"), ) query_builder = HuntingQueryBuilder.CoverUp(**quey_args) query_options = { "file_deleted": query_builder.build_file_deleted_query, "event_log_cleared": query_builder.build_event_log_cleared_query, "compromised_information": query_builder.build_compromised_information_query, "connected_devices": query_builder.build_connected_devices_query, "action_types": query_builder.build_action_types_query, "common_files": query_builder.build_common_files_query, } if query_purpose not in query_options: raise DemistoException(f"Unsupported query_purpose: {query_purpose}.") query = query_options[query_purpose]() # send request + handle result response = client.get_advanced_hunting(query, timeout, time_range) results = response.get("Results") if isinstance(results, list) and page > 1: results = results[(page - 1) * limit : limit * page] readable_output = tableToMarkdown(f"Cover Up Hunt ({query_purpose}) Results", results, removeNull=True) if show_query: readable_output = f"### The Query:\n{query}\n{readable_output}" return CommandResults( readable_output=readable_output, outputs_prefix=f"MicrosoftATP.HuntCoverUp.Result.{query_purpose}", outputs=results ) def test_module(client: MsClient): client.ms_client.http_request(method="GET", url_suffix="/alerts", params={"$top": "1"}, overwrite_rate_limit_retry=True) def get_dbot_indicator(dbot_type, dbot_score, value): if dbot_type == DBotScoreType.FILE: hash_type = get_hash_type(value) if hash_type == "md5": return Common.File(dbot_score=dbot_score, md5=value) if hash_type == "sha1": return Common.File(dbot_score=dbot_score, sha1=value) if hash_type == "sha256": return Common.File(dbot_score=dbot_score, sha256=value) if dbot_type == DBotScoreType.IP: return Common.IP(ip=value, dbot_score=dbot_score) if dbot_type == DBotScoreType.DOMAIN: return Common.Domain(domain=value, dbot_score=dbot_score) if dbot_type == DBotScoreType.URL: return Common.URL(url=value, dbot_score=dbot_score) return None def get_indicator_dbot_object(indicator): indicator_type = INDICATOR_TYPE_TO_DBOT_TYPE.get(indicator.get("indicatorType")) if indicator_type: indicator_value = indicator.get("indicatorValue") dbot = Common.DBotScore(indicator=indicator_value, indicator_type=indicator_type, score=Common.DBotScore.NONE) # type:ignore return get_dbot_indicator(indicator_type, dbot, indicator_value) else: return None def list_machines_by_software_command(client: MsClient, args: dict) -> CommandResults: """Retrieve a list of device references that has the given software installed. Args: client: MsClient. args: dict - arguments from CortexSOAR. Returns: A CommandResults object with a list of machines by software. """ software_id = str(args.get("id")) headers = ["id", "computerDnsName", "osPlatform", "rbacGroupName", "rbacGroupId"] machines_response = client.get_list_machines_by_software(software_id) machines_response_value = machines_response.get("value") human_readable = tableToMarkdown( f"{INTEGRATION_NAME} list machines by software: {software_id}", machines_response_value, headers=headers, removeNull=True ) return CommandResults( outputs_prefix="MicrosoftATP.SoftwareMachine", outputs_key_field="id", outputs=machines_response_value, readable_output=human_readable, raw_response=machines_response, ) def list_software_version_distribution_command(client: MsClient, args: dict) -> CommandResults: """Retrieves a list of your organization's software version distribution. Args: client: MsClient. args: dict - arguments from CortexSOAR. Returns: A CommandResults object with a list of software version distribution. """ software_id = str(args.get("id")) headers = ["version", "installations", "vulnerabilities"] software_version_distribution_response = client.get_list_software_version_distribution(software_id) software_version_distribution_response_value = software_version_distribution_response.get("value") human_readable = tableToMarkdown( f"{INTEGRATION_NAME} software version distribution:", software_version_distribution_response_value, headers=headers, removeNull=True, ) return CommandResults( outputs_prefix="MicrosoftATP.SoftwareVersion", outputs=software_version_distribution_response_value, outputs_key_field=["version", "installations", "vulnerabilities"], readable_output=human_readable, raw_response=software_version_distribution_response, ) def list_missing_kb_by_software_command(client: MsClient, args: dict) -> CommandResults: """Retrieves missing KBs (security updates) by software ID Args: client: MsClient. args: dict - arguments from CortexSOAR. Returns: A CommandResults object with a list of missing kb by software. """ software_id = str(args.get("id")) headers = ["id", "name", "osBuild", "productsNames", "url", "machineMissedOn", "cveAddressed"] missing_kb_by_software_response = client.get_list_missing_kb_by_software(software_id) missing_kb_by_software_response_value = missing_kb_by_software_response.get("value") mark_down_values = add_backslash_infront_of_underscore_list(missing_kb_by_software_response_value) human_readable = tableToMarkdown( f"{INTEGRATION_NAME} missing kb by software: {software_id}", mark_down_values, headers=headers, removeNull=True ) return CommandResults( outputs_prefix="MicrosoftATP.SoftwareKB", outputs_key_field="id", outputs=missing_kb_by_software_response_value, readable_output=human_readable, raw_response=missing_kb_by_software_response, ) def list_vulnerabilities_by_software_command(client: MsClient, args: dict) -> list[CommandResults]: """Retrieves list of vulnerabilities by software. Args: client: MsClient. args: dict - arguments from CortexSOAR. Returns: A CommandResult list with a list of vulnerabilities by software. """ results_list = [] software_id = str(args.get("id")) headers = [ "id", "name", "description", "severity", "cvssV3", "publishedOn", "updatedOn", "exposedMachines", "exploitVerified", "publicExploit", ] vulnerabilities_response = client.get_list_vulnerabilities_by_software(software_id) vulnerabilities_response_value = vulnerabilities_response.get("value") demisto.debug(f"Vulnerabilities Response {vulnerabilities_response_value}") if vulnerabilities_response_value: for cve in vulnerabilities_response_value: cve_id = cve.get("id") cve_indicator = Common.CVE( id=cve_id, cvss=cve.get("cvssV3"), description=cve.get("description"), published=cve.get("publishedOn"), modified=cve.get("updatedOn"), ) human_readable = tableToMarkdown( f"{INTEGRATION_NAME} vulnerability {cve_id} by software: {software_id}", add_backslash_infront_of_underscore_list([cve]), headers=headers, removeNull=True, ) results_list.append( CommandResults( outputs_prefix="MicrosoftATP.SoftwareCVE", outputs_key_field="id", outputs=cve, readable_output=human_readable, raw_response=cve, indicator=cve_indicator, ) ) else: results_list.append(CommandResults(readable_output=f"No vulnerabilities were found for software: {software_id}.")) return results_list def create_filters_conjunction(filters_arg_list: list[str], name: str) -> str: """Create filter conjunction (added 'or' between args) example output: id eq 'id1' or id eq 'id2' Args: filters_arg_list: list[str]. name: str. Returns: A str corresponding to the filter param in a qury. """ query = "" filters_arg_list = list(filter(None, filters_arg_list)) list_length = len(filters_arg_list) if filters_arg_list: for index, list_item in enumerate(filters_arg_list): if index == list_length - 1 or list_length == 1: query = f"{query}{name} eq '{list_item}'" else: query = f"{query}{name} eq '{list_item}' or " demisto.debug(f"Filter conjunction query results: {query} ") return query def add_backslash_infront_of_underscore_list(markdown_data: list[dict] | None) -> list[dict]: """Escape underscores with a backslash in order to show underscores after markdown parsing. Args: markdown_data: list[dict] - list of dicts. Returns: A list of dicts with a backslash before each underscore. """ markdown_data_to_return = [] if markdown_data: for dict_item in markdown_data: dict = {} for k, v in dict_item.items(): if isinstance(v, str): v = str(v.replace("_", r"""\_""")) dict[k] = v markdown_data_to_return.append(dict) return markdown_data_to_return def create_filters_disjunctions(filters_arg_list: list[str]) -> str: """Create filter disjunctions (added 'and' between args) example output: id eq 'id1' and vendor eq 'vendor1' Args: filters_arg_list: list[str]. Returns: A str corresponding to the filter param in a qury. """ query = "" filters_arg_list = list(filter(None, filters_arg_list)) list_length = len(filters_arg_list) if filters_arg_list: for index, list_item in enumerate(filters_arg_list): if list_length == 1 and list_item == "": continue if list_length == 1: query = f"{query}{list_item}" continue if index == list_length - 1: query = f"{query}({list_item})" continue else: query = f"{query}({list_item}) and " demisto.debug(f"Filter disjunctions query results: {query} ") return query def create_filter(args_and_name_list: list[tuple[list[str], str]]) -> str: """Create filter with disjunctions and conjunction according to the API requirements example output: id eq 'id1' and vendor eq 'vendor1' or vendor eq 'vendor2' Args: filters_arg_list: list[str]. Returns: A str corresponding to the filter param in a qury. """ list_for_disjunctions = [] for arg_and_name in args_and_name_list: list_for_disjunctions.append(create_filters_conjunction(arg_and_name[0], arg_and_name[1])) return create_filters_disjunctions(list_for_disjunctions) def list_software_command(client: MsClient, args: dict) -> CommandResults: """Retrieves the organization software inventory. Args: client: MsClient. args: dict - arguments from CortexSOAR. Returns: A CommandResults object. """ software_id = argToList(args.get("id", "")) names = argToList(args.get("name", "")) vendors = argToList(args.get("vendor", "")) limit = args.get("limit", "50") offset = args.get("offset", "0") filter_req = create_filter([(software_id, "id"), (names, "name"), (vendors, "vendor")]) headers = ["id", "name", "vendor", "weaknesses", "activeAlert", "exposedMachines", "installedMachines", "publicExploit"] list_software_response = client.get_list_software(filter_req, limit, offset) list_software_response_value = list_software_response.get("value") mark_down_values = add_backslash_infront_of_underscore_list(list_software_response_value) human_readable = tableToMarkdown(f"{INTEGRATION_NAME} list software:", mark_down_values, headers=headers, removeNull=True) return CommandResults( outputs_prefix="MicrosoftATP.Software", outputs_key_field="id", outputs=list_software_response_value, readable_output=human_readable, raw_response=list_software_response, ) def list_vulnerabilities_by_machine_command(client: MsClient, args: dict) -> list[CommandResults]: """Retrieves a list of all the vulnerabilities affecting the organization per machine. Args: client: MsClient. args: dict - arguments from CortexSOAR. Returns: A CommandResults object. """ machine_id = argToList(args.get("machine_id")) software_id = argToList(args.get("software_id", "")) cve_id = argToList(args.get("cve_id", "")) product_name = argToList(args.get("product_name", "")) product_version = argToList(args.get("product_version", "")) severity = argToList(args.get("severity", "")) product_vendor = argToList(args.get("product_vendor", "")) limit = args.get("limit", "25") offset = args.get("offset", "0") results_list = [] filter_req = create_filter( [ (machine_id, "machineId"), (software_id, "id"), (cve_id, "cveId"), (product_name, "productName"), (product_version, "productVersion"), (severity, "severity"), (product_vendor, "productVendor"), ] ) headers = ["id", "cveId", "machineId", "productName", "productVendor", "productVersion", "severity"] list_vulnerabilities_response = client.get_list_vulnerabilities_by_machine(filter_req, limit, offset) list_vulnerabilities_response_value = list_vulnerabilities_response.get("value") if list_vulnerabilities_response_value: for cve in list_vulnerabilities_response_value: cve_id = cve.get("cveId") cve_indicator = Common.CVE(id=cve_id, cvss="", description="", published="", modified="") human_readable = tableToMarkdown( f"{INTEGRATION_NAME} vulnerability {cve_id}:", add_backslash_infront_of_underscore_list([cve]), headers=headers, removeNull=True, ) results_list.append( CommandResults( outputs_prefix="MicrosoftATP.MachineCVE", outputs_key_field="id", outputs=cve, readable_output=human_readable, raw_response=cve, indicator=cve_indicator, ) ) else: results_list.append(CommandResults(readable_output=f"No vulnerabilities were found for machine: {machine_id}.")) return results_list def create_filter_list_vulnerabilities( id_and_severity: str, name_equal: str, name_contains: str, description: str, published_on: str, cvss: str, updated_on: str ) -> str: """Create a string filter. Args: id_and_severity: str - Id and severity of the vulnerability. name: str - Name of the vulnerability. description: str - Description of the vulnerability. published_on: str - Date when vulnerability was published. cvss: str - CVSS v3 score. updated_on: str - Date when vulnerability was updated. Returns: A string filter. """ filter_query_list = [] if id_and_severity: filter_query_list.append(id_and_severity) if name_contains: filter_query_list.append(f"contains(name, '{name_contains}')") if name_equal: filter_query_list.append(f"name eq '{name_equal}'") if description: filter_query_list.append(f"contains(description, '{description}')") if cvss: filter_query_list.append(f"cvssV3 ge {cvss}") if updated_on: filter_query_list.append(f"updatedOn ge {updated_on}") if published_on: filter_query_list.append(f"publishedOn ge {published_on}") return create_filters_disjunctions(filter_query_list) def date_to_iso_format(date: str) -> str: """Retrieves date string or relational expression to iso format date. Args: date: str - date or relational expression. Returns: A str in ISO format. """ date = dateparser.parse(date) date = date.strftime("%Y-%m-%dT%H:%M:%SZ") if date else "" return date def list_vulnerabilities_command(client: MsClient, args: dict) -> list[CommandResults]: """Retrieves a list of all vulnerabilities. Args: client: MsClient. args: dict - arguments from CortexSOAR. Returns: A CommandResults object. """ id = argToList(args.get("id", "")) severity = argToList(args.get("severity", "")) name_equal = args.get("name_equal", "") name_contains = args.get("name_contains", "") description = args.get("description_contains", "") published_on = date_to_iso_format(args.get("published_on", "")) updated_on = date_to_iso_format(args.get("updated_on", "")) cvss = args.get("cvss", "") limit = args.get("limit", "25") offset = args.get("offset", "0") filter_req_id_and_severity = create_filter([(id, "id"), (severity, "severity")]) filter_req = create_filter_list_vulnerabilities( filter_req_id_and_severity, name_equal, name_contains, description, published_on, cvss, updated_on ) headers = [ "id", "name", "description", "severity", "publishedOn", "updatedOn", "exposedMachines", "exploitVerified", "publicExploit", "cvssV3", ] list_vulnerabilities_response = client.get_list_vulnerabilities(filter_req, limit, offset) list_vulnerabilities_response_value = list_vulnerabilities_response.get("value") results_list = [] if list_vulnerabilities_response_value: for cve in list_vulnerabilities_response_value: cve_id = cve.get("id") cve_indicator = Common.CVE( id=cve_id, cvss=cve.get("cvssV3"), description=cve.get("description"), published=cve.get("publishedOn"), modified=cve.get("updatedOn"), ) human_readable = tableToMarkdown( f"{INTEGRATION_NAME} vulnerabilities:", add_backslash_infront_of_underscore_list([cve]), headers=headers, removeNull=True, ) results_list.append( CommandResults( outputs_prefix="MicrosoftATP.Vulnerability", outputs_key_field="id", outputs=cve, readable_output=human_readable, raw_response=cve, indicator=cve_indicator, ) ) else: results_list.append(CommandResults(readable_output="No vulnerabilities were found.")) return results_list def list_machines_by_vulnerability_command(client: MsClient, args: dict) -> CommandResults: """Retrieves a list of devices affected by a vulnerability (by the given CVE ID). Returns: CommandResults. Human readable, context, raw response """ headers = ["ID", "ComputerDNSName", "OSPlatform", "RBACGroupID", "RBACGroupName", "CVE"] cve_ids = remove_duplicates_from_list_arg(args, "cve_id") raw_response = [] machines_outputs = [] failed_cve = {} # if we got an error, we will return the machine ids that failed for cve_id in cve_ids: try: machines_response = client.get_list_machines_by_vulnerability(cve_id) for machine in machines_response["value"]: machine_data = get_machine_data(machine) machine_data.update({"CVE": cve_id}) machines_outputs.append(machine_data) raw_response.append(machines_response) except Exception as e: failed_cve[cve_id] = e continue machines_outputs = create_related_cve_list_for_machine(machines_outputs) human_readable = tableToMarkdown( f"{INTEGRATION_NAME} machines by vulnerabilities: {cve_ids}", machines_outputs, headers=headers, removeNull=True ) human_readable += add_error_message(failed_cve, cve_ids) return CommandResults( outputs_prefix="MicrosoftATP.CveMachine", outputs_key_field="ID", outputs=machines_outputs, readable_output=human_readable, raw_response=raw_response, ) def create_related_cve_list_for_machine(machines): """ Parses the machines list to include a CVE list for each machine by ID. For example, machines = [{'ID': 1, 'CVE': 'CVE-1'},{'ID': 1, 'CVE': 'CVE-2'},{'ID': 2, 'CVE': 'CVE-1'}] the output after the for loop will be: machines = [{'ID': 1, ['CVE': 'CVE-1','CVE-2']},{'ID': 1, ['CVE': 'CVE-1','CVE-2']},{'ID': 2, 'CVE': ['CVE-1']}] and the output after remove duplicates will be: unique_machines = [{'ID': 1, 'CVE': ['CVE-1','CVE-2']},{'ID': 2, 'CVE': ['CVE-1']}] """ machine_id_to_cve_list: dict[str, list[str]] = {} for machine in machines: machine_id = machine.get("ID") cve_id = machine.get("CVE") if not machine_id_to_cve_list.get(machine_id): machine_id_to_cve_list[machine_id] = [cve_id] else: machine_id_to_cve_list[machine_id].append(cve_id) machine.pop("CVE") machine["CVE"] = machine_id_to_cve_list[machine_id] # handle duplicates unique_machines = [] for machine in machines: if machine not in unique_machines: unique_machines.append(machine) return unique_machines def get_file_context(file_info_response: dict[str, str], headers: list): return {key.capitalize(): value for (key, value) in file_info_response.items() if key in headers} def get_dbot_score(determination_type): if determination_type == "Clean": verdict = Common.DBotScore.GOOD elif determination_type == "Unknown": verdict = Common.DBotScore.NONE else: verdict = Common.DBotScore.BAD return verdict def build_file_error_output(error_message, file_hash): dbot_score = Common.DBotScore( indicator=file_hash, indicator_type=DBotScoreType.FILE, integration_name=INTEGRATION_NAME, score=Common.DBotScore.NONE, ) indicator = get_dbot_indicator(dbot_type=DBotScoreType.FILE, dbot_score=dbot_score, value=file_hash) readable_output = f"Unable to create indicator for file hash: {file_hash!r}.\nError: {error_message!r}" result = CommandResults(readable_output=readable_output, indicator=indicator) return result def build_file_output(raw_response, file_hash): dbot_score = Common.DBotScore( indicator=file_hash, indicator_type=DBotScoreType.FILE, integration_name=INTEGRATION_NAME, score=get_dbot_score(raw_response.get("DeterminationType")), ) file_object = Common.File( md5=raw_response.get("Md5"), sha1=raw_response.get("Sha1"), sha256=raw_response.get("Sha256"), file_type=raw_response.get("FileType"), dbot_score=dbot_score, ) result = CommandResults( outputs_prefix="MicrosoftATP.File", outputs_key_field="Sha1", outputs=raw_response, raw_response=raw_response, indicator=file_object, ) return result def file_command(client: MsClient, args: dict) -> list[CommandResults]: """Returns verdict for files Returns: CommandResults list. """ file_hashes = argToList(args["file"]) results = [] for file_hash in file_hashes: try: file_info_response = client.get_file_data(file_hash) results.append(build_file_output(get_file_data(file_info_response), file_hash)) except DemistoException as f: error_message = f.res.json().get("error", {}).get("message", "") results.append(build_file_error_output(error_message, file_hash)) return results def get_file_info_command(client: MsClient, args: dict): """Retrieves file info by a file hash (Sha1 or Sha256). Returns: CommandResults. Human readable, context, raw response """ headers = ["Sha1", "Sha256", "Size", "FileType", "Signer", "IsValidCertificate"] file_context_path = ( "File(val.SHA1 && val.SHA1 == obj.SHA1 || val.SHA256 && val.SHA256 == obj.SHA256 || " "val.Type && val.Type == obj.Type || val.Size && val.Size == obj.Size )" ) file_hashes = remove_duplicates_from_list_arg(args, "hash") raw_response = [] file_outputs = [] file_context_outputs = [] failed_hashes = {} # if we got an error, we will return the machine ids that failed sha1_value_in_files = [] # for not adding duplicates machines to the table not_found_ids = [] for file_hash in file_hashes: try: file_info_response = client.get_file_data(file_hash) file_data = get_file_data(file_info_response) if file_data.get("Sha1", "") not in sha1_value_in_files: file_outputs.append(file_data) sha1_value_in_files.append(file_data.get("Sha1", "")) raw_response.append(file_info_response) file_context_outputs.append(get_file_context(file_info_response, ["sha1", "sha256", "filetype", "size"])) except NotFoundError: # in case the error is not found hash, we want to return "No entries" not_found_ids.append(file_hash) continue except Exception as e: failed_hashes[file_hash] = e continue human_readable = tableToMarkdown( f"{INTEGRATION_NAME} file info by hashes: {file_hashes}", file_outputs, headers=headers, removeNull=True ) human_readable += add_error_message(failed_hashes, file_hashes) human_readable += not_found_message(not_found_ids) if file_outputs: context = {"MicrosoftATP.File(val.Sha1 === obj.Sha1)": file_outputs, file_context_path: file_context_outputs} return { "Type": entryTypes["note"], "ContentsFormat": formats["text"], "Contents": file_outputs, "EntryContext": context, "HumanReadable": human_readable, "raw_response": raw_response, } else: return "No entries." def create_endpoint_verdict(machine: dict): return Common.Endpoint( id=machine.get("ID"), hostname=machine.get("ComputerDNSName"), ip_address=machine.get("LastIPAddress"), mac_address=machine.get("MACAddress"), os=machine.get("OSPlatform"), status=HEALTH_STATUS_TO_ENDPOINT_STATUS[machine.get("HealthStatus", "Unknown")], vendor=INTEGRATION_NAME, os_version=f"{machine.get('OSVersion')} {machine.get('OSProcessor')} bit", ) def create_filter_for_endpoint_command(hostnames, ips, ids): """ Creates an OData filter query using the 'in' operator to get machines. This method avoids the 'node count limit' API error by grouping values. For example, for the input: hostnames=['b.com', 'a.com'], ips=['1.2.3.4'], ids=['1','2'] The result will be: "computerDnsName in ('b.com','a.com') or lastIpAddress in ('1.2.3.4') or id in ('1','2')" Args: hostnames (list): A list of computerDnsName strings. ips (list): A list of lastIpAddress strings. ids (list): A list of id strings. Returns: str: An efficient OData filter query string. """ fields_to_values = { "computerDnsName": hostnames, "lastIpAddress": ips, "id": ids, } filter_parts = [] for field, values in fields_to_values.items(): if values: # Format each value with single quotes (e.g., 'value1') formatted_values = [f"'{v}'" for v in values] joined_values = ",".join(formatted_values) filter_parts.append(f"{field} in ({joined_values})") return " or ".join(filter_parts) def validate_args_endpoint_command(hostnames, ips, ids): no_hostname = len(hostnames) == 0 no_ip = len(ips) == 0 no_id = len(ids) == 0 if no_hostname and no_ip and no_id: raise DemistoException(f"{INTEGRATION_NAME} - In order to run this command, please provide valid id, ip or hostname") def handle_machines(machines_response: dict) -> list[CommandResults]: """Converts the raw response of the API to a CommandResults list with relevant keys. Args: The raw API response, a list of machines. Returns: CommandResults list. """ headers = ["ID", "Hostname", "OS", "OSVersion", "IPAddress", "Status", "MACAddress", "Vendor"] machines_outputs = [] for machine in machines_response.get("value", []): machine_data = get_machine_data(machine) machine_data["MACAddress"] = get_machine_mac_address(machine) endpoint_indicator = create_endpoint_verdict(machine_data) human_readable = tableToMarkdown( f"{INTEGRATION_NAME} Machine:", endpoint_indicator.to_context()[Common.Endpoint.CONTEXT_PATH], headers=headers, removeNull=True, ) machines_outputs.append( CommandResults( readable_output=human_readable, outputs_prefix="MicrosoftATP.Machine", raw_response=machines_response, outputs_key_field="ID", outputs=machine_data, indicator=endpoint_indicator, ) ) if not machines_outputs: machines_outputs.append( CommandResults( readable_output=f"{INTEGRATION_NAME} no device found.", raw_response=machines_response, ) ) return machines_outputs def get_machine_by_ip_command(client: MsClient, args: dict) -> list[CommandResults]: """Retreives Machines that were seen with the requested internal IP in the time range of 15 minutes prior and aftera given timestamp. Args: client: MsClient args: dict Returns: CommandResults list. """ ip = args["ip"] timestamp = args["timestamp"] limit = arg_to_number(args.get("limit", 50)) should_limit_result = not argToBoolean(args.get("all_results", False)) filter = f"(ip='{ip}',timestamp={timestamp})" raw_machines_response = client.get_machines_for_get_machine_by_ip_command(filter) machines_response = raw_machines_response.get("value", []) demisto.debug(f"limit is set to: {limit}") limited_machines_response = machines_response[:limit] if should_limit_result else machines_response raw_machines_response["value"] = limited_machines_response demisto.debug("Calling handle_machines function to convert raw response to CommandResults list") return handle_machines(raw_machines_response) def endpoint_command(client: MsClient, args: dict) -> list[CommandResults]: """Retrieves a collection of machines that have communicated with WDATP cloud on the last 30 days Returns: CommandResults list. """ hostnames = argToList(args.get("hostname", "")) ips = argToList(args.get("ip", "")) ids = argToList(args.get("id", "")) validate_args_endpoint_command(hostnames, ips, ids) machines_response = client.get_machines(create_filter_for_endpoint_command(hostnames, ips, ids)) return handle_machines(machines_response) def get_machine_users_command(client: MsClient, args: dict) -> CommandResults: """Retrieves a collection of logon users on a given machine Returns: CommandResults. """ headers = ["ID", "AccountName", "AccountDomain", "FirstSeen", "LastSeen", "LogonTypes", "DomainAdmin", "NetworkUser"] machine_id = args.get("machine_id") response = client.get_machine_users(machine_id) users_list = [dict(**get_user_data(r), MachineID=machine_id) for r in response.get("value", [])] return CommandResults( outputs=users_list, outputs_key_field=["ID", "MachineID"], outputs_prefix="MicrosoftATP.MachineUser", readable_output=tableToMarkdown( f"Microsoft Defender ATP logon users for machine {machine_id}:", users_list, headers=headers, removeNull=True, ), raw_response=response, ) def get_machine_alerts_command(client: MsClient, args: dict) -> CommandResults: """Retrieves a collection of alerts related to specific device. Returns: CommandResults. """ headers = [ "ID", "Title", "Description", "IncidentID", "Severity", "Status", "Classification", "Category", "ThreatFamilyName", "MachineID", ] machine_id = args.get("machine_id") alerts_response = client.get_machine_alerts(machine_id) alert_list = get_alerts_list(alerts_response) return CommandResults( outputs=alert_list, outputs_key_field=["ID", "MachineID"], outputs_prefix="MicrosoftATP.MachineAlerts", readable_output=tableToMarkdown( f"Alerts that are related to machine {machine_id}:", alert_list, headers=headers, removeNull=True, ), raw_response=alerts_response, ) """ EXECUTION CODE """ """ LIVE RESPONSE CODE """ def run_polling_command( client: MsClient, args: dict, cmd: str, action_func: Callable, results_function: Callable, post_polling_process: Callable ): """ This function is generically handling the polling flow. In the polling flow, there is always an initial call that starts the uploading to the API (referred here as the 'upload' function) and another call that retrieves the status of that upload (referred here as the 'results' function). The run_polling_command function runs the 'upload' function and returns a ScheduledCommand object that schedules the next 'results' function, until the polling is complete. Args: args: the arguments required to the command being called, under cmd cmd: the command to schedule by after the current command results_function: the function that retrieves the status of the previously initiated upload process client: a Microsoft Client object Returns: """ ScheduledCommand.raise_error_if_not_supported() interval_in_secs = int(args.get("interval_in_seconds", 10)) timeout_in_seconds = int(args.get("timeout_in_seconds", 600)) # distinguish between the initial run, which is the upload run, and the results run is_first_run = "machine_action_id" not in args if is_first_run: command_results = action_func(client, args) outputs = command_results.outputs # schedule next poll polling_args = { "machine_action_id": outputs.get("action_id"), "interval_in_seconds": interval_in_secs, "polling": True, **args, } scheduled_command = ScheduledCommand( command=cmd, next_run_in_seconds=interval_in_secs, args=polling_args, timeout_in_seconds=timeout_in_seconds ) command_results.scheduled_command = scheduled_command return command_results # not a first run command_result = results_function(client, args) action_status = command_result.outputs.get("status") demisto.debug(f"action status is: {action_status}") # In case command is one of the put/get file/ run script there is command section, otherwise there isnt. if command_result.outputs.get("commands", []): command_status = command_result.outputs.get("commands", [{}])[0].get("commandStatus") else: command_status = "Completed" if action_status == "Succeeded" else None if action_status in ["Failed", "Cancelled"] or command_status == "Failed": error_msg = f"Command {action_status}." if command_result.outputs.get("commands", []): error_msg += f'{command_result.outputs.get("commands", [{}])[0].get("errors")}' raise Exception(error_msg) elif command_status != "Completed" or action_status in ("InProgress", "Pending"): demisto.debug("action status is not completed, will poll again") # schedule next poll polling_args = {"interval_in_seconds": interval_in_secs, "polling": True, **args} scheduled_command = ScheduledCommand( command=cmd, next_run_in_seconds=interval_in_secs, args=polling_args, timeout_in_seconds=timeout_in_seconds ) command_result = CommandResults(scheduled_command=scheduled_command) return command_result # action was completed else: return post_polling_process(client, command_result.outputs) def get_live_response_result_command(client, args): machine_action_id = args["machine_action_id"] command_index = arg_to_number(args["command_index"]) res = client.get_live_response_result(machine_action_id, command_index) file_link = res["value"] # download link, create file result f_data = client.download_file(file_link) try: outputs = f_data.json() except Exception: outputs = {"value": file_link} return [ fileResult("Response Result", f_data.content), CommandResults( outputs_prefix="MicrosoftATP.LiveResponseResult", outputs=outputs, readable_output=f"file_link: {file_link}" ), ] def get_machine_action_command(client, args): id = args["machine_action_id"] res = client.get_machine_action_by_id(id, overwrite_rate_limit_retry=True) return CommandResults(outputs_prefix="MicrosoftATP.MachineAction", outputs_key_field="action_id", outputs=res) def cancel_action_command(client, args): action_id = args["machine_action_id"] comment = args["comment"] body = {"Comment": comment} # cancel action should return either 200 or 404. try: client.cancel_action(action_id, body) except Exception as e: if "404" in str(e): raise DemistoException(f"Action ID {action_id} could not be found. Make sure you entered the correct ID.") raise return CommandResults(readable_output="Action was cancelled successfully.") # -------------- Run Script --------------- def run_live_response_script_with_polling(client, args): return run_polling_command( client, args, "microsoft-atp-live-response-run-script", run_live_response_script_action, get_machine_action_command, get_successfull_action_results_as_info, ) def run_live_response_script_action(client, args): machine_id = args["machine_id"] scriptName = args["scriptName"] comment = args["comment"] arguments = args.get("arguments") params = [{"key": "ScriptName", "value": scriptName}] if arguments: params.append({"key": "Args", "value": arguments}) request_body = { "Commands": [ {"type": "RunScript", "params": params}, ], "Comment": comment, } # create action: res = client.create_action(machine_id, request_body, overwrite_rate_limit_retry=True) md = tableToMarkdown("Processing action. This may take a few minutes.", res["id"], headers=["id"]) return CommandResults(outputs_prefix="MicrosoftATP.LiveResponseAction", outputs={"action_id": res["id"]}, readable_output=md) def get_successfull_action_results_as_info(client, res): machine_action_id = res["id"] file_link = client.get_live_response_result(machine_action_id, 0, overwrite_rate_limit_retry=True)["value"] f_data = client.download_file(file_link) try: script_result = f_data.json() except Exception as e: demisto.debug(f"Failed download script results from link {file_link}. Error: {e!s}") script_result = None return [ CommandResults( outputs_prefix="MicrosoftATP.LiveResponseAction", outputs=script_result if script_result else res, readable_output=tableToMarkdown("Script Results:", script_result, is_auto_json_transform=True) if script_result else "Could not retrieve script results.", ), fileResult("Response Result", f_data.content, file_type=EntryType.ENTRY_INFO_FILE), ] # -------------- Get File --------------- def get_live_response_file_with_polling(client, args): return run_polling_command( client, args, "microsoft-atp-live-response-get-file", get_live_response_file_action, get_machine_action_command, get_file_get_successfull_action_results, ) def get_live_response_file_action(client, args): machine_id = args["machine_id"] file_path = args["path"] comment = args["comment"] request_body = { "Commands": [ {"type": "GetFile", "params": [{"key": "Path", "value": file_path}]}, ], "Comment": comment, } # create action: res = client.create_action(machine_id, request_body, overwrite_rate_limit_retry=True) md = tableToMarkdown("Processing action. This may take a few minutes.", res["id"], headers=["id"]) return CommandResults(outputs_prefix="MicrosoftATP.LiveResponseAction", outputs={"action_id": res["id"]}, readable_output=md) def get_file_get_successfull_action_results(client, res): machine_action_id = res["id"] # get file link from action: file_link = client.get_live_response_result(machine_action_id, 0, overwrite_rate_limit_retry=True)["value"] demisto.debug(f"Got file for downloading: {file_link}") # download link, create file result. File comes back as compressed gz file. f_data = client.download_file(file_link) md_results = { "Machine Action Id": res.get("id"), "MachineId": res.get("machineId"), "Hostname": res.get("computerDnsName"), "Status": res.get("status"), "Creation time": res.get("creationDateTimeUtc"), "Commands": res.get("commands"), } return [ fileResult("Response Result.gz", f_data.content), CommandResults( outputs_prefix="MicrosoftATP.LiveResponseAction", outputs=res, readable_output=tableToMarkdown("Machine Action:", md_results, is_auto_json_transform=True), ), ] # -------------- Put File --------------- def put_live_response_file_with_polling(client, args): return run_polling_command( client, args, "microsoft-atp-live-response-put-file", put_live_response_file_action, get_machine_action_command, put_file_get_successful_action_results, ) def put_live_response_file_action(client, args): machine_id = args["machine_id"] file_path = args["file_name"] comment = args["comment"] request_body = { "Commands": [ {"type": "PutFile", "params": [{"key": "FileName", "value": file_path}]}, ], "Comment": comment, } # create action: res = client.create_action(machine_id, request_body, overwrite_rate_limit_retry=True) md = tableToMarkdown("Processing action. This may take a few minutes.", res["id"], headers=["id"]) return CommandResults(outputs_prefix="MicrosoftATP.LiveResponseAction", outputs={"action_id": res["id"]}, readable_output=md) def put_file_get_successful_action_results(client, res): md_results = { "Machine Action Id": res.get("id"), "MachineId": res.get("machineId"), "Hostname": res.get("computerDnsName"), "Status": res.get("status"), "Creation time": res.get("creationDateTimeUtc"), "Commands": res.get("commands"), } return CommandResults( outputs_prefix="MicrosoftATP.LiveResponseAction", outputs=res, readable_output=tableToMarkdown("Machine Action:", md_results, is_auto_json_transform=True), ) def main(): # pragma: no cover params: dict = demisto.params() params_endpoint_type = params.get("endpoint_type") or "Worldwide" params_url = params.get("url") is_gcc = params.get("is_gcc", False) tenant_id = params.get("tenant_id") or params.get("_tenant_id") or params.get("_tenant_id_encrypted", {}).get("password") auth_id = params.get("_auth_id") or params.get("auth_id") or params.get("_auth_id_encrypted", {}).get("password") enc_key = (params.get("credentials") or {}).get("password") or params.get("enc_key") use_ssl: bool = not params.get("insecure", False) proxy: bool = params.get("proxy", False) self_deployed: bool = params.get("self_deployed", False) certificate_thumbprint = params.get("creds_certificate", {}).get("identifier") or params.get("certificate_thumbprint") private_key = replace_spaces_in_credential(params.get("creds_certificate", {}).get("password")) or params.get("private_key") alert_detectionsource_to_fetch = params.get("fetch_detectionsource") alert_severities_to_fetch = params.get("fetch_severity") alert_status_to_fetch = params.get("fetch_status") alert_time_to_fetch = params.get("first_fetch_timestamp", "3 days") max_alert_to_fetch = arg_to_number(params.get("max_fetch", 50)) fetch_evidence = argToBoolean(params.get("fetch_evidence", False)) last_run = demisto.getLastRun() auth_type = params.get("auth_type", "Client Credentials") auth_code = params.get("auth_code", {}).get("password", "") redirect_uri = params.get("redirect_uri", "") managed_identities_client_id = get_azure_managed_identities_client_id(params) self_deployed = self_deployed or managed_identities_client_id is not None endpoint_type, params_url = microsoft_defender_for_endpoint_get_base_url(params_endpoint_type, params_url, is_gcc) base_url: str = urljoin(params_url, "/api") if not managed_identities_client_id: if not self_deployed and not enc_key: raise DemistoException( "Key must be provided. For further information see " "https://xsoar.pan.dev/docs/reference/articles/microsoft-integrations---authentication" ) elif not enc_key and (not certificate_thumbprint or not private_key): raise DemistoException("Key or Certificate Thumbprint and Private Key must be provided.") if not auth_id: raise Exception("Authentication ID must be provided.") if not tenant_id: raise Exception("Tenant ID must be provided.") if auth_code: if redirect_uri and not self_deployed: raise Exception("In order to use Authorization Code, set Self Deployed: True.") if not redirect_uri: raise Exception( "In order to use Authorization Code auth flow, you should set: " '"Application redirect URI", "Authorization code" and "Self Deployed=True".' ) command = demisto.command() args = demisto.args() LOG(f"command is {command}") try: client = MsClient( base_url=base_url, tenant_id=tenant_id, auth_id=auth_id, enc_key=enc_key, app_name=APP_NAME, verify=use_ssl, proxy=proxy, self_deployed=self_deployed, alert_severities_to_fetch=alert_severities_to_fetch, alert_status_to_fetch=alert_status_to_fetch, alert_time_to_fetch=alert_time_to_fetch, max_fetch=max_alert_to_fetch, certificate_thumbprint=certificate_thumbprint, private_key=private_key, auth_type=auth_type, endpoint_type=endpoint_type, auth_code=auth_code, redirect_uri=redirect_uri, managed_identities_client_id=managed_identities_client_id, alert_detectionsource_to_fetch=alert_detectionsource_to_fetch, ) if command == "test-module": if auth_type == "Authorization Code": raise Exception( "Test-module is not available when using Authentication-code auth flow. " "Please use `!microsoft-atp-test` command to test the connection" ) test_module(client) demisto.results("ok") elif command == "microsoft-atp-test": test_module(client) return_results("✅ Success!") elif command == "fetch-incidents": incidents, last_run = fetch_incidents(client, last_run, fetch_evidence) demisto.setLastRun(last_run) demisto.incidents(incidents) elif command == "microsoft-atp-get-machine-by-ip": return_results(get_machine_by_ip_command(client, args)) elif command == "microsoft-atp-isolate-machine": return_outputs(*isolate_machine_command(client, args)) elif command == "microsoft-atp-unisolate-machine": return_outputs(*unisolate_machine_command(client, args)) elif command == "microsoft-atp-get-machines": return_outputs(*get_machines_command(client, args)) elif command == "microsoft-atp-get-file-related-machines": return_results(get_file_related_machines_command(client, args)) elif command == "microsoft-atp-get-machine-details": return_results(get_machine_details_command(client, args)) elif command == "microsoft-atp-get-machine-software": return_results(get_machine_software_command(client, args)) elif command == "microsoft-atp-get-machine-missing-kbs": return_results(get_machine_missing_kbs_command(client, args)) elif command == "microsoft-atp-run-antivirus-scan": return_outputs(*run_antivirus_scan_command(client, args)) elif command == "microsoft-atp-list-alerts": return_outputs(*list_alerts_command(client, args)) elif command == "microsoft-atp-update-alert": return_outputs(*update_alert_command(client, args)) elif command == "microsoft-atp-advanced-hunting": return_outputs(*get_advanced_hunting_command(client, args)) elif command == "microsoft-atp-create-alert": return_outputs(*create_alert_command(client, args)) elif command == "microsoft-atp-get-alert-related-user": return_outputs(*get_alert_related_user_command(client, args)) elif command == "microsoft-atp-get-alert-related-files": return_outputs(*get_alert_related_files_command(client, args)) elif command == "microsoft-atp-get-alert-related-ips": return_outputs(*get_alert_related_ips_command(client, args)) elif command == "microsoft-atp-get-alert-related-domains": return_outputs(*get_alert_related_domains_command(client, args)) elif command == "microsoft-atp-list-machine-actions-details": return_outputs(*get_machine_action_by_id_command(client, args)) elif command == "microsoft-atp-collect-investigation-package": return_outputs(*get_machine_investigation_package_command(client, args)) elif command == "microsoft-atp-get-investigation-package-sas-uri": return_outputs(*get_investigation_package_sas_uri_command(client, args)) elif command == "microsoft-atp-restrict-app-execution": return_outputs(*restrict_app_execution_command(client, args)) elif command == "microsoft-atp-remove-app-restriction": return_outputs(*remove_app_restriction_command(client, args)) elif command == "microsoft-atp-stop-and-quarantine-file": return_results(stop_and_quarantine_file_command_polling(args, client)) elif command == "microsoft-atp-list-investigations": return_outputs(*get_investigations_by_id_command(client, args)) elif command == "microsoft-atp-start-investigation": return_outputs(*start_investigation_command(client, args)) elif command == "microsoft-atp-get-domain-statistics": return_outputs(*get_domain_statistics_command(client, args)) elif command == "microsoft-atp-get-domain-alerts": return_outputs(*get_domain_alerts_command(client, args)) elif command == "microsoft-atp-get-domain-machines": return_outputs(*get_domain_machine_command(client, args)) elif command == "microsoft-atp-get-file-statistics": return_results(get_file_statistics_command(client, args)) elif command == "microsoft-atp-get-file-alerts": return_outputs(*get_file_alerts_command(client, args)) elif command == "microsoft-atp-get-ip-statistics": return_outputs(*get_ip_statistics_command(client, args)) elif command == "microsoft-atp-get-ip-alerts": return_outputs(*get_ip_alerts_command(client, args)) elif command == "microsoft-atp-get-user-alerts": return_outputs(*get_user_alerts_command(client, args)) elif command == "microsoft-atp-get-alert-by-id": return_results(get_alert_by_id_command(client, args)) elif command == "microsoft-atp-get-user-machines": return_outputs(*get_user_machine_command(client, args)) elif command == "microsoft-atp-add-remove-machine-tag": return_outputs(*add_remove_machine_tag_command(client, args)) elif command == "microsoft-atp-list-machines-by-vulnerability": return_results(list_machines_by_vulnerability_command(client, args)) elif command == "microsoft-atp-list-software-version-distribution": return_results(list_software_version_distribution_command(client, args)) elif command == "microsoft-atp-list-machines-by-software": return_results(list_machines_by_software_command(client, args)) elif command == "microsoft-atp-list-missing-kb-by-software": return_results(list_missing_kb_by_software_command(client, args)) elif command == "microsoft-atp-list-vulnerabilities-by-software": return_results(list_vulnerabilities_by_software_command(client, args)) elif command == "microsoft-atp-list-software": return_results(list_software_command(client, args)) elif command == "microsoft-atp-list-vulnerabilities-by-machine": return_results(list_vulnerabilities_by_machine_command(client, args)) elif command == "microsoft-atp-list-vulnerabilities": return_results(list_vulnerabilities_command(client, args)) elif command == "microsoft-atp-get-file-info": demisto.results(get_file_info_command(client, args)) elif command == "endpoint": return_results(endpoint_command(client, args)) elif command == "file": return_results(file_command(client, args)) elif command in ("microsoft-atp-indicator-list", "microsoft-atp-indicator-get-by-id"): return_outputs(*list_indicators_command(client, args)) elif command == "microsoft-atp-indicator-create-file": return_outputs(*create_file_indicator_command(client, args)) elif command == "microsoft-atp-indicator-create-network": return_outputs(*create_network_indicator_command(client, args)) elif command == "microsoft-atp-indicator-update": return_outputs(*update_indicator_command(client, args)) elif command == "microsoft-atp-indicator-delete": return_outputs(delete_indicator_command(client, args)) elif command in ("microsoft-atp-sc-indicator-list", "microsoft-atp-sc-indicator-get-by-id"): return_results(sc_list_indicators_command(client, args)) elif command in ("microsoft-atp-sc-indicator-update", "microsoft-atp-sc-indicator-create"): return_results(sc_create_update_indicator_command(client, args)) elif command == "microsoft-atp-sc-indicator-delete": return_results(sc_delete_indicator_command(client, args)) elif command == "microsoft-atp-indicator-batch-update": return_results(sc_update_batch_indicators_command(client, args)) elif command == "microsoft-atp-live-response-put-file": return_results(put_live_response_file_with_polling(client, args)) elif command == "microsoft-atp-live-response-get-file": return_results(get_live_response_file_with_polling(client, args)) elif command == "microsoft-atp-live-response-run-script": return_results(run_live_response_script_with_polling(client, args)) elif command == "microsoft-atp-live-response-cancel-action": return_results(cancel_action_command(client, args)) elif command == "microsoft-atp-live-response-result": return_results(get_live_response_result_command(client, args)) elif command == "microsoft-atp-advanced-hunting-lateral-movement-evidence": return_results(lateral_movement_evidence_command(client, args)) elif command == "microsoft-atp-advanced-hunting-persistence-evidence": return_results(persistence_evidence_command(client, args)) elif command == "microsoft-atp-advanced-hunting-file-origin": return_results(file_origin_command(client, args)) elif command == "microsoft-atp-advanced-hunting-process-details": return_results(process_details_command(client, args)) elif command == "microsoft-atp-advanced-hunting-network-connections": return_results(network_connections_command(client, args)) elif command == "microsoft-atp-advanced-hunting-privilege-escalation": return_results(privilege_escalation_command(client, args)) elif command == "microsoft-atp-advanced-hunting-tampering": return_results(tampering_command(client, args)) elif command == "microsoft-atp-advanced-hunting-cover-up": return_results(cover_up_command(client, args)) elif command == "microsoft-atp-offboard-machine": return_results(offboard_machine_command(client, args)) elif command == "microsoft-atp-get-machine-users": return_results(get_machine_users_command(client, args)) elif command == "microsoft-atp-get-machine-alerts": return_results(get_machine_alerts_command(client, args)) elif command == "microsoft-atp-get-machine-vulnerabilities": return_results(get_machine_vulnerabilities_command(client, args)) elif command == "microsoft-atp-request-and-download-investigation-package": return_results(request_download_investigation_package_command(client, args)) elif command == "microsoft-atp-generate-login-url": return_results(generate_login_url_command(client)) elif command == "microsoft-atp-auth-reset": return_results(reset_auth()) elif command == "microsoft-atp-list-auth-permissions": return_results(list_auth_permissions_command(client)) except Exception as err: # TODO Following the CIAC-12304 ticket, many commands, including fetch incidents, are deprecated. # In the future, if the deprecation reaches end-of-life, we may receive a unique error. # It would be worth handling that error and adding explanations if needed. return_error(str(err)) if __name__ in ("__main__", "__builtin__", "builtins"): main()