Cortex Attack Surface Management
Integration to pull assets and other ASM related information.
Vulnerability Management · Cortex Attack Surface Management
Details
| ID | Cortex Attack Surface Management |
|---|---|
| Provider | Palo Alto Networks |
| Category | Vulnerability Management |
| From Version | 6.5.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
README
Integration to pull assets and other ASM related information.
This integration was integrated and tested with version 1.2.0 of Cortex Attack Surface Management.
Configure Cortex Attack Surface Management
| Parameter | Description | Required |
|---|---|---|
| Server URL | The web UI with api- appended to front (e.g., https://api-xsiam.paloaltonetworks.com). For more information please see Cortex XDR API documentation. |
True |
| API Key ID | For more information please see Cortex XDR API documentation. Only a standard API key type is supported. | True |
| API Key | True | |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False |
Commands
You can execute these commands from the 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.
asm-list-external-service
Get a list of all your external services filtered by business units, externally detected providers, domain, externally inferred CVEs, active classifications, inactive classifications, service name, service type, protocol, IP address, is active, and discovery type. Maximum result limit is 100 assets.
Base Command
asm-list-external-service
Input
| Argument Name | Description | Required |
|---|---|---|
| ip_address | IP address on which to search. | Optional |
| domain | Domain on which to search. | Optional |
| is_active | Whether the service is active. Possible values are: yes, no. | Optional |
| discovery_type | How service was discovered. Possible values are: colocated_on_ip, directly_discovery, unknown. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| ASM.ExternalService.service_id | String | External service UUID. |
| ASM.ExternalService.service_name | String | Name of the external service. |
| ASM.ExternalService.service_type | String | Type of the external service. |
| ASM.ExternalService.ip_address | String | IP address of the external service. |
| ASM.ExternalService.externally_detected_providers | String | Providers of an external service. |
| ASM.ExternalService.is_active | String | Whether the external service is active. |
| ASM.ExternalService.first_observed | Date | Date of the first observation of the external service. |
| ASM.ExternalService.last_observed | Date | Date of the last observation of the external service. |
| ASM.ExternalService.port | Number | Port number of the external service. |
| ASM.ExternalService.protocol | String | Protocol number of the external service. |
| ASM.ExternalService.inactive_classifications | String | External service classifications that are no longer active. |
| ASM.ExternalService.discovery_type | String | How the external service was discovered. |
| ASM.ExternalService.business_units | String | External service associated business units. |
| ASM.ExternalService.externally_inferred_vulnerability_score | Unknown | External service vulnerability score. |
Command example
!asm-list-external-service domain=acme.com is_active=yes discovery_type=directly_discovery
Context Example
{
"ASM": {
"ExternalService": [
{
"active_classifications": [
"HttpServer",
"MicrosoftOWAServer",
"ServerSoftware",
"MicrosoftIisWebServer",
"ApplicationServerSoftware"
],
"business_units": [
"Acme",
"VanDelay Industries"
],
"discovery_type": "DirectlyDiscovered",
"domain": [
"autodiscover.acme.com"
],
"externally_detected_providers": [
"Microsoft Azure"
],
"externally_inferred_cves": [],
"externally_inferred_vulnerability_score": null,
"first_observed": 1659395040000,
"inactive_classifications": [],
"ip_address": [
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1"
],
"is_active": "Active",
"last_observed": 1663024320000,
"port": 80,
"protocol": "TCP",
"service_id": "4c755fea-59e8-3719-8829-9f6adde65068",
"service_name": "HTTP Server at autodiscover.acme.com:80",
"service_type": "HttpServer"
},
{
"active_classifications": [
"HttpServer",
"ServerSoftware"
],
"business_units": [
"Acme",
"VanDelay Industries"
],
"discovery_type": "DirectlyDiscovered",
"domain": [
"web.acme.com"
],
"externally_detected_providers": [
"Amazon Web Services"
],
"externally_inferred_cves": [],
"externally_inferred_vulnerability_score": null,
"first_observed": 1659396480000,
"inactive_classifications": [],
"ip_address": [
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1",
"1.1.1.1"
],
"is_active": "Active",
"last_observed": 1663029060000,
"port": 80,
"protocol": "TCP",
"service_id": "32c85ab1-fc98-3061-a813-2fe5daf7e7c5",
"service_name": "HTTP Server at web.acme.com:80",
"service_type": "HttpServer"
}
]
}
}
Human Readable Output
External Services
Active Classifications Business Units Discovery Type Domain Externally Detected Providers First Observed Ip Address Is Active Last Observed Port Protocol Service Id Service Name Service Type HttpServer,
MicrosoftOWAServer,
ServerSoftware,
MicrosoftIisWebServer,
ApplicationServerSoftwareAcme,
VanDelay IndustriesDirectlyDiscovered autodiscover.acme.com Microsoft Azure 1659395040000 1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1Active 1663024320000 80 TCP 4c755fea-59e8-3719-8829-9f6adde65068 HTTP Server at autodiscover.acme.com:80 HttpServer HttpServer,
ServerSoftwareAcme,
VanDelay IndustriesDirectlyDiscovered web.acme.com Amazon Web Services 1659396480000 1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1,
1.1.1.1Active 1663029060000 80 TCP 32c85ab1-fc98-3061-a813-2fe5daf7e7c5 HTTP Server at web.acme.com:80 HttpServer
asm-get-external-service
Get service details according to the service ID.
Base Command
asm-get-external-service
Input
| Argument Name | Description | Required |
|---|---|---|
| service_id | A string representing the service ID you want to get details for. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| ASM.ExternalService.service_id | String | External service UUID. |
| ASM.ExternalService.service_name | String | Name of the external service. |
| ASM.ExternalService.service_type | String | Type of the external service. |
| ASM.ExternalService.ip_address | String | IP address of the external service. |
| ASM.ExternalService.externally_detected_providers | String | Providers of the external service. |
| ASM.ExternalService.is_active | String | Whether the external service is active. |
| ASM.ExternalService.first_observed | Date | Date of the first observation of the external service. |
| ASM.ExternalService.last_observed | Date | Date of the last observation of the external service. |
| ASM.ExternalService.port | Number | Port number of the external service. |
| ASM.ExternalService.protocol | String | Protocol of the external service. |
| ASM.ExternalService.inactive_classifications | String | External service classifications that are no longer active. |
| ASM.ExternalService.discovery_type | String | How the external service was discovered. |
| ASM.ExternalService.business_units | String | External service associated business units. |
| ASM.ExternalService.externally_inferred_vulnerability_score | Unknown | External service vulnerability score. |
| ASM.ExternalService.details | String | Additional details. |
Command example
!asm-get-external-service service_id=94232f8a-f001-3292-aa65-63fa9d981427
Context Example
{
"ASM": {
"ExternalService": {
"active_classifications": [
"SSHWeakMACAlgorithmsEnabled",
"SshServer",
"OpenSSH"
],
"business_units": [
"Acme"
],
"details": {
"businessUnits": [
{
"name": "Acme"
}
],
"certificates": [],
"classifications": [
{
"activityStatus": "Active",
"firstObserved": 1662774120000,
"lastObserved": 1663026480000,
"name": "SshServer",
"values": [
{
"firstObserved": 1662774169000,
"jsonValue": "{\"version\":\"2.0\",\"serverVersion\":\"OpenSSH_7.6p1\",\"extraInfo\":\"Ubuntu-4ubuntu0.7\"}",
"lastObserved": 1663026500000
}
]
},
{
"activityStatus": "Active",
"firstObserved": 1662774120000,
"lastObserved": 1663026480000,
"name": "SSHWeakMACAlgorithmsEnabled",
"values": [
{
"firstObserved": 1662774169000,
"jsonValue": "{}",
"lastObserved": 1663026500000
}
]
},
{
"activityStatus": "Active",
"firstObserved": 1662774120000,
"lastObserved": 1663026480000,
"name": "OpenSSH",
"values": [
{
"firstObserved": 1662774169000,
"jsonValue": "{\"version\":\"7.6\"}",
"lastObserved": 1663026500000
}
]
}
],
"domains": [],
"enrichedObservationSource": "CLOUD",
"inferredCvesObserved": [
{
"activityStatus": "Active",
"firstObserved": 1662774169000,
"inferredCve": {
"cveId": "CVE-2020-15778",
"cveSeverityV2": "MEDIUM",
"cveSeverityV3": "HIGH",
"cvssScoreV2": 6.8,
"cvssScoreV3": 7.8,
"inferredCveMatchMetadata": {
"confidence": "High",
"inferredCveMatchType": "ExactVersionMatch",
"product": "openssh",
"vendor": "openbsd",
"version": "7.6"
}
},
"lastObserved": 1663026500000
},
{
"activityStatus": "Active",
"firstObserved": 1662774169000,
"inferredCve": {
"cveId": "CVE-2021-41617",
"cveSeverityV2": "MEDIUM",
"cveSeverityV3": "HIGH",
"cvssScoreV2": 4.4,
"cvssScoreV3": 7,
"inferredCveMatchMetadata": {
"confidence": "High",
"inferredCveMatchType": "ExactVersionMatch",
"product": "openssh",
"vendor": "openbsd",
"version": "7.6"
}
},
"lastObserved": 1663026500000
},
{
"activityStatus": "Active",
"firstObserved": 1662774169000,
"inferredCve": {
"cveId": "CVE-2019-6110",
"cveSeverityV2": "MEDIUM",
"cveSeverityV3": "MEDIUM",
"cvssScoreV2": 4,
"cvssScoreV3": 6.8,
"inferredCveMatchMetadata": {
"confidence": "High",
"inferredCveMatchType": "ExactVersionMatch",
"product": "openssh",
"vendor": "openbsd",
"version": "7.6"
}
},
"lastObserved": 1663026500000
},
{
"activityStatus": "Active",
"firstObserved": 1662774169000,
"inferredCve": {
"cveId": "CVE-2019-6109",
"cveSeverityV2": "MEDIUM",
"cveSeverityV3": "MEDIUM",
"cvssScoreV2": 4,
"cvssScoreV3": 6.8,
"inferredCveMatchMetadata": {
"confidence": "High",
"inferredCveMatchType": "ExactVersionMatch",
"product": "openssh",
"vendor": "openbsd",
"version": "7.6"
}
},
"lastObserved": 1663026500000
},
{
"activityStatus": "Active",
"firstObserved": 1662774169000,
"inferredCve": {
"cveId": "CVE-2020-14145",
"cveSeverityV2": "MEDIUM",
"cveSeverityV3": "MEDIUM",
"cvssScoreV2": 4.3,
"cvssScoreV3": 5.9,
"inferredCveMatchMetadata": {
"confidence": "High",
"inferredCveMatchType": "ExactVersionMatch",
"product": "openssh",
"vendor": "openbsd",
"version": "7.6"
}
},
"lastObserved": 1663026500000
},
{
"activityStatus": "Active",
"firstObserved": 1662774169000,
"inferredCve": {
"cveId": "CVE-2019-6111",
"cveSeverityV2": "MEDIUM",
"cveSeverityV3": "MEDIUM",
"cvssScoreV2": 5.8,
"cvssScoreV3": 5.9,
"inferredCveMatchMetadata": {
"confidence": "High",
"inferredCveMatchType": "ExactVersionMatch",
"product": "openssh",
"vendor": "openbsd",
"version": "7.6"
}
},
"lastObserved": 1663026500000
},
{
"activityStatus": "Active",
"firstObserved": 1662774169000,
"inferredCve": {
"cveId": "CVE-2018-20685",
"cveSeverityV2": "LOW",
"cveSeverityV3": "MEDIUM",
"cvssScoreV2": 2.6,
"cvssScoreV3": 5.3,
"inferredCveMatchMetadata": {
"confidence": "High",
"inferredCveMatchType": "ExactVersionMatch",
"product": "openssh",
"vendor": "openbsd",
"version": "7.6"
}
},
"lastObserved": 1663026500000
},
{
"activityStatus": "Active",
"firstObserved": 1662774169000,
"inferredCve": {
"cveId": "CVE-2018-15919",
"cveSeverityV2": "MEDIUM",
"cveSeverityV3": "MEDIUM",
"cvssScoreV2": 5,
"cvssScoreV3": 5.3,
"inferredCveMatchMetadata": {
"confidence": "High",
"inferredCveMatchType": "ExactVersionMatch",
"product": "openssh",
"vendor": "openbsd",
"version": "7.6"
}
},
"lastObserved": 1663026500000
},
{
"activityStatus": "Active",
"firstObserved": 1662774169000,
"inferredCve": {
"cveId": "CVE-2016-20012",
"cveSeverityV2": "MEDIUM",
"cveSeverityV3": "MEDIUM",
"cvssScoreV2": 4.3,
"cvssScoreV3": 5.3,
"inferredCveMatchMetadata": {
"confidence": "High",
"inferredCveMatchType": "ExactVersionMatch",
"product": "openssh",
"vendor": "openbsd",
"version": "7.6"
}
},
"lastObserved": 1663026500000
},
{
"activityStatus": "Active",
"firstObserved": 1662774169000,
"inferredCve": {
"cveId": "CVE-2018-15473",
"cveSeverityV2": "MEDIUM",
"cveSeverityV3": "MEDIUM",
"cvssScoreV2": 5,
"cvssScoreV3": 5.3,
"inferredCveMatchMetadata": {
"confidence": "High",
"inferredCveMatchType": "ExactVersionMatch",
"product": "openssh",
"vendor": "openbsd",
"version": "7.6"
}
},
"lastObserved": 1663026500000
},
{
"activityStatus": "Active",
"firstObserved": 1662774169000,
"inferredCve": {
"cveId": "CVE-2021-36368",
"cveSeverityV2": "LOW",
"cveSeverityV3": "LOW",
"cvssScoreV2": 2.6,
"cvssScoreV3": 3.7,
"inferredCveMatchMetadata": {
"confidence": "High",
"inferredCveMatchType": "ExactVersionMatch",
"product": "openssh",
"vendor": "openbsd",
"version": "7.6"
}
},
"lastObserved": 1663026500000
}
],
"ip_ranges": {},
"ips": [
{
"activityStatus": "Active",
"firstObserved": 1662774169000,
"geolocation": {
"city": "ASHBURN",
"countryCode": "US",
"latitude": 39.0438,
"longitude": -77.4879,
"regionCode": "VA",
"timeZone": null
},
"ip": 873887795,
"lastObserved": 1663026500000,
"protocol": "TCP",
"provider": "AWS"
}
],
"providerDetails": [
{
"firstObserved": 1662774169000,
"lastObserved": 1663026500000,
"name": "AWS"
}
],
"serviceKey": "1.1.1.1:22",
"serviceKeyType": "IP",
"tlsVersions": []
},
"discovery_type": "ColocatedOnIp",
"domain": [],
"externally_detected_providers": [
"Amazon Web Services"
],
"externally_inferred_cves": [
"CVE-2020-15778",
"CVE-2021-41617",
"CVE-2019-6110",
"CVE-2019-6109",
"CVE-2020-14145",
"CVE-2019-6111",
"CVE-2018-20685",
"CVE-2018-15919",
"CVE-2016-20012",
"CVE-2018-15473",
"CVE-2021-36368"
],
"externally_inferred_vulnerability_score": 7.8,
"first_observed": 1662774120000,
"inactive_classifications": [],
"ip_address": [
"1.1.1.1"
],
"is_active": "Active",
"last_observed": 1663026480000,
"port": 22,
"protocol": "TCP",
"service_id": "94232f8a-f001-3292-aa65-63fa9d981427",
"service_name": "SSH Server at 1.1.1.1:22",
"service_type": "SshServer"
}
}
}
Human Readable Output
External Service
Active Classifications Business Units Details Discovery Type Externally Detected Providers Externally Inferred Cves Externally Inferred Vulnerability Score First Observed Ip Address Is Active Last Observed Port Protocol Service Id Service Name Service Type SSHWeakMACAlgorithmsEnabled,
SshServer,
OpenSSHAcme serviceKey: 1.1.1.1:22
serviceKeyType: IP
businessUnits: {‘name’: ‘Acme’}
providerDetails: {‘name’: ‘AWS’, ‘firstObserved’: 1662774169000, ‘lastObserved’: 1663026500000}
certificates:
domains:
ips: {‘ip’: 873887795, ‘protocol’: ‘TCP’, ‘provider’: ‘AWS’, ‘geolocation’: {‘latitude’: 39.0438, ‘longitude’: -77.4879, ‘countryCode’: ‘US’, ‘city’: ‘ASHBURN’, ‘regionCode’: ‘VA’, ‘timeZone’: None}, ‘activityStatus’: ‘Active’, ‘lastObserved’: 1663026500000, ‘firstObserved’: 1662774169000}
classifications: {‘name’: ‘SshServer’, ‘activityStatus’: ‘Active’, ‘values’: [{‘jsonValue’: ‘{“version”:”2.0”,”serverVersion”:”OpenSSH_7.6p1”,”extraInfo”:”Ubuntu-4ubuntu0.7”}’, ‘firstObserved’: 1662774169000, ‘lastObserved’: 1663026500000}], ‘firstObserved’: 1662774120000, ‘lastObserved’: 1663026480000},
{‘name’: ‘SSHWeakMACAlgorithmsEnabled’, ‘activityStatus’: ‘Active’, ‘values’: [{‘jsonValue’: ‘{}’, ‘firstObserved’: 1662774169000, ‘lastObserved’: 1663026500000}], ‘firstObserved’: 1662774120000, ‘lastObserved’: 1663026480000},
{‘name’: ‘OpenSSH’, ‘activityStatus’: ‘Active’, ‘values’: [{‘jsonValue’: ‘{“version”:”7.6”}’, ‘firstObserved’: 1662774169000, ‘lastObserved’: 1663026500000}], ‘firstObserved’: 1662774120000, ‘lastObserved’: 1663026480000}
tlsVersions:
inferredCvesObserved: {‘inferredCve’: {‘cveId’: ‘CVE-2020-15778’, ‘cvssScoreV2’: 6.8, ‘cveSeverityV2’: ‘MEDIUM’, ‘cvssScoreV3’: 7.8, ‘cveSeverityV3’: ‘HIGH’, ‘inferredCveMatchMetadata’: {‘inferredCveMatchType’: ‘ExactVersionMatch’, ‘product’: ‘openssh’, ‘confidence’: ‘High’, ‘vendor’: ‘openbsd’, ‘version’: ‘7.6’}}, ‘activityStatus’: ‘Active’, ‘firstObserved’: 1662774169000, ‘lastObserved’: 1663026500000},
{‘inferredCve’: {‘cveId’: ‘CVE-2021-41617’, ‘cvssScoreV2’: 4.4, ‘cveSeverityV2’: ‘MEDIUM’, ‘cvssScoreV3’: 7.0, ‘cveSeverityV3’: ‘HIGH’, ‘inferredCveMatchMetadata’: {‘inferredCveMatchType’: ‘ExactVersionMatch’, ‘product’: ‘openssh’, ‘confidence’: ‘High’, ‘vendor’: ‘openbsd’, ‘version’: ‘7.6’}}, ‘activityStatus’: ‘Active’, ‘firstObserved’: 1662774169000, ‘lastObserved’: 1663026500000},
{‘inferredCve’: {‘cveId’: ‘CVE-2019-6110’, ‘cvssScoreV2’: 4.0, ‘cveSeverityV2’: ‘MEDIUM’, ‘cvssScoreV3’: 6.8, ‘cveSeverityV3’: ‘MEDIUM’, ‘inferredCveMatchMetadata’: {‘inferredCveMatchType’: ‘ExactVersionMatch’, ‘product’: ‘openssh’, ‘confidence’: ‘High’, ‘vendor’: ‘openbsd’, ‘version’: ‘7.6’}}, ‘activityStatus’: ‘Active’, ‘firstObserved’: 1662774169000, ‘lastObserved’: 1663026500000},
{‘inferredCve’: {‘cveId’: ‘CVE-2019-6109’, ‘cvssScoreV2’: 4.0, ‘cveSeverityV2’: ‘MEDIUM’, ‘cvssScoreV3’: 6.8, ‘cveSeverityV3’: ‘MEDIUM’, ‘inferredCveMatchMetadata’: {‘inferredCveMatchType’: ‘ExactVersionMatch’, ‘product’: ‘openssh’, ‘confidence’: ‘High’, ‘vendor’: ‘openbsd’, ‘version’: ‘7.6’}}, ‘activityStatus’: ‘Active’, ‘firstObserved’: 1662774169000, ‘lastObserved’: 1663026500000},
{‘inferredCve’: {‘cveId’: ‘CVE-2020-14145’, ‘cvssScoreV2’: 4.3, ‘cveSeverityV2’: ‘MEDIUM’, ‘cvssScoreV3’: 5.9, ‘cveSeverityV3’: ‘MEDIUM’, ‘inferredCveMatchMetadata’: {‘inferredCveMatchType’: ‘ExactVersionMatch’, ‘product’: ‘openssh’, ‘confidence’: ‘High’, ‘vendor’: ‘openbsd’, ‘version’: ‘7.6’}}, ‘activityStatus’: ‘Active’, ‘firstObserved’: 1662774169000, ‘lastObserved’: 1663026500000},
{‘inferredCve’: {‘cveId’: ‘CVE-2019-6111’, ‘cvssScoreV2’: 5.8, ‘cveSeverityV2’: ‘MEDIUM’, ‘cvssScoreV3’: 5.9, ‘cveSeverityV3’: ‘MEDIUM’, ‘inferredCveMatchMetadata’: {‘inferredCveMatchType’: ‘ExactVersionMatch’, ‘product’: ‘openssh’, ‘confidence’: ‘High’, ‘vendor’: ‘openbsd’, ‘version’: ‘7.6’}}, ‘activityStatus’: ‘Active’, ‘firstObserved’: 1662774169000, ‘lastObserved’: 1663026500000},
{‘inferredCve’: {‘cveId’: ‘CVE-2018-20685’, ‘cvssScoreV2’: 2.6, ‘cveSeverityV2’: ‘LOW’, ‘cvssScoreV3’: 5.3, ‘cveSeverityV3’: ‘MEDIUM’, ‘inferredCveMatchMetadata’: {‘inferredCveMatchType’: ‘ExactVersionMatch’, ‘product’: ‘openssh’, ‘confidence’: ‘High’, ‘vendor’: ‘openbsd’, ‘version’: ‘7.6’}}, ‘activityStatus’: ‘Active’, ‘firstObserved’: 1662774169000, ‘lastObserved’: 1663026500000},
{‘inferredCve’: {‘cveId’: ‘CVE-2018-15919’, ‘cvssScoreV2’: 5.0, ‘cveSeverityV2’: ‘MEDIUM’, ‘cvssScoreV3’: 5.3, ‘cveSeverityV3’: ‘MEDIUM’, ‘inferredCveMatchMetadata’: {‘inferredCveMatchType’: ‘ExactVersionMatch’, ‘product’: ‘openssh’, ‘confidence’: ‘High’, ‘vendor’: ‘openbsd’, ‘version’: ‘7.6’}}, ‘activityStatus’: ‘Active’, ‘firstObserved’: 1662774169000, ‘lastObserved’: 1663026500000},
{‘inferredCve’: {‘cveId’: ‘CVE-2016-20012’, ‘cvssScoreV2’: 4.3, ‘cveSeverityV2’: ‘MEDIUM’, ‘cvssScoreV3’: 5.3, ‘cveSeverityV3’: ‘MEDIUM’, ‘inferredCveMatchMetadata’: {‘inferredCveMatchType’: ‘ExactVersionMatch’, ‘product’: ‘openssh’, ‘confidence’: ‘High’, ‘vendor’: ‘openbsd’, ‘version’: ‘7.6’}}, ‘activityStatus’: ‘Active’, ‘firstObserved’: 1662774169000, ‘lastObserved’: 1663026500000},
{‘inferredCve’: {‘cveId’: ‘CVE-2018-15473’, ‘cvssScoreV2’: 5.0, ‘cveSeverityV2’: ‘MEDIUM’, ‘cvssScoreV3’: 5.3, ‘cveSeverityV3’: ‘MEDIUM’, ‘inferredCveMatchMetadata’: {‘inferredCveMatchType’: ‘ExactVersionMatch’, ‘product’: ‘openssh’, ‘confidence’: ‘High’, ‘vendor’: ‘openbsd’, ‘version’: ‘7.6’}}, ‘activityStatus’: ‘Active’, ‘firstObserved’: 1662774169000, ‘lastObserved’: 1663026500000},
{‘inferredCve’: {‘cveId’: ‘CVE-2021-36368’, ‘cvssScoreV2’: 2.6, ‘cveSeverityV2’: ‘LOW’, ‘cvssScoreV3’: 3.7, ‘cveSeverityV3’: ‘LOW’, ‘inferredCveMatchMetadata’: {‘inferredCveMatchType’: ‘ExactVersionMatch’, ‘product’: ‘openssh’, ‘confidence’: ‘High’, ‘vendor’: ‘openbsd’, ‘version’: ‘7.6’}}, ‘activityStatus’: ‘Active’, ‘firstObserved’: 1662774169000, ‘lastObserved’: 1663026500000}
enrichedObservationSource: CLOUD
ip_ranges: {}ColocatedOnIp Amazon Web Services CVE-2020-15778,
CVE-2021-41617,
CVE-2019-6110,
CVE-2019-6109,
CVE-2020-14145,
CVE-2019-6111,
CVE-2018-20685,
CVE-2018-15919,
CVE-2016-20012,
CVE-2018-15473,
CVE-2021-363687.8 1662774120000 1.1.1.1 Active 1663026480000 22 TCP 94232f8a-f001-3292-aa65-63fa9d981427 SSH Server at 1.1.1.1:22 SshServer
asm-list-external-ip-address-range
Get a list of all your internet exposure filtered by business units and organization handles. Maximum result limit is 100 ranges.
Base Command
asm-list-external-ip-address-range
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
| Path | Type | Description |
|---|---|---|
| ASM.ExternalIpAddressRange.range_id | String | External IP address range UUID. |
| ASM.ExternalIpAddressRange.first_ip | String | First IP address of the external IP address range. |
| ASM.ExternalIpAddressRange.last_ip | String | Last IP address of the external IP address range. |
| ASM.ExternalIpAddressRange.ips_count | Number | Number of IP addresses of the external IP address range. |
| ASM.ExternalIpAddressRange.active_responsive_ips_count | Number | The number of IPs in the external address range that are actively responsive. |
| ASM.ExternalIpAddressRange.date_added | Date | Date the external IP address range was added. |
| ASM.ExternalIpAddressRange.business_units | String | External IP address range associated business units. |
| ASM.ExternalIpAddressRange.organization_handles | String | External IP address range associated organization handles. |
Command example
#### Context Example
```json
{
"ASM": {
"ExternalIpAddressRange": [
{
"active_responsive_ips_count": 0,
"business_units": [
"VanDelay Industries"
],
"date_added": 1663031000145,
"first_ip": "1.1.1.1",
"ips_count": 64,
"last_ip": "1.1.1.1",
"organization_handles": [
"MAINT-HK-PCCW-BIA-CS",
"BNA2-AP",
"TA66-AP"
],
"range_id": "4da29b7f-3086-3b52-981b-aa8ee5da1e60"
},
{
"active_responsive_ips_count": 0,
"business_units": [
"VanDelay Industries"
],
"date_added": 1663031000144,
"first_ip": "1.1.1.1",
"ips_count": 16,
"last_ip": "1.1.1.1",
"organization_handles": [
"AR17615-RIPE",
"EASYNET-UK-MNT",
"JW372-RIPE",
"EH92-RIPE"
],
"range_id": "6ef4638e-7788-3ef5-98a5-ad5b7f4e02f5"
}
]
}
}
Human Readable Output
External IP Address Ranges
Active Responsive Ips Count Business Units Date Added First Ip Ips Count Last Ip Organization Handles Range Id 0 VanDelay Industries 1663031000145 1.1.1.1 64 1.1.1.1 MAINT-HK-PCCW-BIA-CS,
BNA2-AP,
TA66-AP4da29b7f-3086-3b52-981b-aa8ee5da1e60 0 VanDelay Industries 1663031000144 1.1.1.1 16 1.1.1.1 AR17615-RIPE,
EASYNET-UK-MNT,
JW372-RIPE,
EH92-RIPE6ef4638e-7788-3ef5-98a5-ad5b7f4e02f5
asm-get-external-ip-address-range
Get the external IP address range details according to the range IDs.
Base Command
asm-get-external-ip-address-range
Input
| Argument Name | Description | Required |
|---|---|---|
| range_id | A string representing the range ID for which you want to get the details. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| ASM.ExternalIpAddressRange.range_id | String | External IP address range UUID. |
| ASM.ExternalIpAddressRange.first_ip | String | First IP address of the external IP address range. |
| ASM.ExternalIpAddressRange.last_ip | String | Last IP address of the external IP address range. |
| ASM.ExternalIpAddressRange.ips_count | Number | Number of IP addresses of the external IP address range. |
| ASM.ExternalIpAddressRange.active_responsive_ips_count | Number | The number of IPs in the external address range that are actively responsive. |
| ASM.ExternalIpAddressRange.date_added | Date | Date the external IP address range was added. |
| ASM.ExternalIpAddressRange.business_units | String | External IP address range associated business units. |
| ASM.ExternalIpAddressRange.organization_handles | String | External IP address range associated organization handles. |
| ASM.ExternalIpAddressRange.details | String | Additional information. |
Command example
!asm-get-external-ip-address-range range_id=4da29b7f-3086-3b52-981b-aa8ee5da1e60
Context Example
{
"ASM": {
"ExternalIpAddressRange": {
"active_responsive_ips_count": 0,
"business_units": [
"VanDelay Industries"
],
"date_added": 1663031000145,
"details": {
"networkRecords": [
{
"firstIp": "1.1.1.1",
"handle": "1.1.1.1 - 1.1.1.1",
"lastChanged": 1663030241931,
"lastIp": "1.1.1.1",
"name": "SEARS-HK",
"organizationRecords": [
{
"address": "",
"dateAdded": 1663029346957,
"email": "noc@acme.com",
"firstRegistered": null,
"formattedName": "",
"handle": "MAINT-HK-PCCW-BIA-CS",
"kind": "group",
"lastChanged": null,
"org": "",
"phone": "",
"remarks": "",
"roles": [
"registrant"
]
},
{
"address": "27/F, PCCW Tower, Taikoo Place,\n979 King's Road, Quarry Bay, HK ",
"dateAdded": 1663029346957,
"email": "cs@acme.com",
"firstRegistered": 1220514857000,
"formattedName": "BIZ NETVIGATOR ADMINISTRATORS",
"handle": "BNA2-AP",
"kind": "group",
"lastChanged": 1514892767000,
"org": "",
"phone": "+852-2888-6932",
"remarks": "",
"roles": [
"administrative"
]
},
{
"address": "HKT Limited\nPO Box 9896 GPO ",
"dateAdded": 1663029346957,
"email": "noc@acme.com",
"firstRegistered": 1220514856000,
"formattedName": "TECHNICAL ADMINISTRATORS",
"handle": "TA66-AP",
"kind": "group",
"lastChanged": 1468555410000,
"org": "",
"phone": "+852-2883-5151",
"remarks": "",
"roles": [
"technical"
]
}
],
"remarks": "Sears Holdings Global Sourcing Ltd",
"whoIsServer": "whois.apnic.net"
}
]
},
"first_ip": "1.1.1.1",
"ips_count": 64,
"last_ip": "1.1.1.1",
"organization_handles": [
"MAINT-HK-PCCW-BIA-CS",
"BNA2-AP",
"TA66-AP"
],
"range_id": "4da29b7f-3086-3b52-981b-aa8ee5da1e60"
}
}
}
Human Readable Output
External IP Address Range
Active Responsive Ips Count Business Units Date Added First Ip Ips Count Last Ip Organization Handles Range Id 0 VanDelay Industries 1663031000145 networkRecords: {‘handle’: ‘1.1.1.1 - 1.1.1.1’, ‘firstIp’: ‘1.1.1.1’, ‘lastIp’: ‘1.1.1.1’, ‘name’: ‘SEARS-HK’, ‘whoIsServer’: ‘whois.apnic.net’, ‘lastChanged’: 1663030241931, ‘organizationRecords’: [{‘handle’: ‘MAINT-HK-PCCW-BIA-CS’, ‘dateAdded’: 1663029346957, ‘address’: ‘’, ‘email’: ‘noc@acme.com’, ‘phone’: ‘’, ‘org’: ‘’, ‘formattedName’: ‘’, ‘kind’: ‘group’, ‘roles’: [‘registrant’], ‘lastChanged’: None, ‘firstRegistered’: None, ‘remarks’: ‘’}, {‘handle’: ‘BNA2-AP’, ‘dateAdded’: 1663029346957, ‘address’: “27/F, PCCW Tower, Taikoo Place,\n979 King’s Road, Quarry Bay, HK “, ‘email’: ‘cs@acme.com’, ‘phone’: ‘+852-2888-6932’, ‘org’: ‘’, ‘formattedName’: ‘BIZ NETVIGATOR ADMINISTRATORS’, ‘kind’: ‘group’, ‘roles’: [‘administrative’], ‘lastChanged’: 1514892767000, ‘firstRegistered’: 1220514857000, ‘remarks’: ‘’}, {‘handle’: ‘TA66-AP’, ‘dateAdded’: 1663029346957, ‘address’: ‘HKT Limited\nPO Box 9896 GPO ‘, ‘email’: ‘noc@acme.com’, ‘phone’: ‘+852-2883-5151’, ‘org’: ‘’, ‘formattedName’: ‘TECHNICAL ADMINISTRATORS’, ‘kind’: ‘group’, ‘roles’: [‘technical’], ‘lastChanged’: 1468555410000, ‘firstRegistered’: 1220514856000, ‘remarks’: ‘’}], ‘remarks’: ‘Sears Holdings Global Sourcing Ltd’} 1.1.1.1 64 1.1.1.1 MAINT-HK-PCCW-BIA-CS,
BNA2-AP,
TA66-AP4da29b7f-3086-3b52-981b-aa8ee5da1e60
asm-list-asset-internet-exposure
Get a list of all your internet exposure filtered by IP address, domain, type, asm id, IPv6 address, AWS/GCP/Azure tags, has XDR agent, Externally detected providers, Externally inferred cves, Business units list, has BU overrides and/or if there is an active external service. Maximum result limit is 100 assets.
Base Command
asm-list-asset-internet-exposure
Input
| Argument Name | Description | Required |
|---|---|---|
| ip_address | IP address on which to search. | Optional |
| name | Name of the asset on which to search. | Optional |
| type | Type of the external service. Possible values are: certificate, cloud_compute_instance, on_prem, domain, unassociated_responsive_ip. | Optional |
| has_active_external_services | Whether the internet exposure has an active external service. Possible values are: yes, no. | Optional |
| asm_id_list | List of asm ids. | Optional |
| ipv6_address | IPv6 address on which to search. | Optional |
| gcp_cloud_tags | Search based on GCP cloud tags. | Optional |
| aws_cloud_tags | Search based on AWS cloud tags. | Optional |
| azure_cloud_tags | Search based on AZURE cloud tags. | Optional |
| has_xdr_agent | Search based on xdr agent. | Optional |
| externally_detected_providers | Search on externally detected providers. | Optional |
| externally_inferred_cves | Search on externally inferred cve. | Optional |
| business_units_list | Search on Business units list. | Optional |
| has_bu_overrides | Whether it has BU overrides. Possible values are: True, False. | Optional |
| mac_address | Search based on MAC address. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| ASM.AssetInternetExposure.asm_ids | String | Attack surface management UUID. |
| ASM.AssetInternetExposure.name | String | Name of the exposed asset. |
| ASM.AssetInternetExposure.asset_type | String | Type of the exposed asset. |
| ASM.AssetInternetExposure.cloud_provider | Unknown | The cloud provider used to collect these cloud assets as either GCP, AWS, or Azure. |
| ASM.AssetInternetExposure.region | Unknown | Displays the region as provided by the cloud provider. |
| ASM.AssetInternetExposure.last_observed | Unknown | Last time the exposure was observed. |
| ASM.AssetInternetExposure.first_observed | Unknown | First time the exposure was observed. |
| ASM.AssetInternetExposure.has_active_externally_services | Boolean | Whether the internet exposure is associated with an active external service(s). |
| ASM.AssetInternetExposure.has_xdr_agent | String | Whether the internet exposure asset has an XDR agent. |
| ASM.AssetInternetExposure.cloud_id | Unknown | Displays the resource ID as provided from the cloud provider. |
| ASM.AssetInternetExposure.domain_resolves | Boolean | Whether the asset domain is resolvable. |
| ASM.AssetInternetExposure.operation_system | Unknown | The operating system reported by the source for this asset. |
| ASM.AssetInternetExposure.agent_id | Unknown | If there is an endpoint installed on this asset, this is the endpoint ID. |
| ASM.AssetInternetExposure.externally_detected_providers | String | The provider of the asset as determined by an external assessment. |
| ASM.AssetInternetExposure.service_type | String | Type of the asset. |
| ASM.AssetInternetExposure.externally_inferred_cves | String | If the internet exposure has associated CVEs. |
| ASM.AssetInternetExposure.ips | String | IP addresses associated with the internet exposure. |
Command example
!asm-list-asset-internet-exposure name="acme.com" type=certificate has_active_external_services=no
Context Example
{
"ASM": {
"AssetInternetExposure": [
{
"agent_id": null,
"asm_ids": [
"cfa1cd5a-77f1-3963-8557-7f652309a143"
],
"asm_va_score": null,
"asset_type": "CERTIFICATE",
"business_units": [
"Acme",
"VanDelay Industries"
],
"certificate_algorithm": "SHA256withRSA",
"certificate_classifications": [
"LongExpiration",
"Wildcard",
"Expired"
],
"certificate_issuer": "DigiCert",
"cloud_id": null,
"cloud_provider": null,
"domain_resolves": false,
"externally_detected_providers": [],
"externally_inferred_cves": [],
"first_observed": null,
"has_active_externally_services": false,
"has_xdr_agent": "NA",
"iot_category": null,
"iot_model": null,
"iot_profile": null,
"ip_ranges": [],
"ips": [],
"last_observed": null,
"mac_addresses": [],
"management_status": [],
"name": "*.digital-dev.acme.com",
"operation_system": null,
"region": null,
"sensor": [
"XPANSE"
],
"service_type": []
},
{
"agent_id": null,
"asm_ids": [
"78a11e94-58a9-329c-99ca-e527d2db6cfb"
],
"asm_va_score": null,
"asset_type": "CERTIFICATE",
"business_units": [
"Acme",
"VanDelay Industries"
],
"certificate_algorithm": "SHA256withRSA",
"certificate_classifications": [
"LongExpiration",
"Wildcard",
"Expired"
],
"certificate_issuer": "DigiCert",
"cloud_id": null,
"cloud_provider": null,
"domain_resolves": false,
"externally_detected_providers": [],
"externally_inferred_cves": [],
"first_observed": null,
"has_active_externally_services": false,
"has_xdr_agent": "NA",
"iot_category": null,
"iot_model": null,
"iot_profile": null,
"ip_ranges": [],
"ips": [],
"last_observed": null,
"mac_addresses": [],
"management_status": [],
"name": "*.digital-prod.acme.com",
"operation_system": null,
"region": null,
"sensor": [
"XPANSE"
],
"service_type": []
}
]
}
}
Human Readable Output
Asset Internet Exposures
Asm Ids Asset Type Business Units Certificate Algorithm Certificate Classifications Certificate Issuer Domain Resolves Has Active Externally Services Has Xdr Agent Name Sensor cfa1cd5a-77f1-3963-8557-7f652309a143 CERTIFICATE Acme,
VanDelay IndustriesSHA256withRSA LongExpiration,
Wildcard,
ExpiredDigiCert false false NA *.digital-dev.acme.com XPANSE 78a11e94-58a9-329c-99ca-e527d2db6cfb CERTIFICATE Acme,
VanDelay IndustriesSHA256withRSA LongExpiration,
Wildcard,
ExpiredDigiCert false false NA *.digital-prod.acme.com XPANSE
asm-get-asset-internet-exposure
Get internet exposure asset details according to the asset ID.
Base Command
asm-get-asset-internet-exposure
Input
| Argument Name | Description | Required |
|---|---|---|
| asm_id | A string representing the asset ID for which you want to get the details. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| ASM.AssetInternetExposure.asm_ids | String | Attack surface management UUID. |
| ASM.AssetInternetExposure.name | String | Name of the exposed asset. |
| ASM.AssetInternetExposure.type | String | Type of the exposed asset. |
| ASM.AssetInternetExposure.last_observed | Unknown | Last time the exposure was observed. |
| ASM.AssetInternetExposure.first_observed | Unknown | First time the exposure was observed. |
| ASM.AssetInternetExposure.created | Date | Date the ASM issue was created. |
| ASM.AssetInternetExposure.business_units | String | Asset associated business units. |
| ASM.AssetInternetExposure.domain | Unknown | Asset associated domain. |
| ASM.AssetInternetExposure.certificate_issuer | String | Asset certificate issuer. |
| ASM.AssetInternetExposure.certificate_algorithm | String | Asset certificate algorithm. |
| ASM.AssetInternetExposure.certificate_classifications | String | Asset certificate.classifications. |
| ASM.AssetInternetExposure.resolves | Boolean | Whether the asset has a DNS resolution. |
| ASM.AssetInternetExposure.details | Unknown | Additional details. |
| ASM.AssetInternetExposure.externally_inferred_vulnerability_score | Unknown | Asset vulnerability score. |
Command example
!asm-get-asset-internet-exposure asm_id=3c176460-8735-333c-b618-8262e2fb660c
Context Example
{
"ASM": {
"AssetInternetExposure": {
"active_external_services_types": [],
"active_service_ids": [],
"all_service_ids": [],
"asm_ids": "3c176460-8735-333c-b618-8262e2fb660c",
"business_units": [
"Acme"
],
"certificate_algorithm": "SHA1withRSA",
"certificate_classifications": [
"Wildcard",
"Expired",
"InsecureSignature"
],
"certificate_issuer": "Thawte",
"created": 1663030146931,
"details": {
"businessUnits": [
{
"name": "Acme"
}
],
"certificateDetails": {
"formattedIssuerOrg": "Thawte",
"issuer": "C=US,O=Thawte\\, Inc.,CN=Thawte SSL CA",
"issuerAlternativeNames": "",
"issuerCountry": "US",
"issuerEmail": null,
"issuerLocality": null,
"issuerName": "Thawte SSL CA",
"issuerOrg": "Thawte\\\\, Inc.",
"issuerOrgUnit": null,
"issuerState": null,
"publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp21W/QVHuo0Nyy9l6Qp6Ye7yniuCccplWLdkL34pB0roNWBiklLJFftFTXJLtUuYEBhEbUtOPtNr5QRZFo+LQSj+JMQsGajEgNvIIMDms2xtc+vYkuJeNRsN/0zRm8iBjCNEZ0zBbWdupO6xee+Lngq5RiyRzAN2+Q5HlmHmVOcc7NtY5VIQhajp3a5Gc7tmLXa7ZxwQb+afdlpmE0iv4ZxmXFyHwlPXUlIxfETDDjtv2EzAgrnpZ5juo7TEFZA7AjsT0lO6cC2qPE9x9kC02PeC1Heg4hWf70CsXcKQBsprLqusrPYM9+OYfZnj+Dq9j6FjZD314Nz4qTGwmZrwDQIDAQAB",
"publicKeyAlgorithm": "RSA",
"publicKeyBits": 2048,
"publicKeyModulus": "a76d56fd0547ba8d0dcb2f65e90a7a61eef29e2b8271ca6558b7642f7e29074ae83560629252c915fb454d724bb54b981018446d4b4e3ed36be50459168f8b4128fe24c42c19a8c480dbc820c0e6b36c6d73ebd892e25e351b0dff4cd19bc8818c2344674cc16d676ea4eeb179ef8b9e0ab9462c91cc0376f90e479661e654e71cecdb58e5521085a8e9ddae4673bb662d76bb671c106fe69f765a661348afe19c665c5c87c253d75252317c44c30e3b6fd84cc082b9e96798eea3b4c415903b023b13d253ba702daa3c4f71f640b4d8f782d477a0e2159fef40ac5dc29006ca6b2eabacacf60cf7e3987d99e3f83abd8fa163643df5e0dcf8a931b0999af00d",
"publicKeyRsaExponent": 65537,
"publicKeySpki": "Up3fHwOddA9cXEeO4XBOgn63bfnvkXsOrOv6AycwQAk=",
"serialNumber": "91384582774546160650506315451812470612",
"sha1Fingerprint": "77d025c36f055e254063ae2ac3625fd4bf4507fb",
"sha256Fingerprint": "9a37c952ee1169cfa6e91efb57fe6d405d1ca48b26a714e9a46f008c15ea62e8",
"signatureAlgorithm": "SHA1withRSA",
"subject": "C=US,ST=New Jersey,L=Wayne,O=Acme,OU=MIS,CN=*.babiesrus.com",
"subjectAlternativeNames": "*.babiesrus.com",
"subjectCountry": "US",
"subjectEmail": null,
"subjectLocality": "Wayne",
"subjectName": "*.babiesrus.com",
"subjectOrg": "Acme",
"subjectOrgUnit": "MIS",
"subjectState": "New Jersey",
"validNotAfter": 1444780799000,
"validNotBefore": 1413158400000,
"version": "3"
},
"dnsZone": null,
"domain": null,
"domainAssetType": null,
"domainDetails": null,
"inferredCvesObserved": [],
"ip_ranges": {},
"isPaidLevelDomain": false,
"latestSampledIp": null,
"providerDetails": [],
"recentIps": [],
"subdomainMetadata": null,
"topLevelAssetMapperDomain": null
},
"domain": null,
"external_services": [],
"externally_detected_providers": [],
"externally_inferred_cves": [],
"externally_inferred_vulnerability_score": null,
"first_observed": null,
"ips": [],
"last_observed": null,
"name": "*.babiesrus.com",
"resolves": false,
"type": "Certificate"
}
}
}
Human Readable Output
Asset Internet Exposure
Asm Ids Business Units Certificate Algorithm Certificate Classifications Certificate Issuer Created Details Name Resolves Type 3c176460-8735-333c-b618-8262e2fb660c Acme SHA1withRSA Wildcard,
Expired,
InsecureSignatureThawte 1663030146931 providerDetails:
domain: null
topLevelAssetMapperDomain: null
domainAssetType: null
isPaidLevelDomain: false
domainDetails: null
dnsZone: null
latestSampledIp: null
subdomainMetadata: null
recentIps:
businessUnits: {‘name’: ‘Acme’}
certificateDetails: {“issuer”: “C=US,O=Thawte\, Inc.,CN=Thawte SSL CA”, “issuerAlternativeNames”: “”, “issuerCountry”: “US”, “issuerEmail”: null, “issuerLocality”: null, “issuerName”: “Thawte SSL CA”, “issuerOrg”: “Thawte\\, Inc.”, “formattedIssuerOrg”: “Thawte”, “issuerOrgUnit”: null, “issuerState”: null, “publicKey”: “MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp21W/QVHuo0Nyy9l6Qp6Ye7yniuCccplWLdkL34pB0roNWBiklLJFftFTXJLtUuYEBhEbUtOPtNr5QRZFo+LQSj+JMQsGajEgNvIIMDms2xtc+vYkuJeNRsN/0zRm8iBjCNEZ0zBbWdupO6xee+Lngq5RiyRzAN2+Q5HlmHmVOcc7NtY5VIQhajp3a5Gc7tmLXa7ZxwQb+afdlpmE0iv4ZxmXFyHwlPXUlIxfETDDjtv2EzAgrnpZ5juo7TEFZA7AjsT0lO6cC2qPE9x9kC02PeC1Heg4hWf70CsXcKQBsprLqusrPYM9+OYfZnj+Dq9j6FjZD314Nz4qTGwmZrwDQIDAQAB”, “publicKeyAlgorithm”: “RSA”, “publicKeyRsaExponent”: 65537, “signatureAlgorithm”: “SHA1withRSA”, “subject”: “C=US,ST=New Jersey,L=Wayne,O=Acme,OU=MIS,CN=.babiesrus.com”, “subjectAlternativeNames”: “.babiesrus.com”, “subjectCountry”: “US”, “subjectEmail”: null, “subjectLocality”: “Wayne”, “subjectName”: “*.babiesrus.com”, “subjectOrg”: “Acme”, “subjectOrgUnit”: “MIS”, “subjectState”: “New Jersey”, “serialNumber”: “91384582774546160650506315451812470612”, “validNotBefore”: 1413158400000, “validNotAfter”: 1444780799000, “version”: “3”, “publicKeyBits”: 2048, “publicKeyModulus”: “a76d56fd0547ba8d0dcb2f65e90a7a61eef29e2b8271ca6558b7642f7e29074ae83560629252c915fb454d724bb54b981018446d4b4e3ed36be50459168f8b4128fe24c42c19a8c480dbc820c0e6b36c6d73ebd892e25e351b0dff4cd19bc8818c2344674cc16d676ea4eeb179ef8b9e0ab9462c91cc0376f90e479661e654e71cecdb58e5521085a8e9ddae4673bb662d76bb671c106fe69f765a661348afe19c665c5c87c253d75252317c44c30e3b6fd84cc082b9e96798eea3b4c415903b023b13d253ba702daa3c4f71f640b4d8f782d477a0e2159fef40ac5dc29006ca6b2eabacacf60cf7e3987d99e3f83abd8fa163643df5e0dcf8a931b0999af00d”, “publicKeySpki”: “Up3fHwOddA9cXEeO4XBOgn63bfnvkXsOrOv6AycwQAk=”, “sha1Fingerprint”: “77d025c36f055e254063ae2ac3625fd4bf4507fb”, “sha256Fingerprint”: “9a37c952ee1169cfa6e91efb57fe6d405d1ca48b26a714e9a46f008c15ea62e8”, “md5Fingerprint”: “498ec19ebd6c6883ecd43d064e713002”}
inferredCvesObserved:
ip_ranges: {}*.babiesrus.com false Certificate
asm-list-remediation-rule
Returns the list of remediation path rules. This command applies only to Expander v2.
Base Command
asm-list-remediation-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| asm_rule_id | A string representing the ASM rule ID you want to get the associated remediation path rules for. | Required |
| sort_by_creation_time | Sorts returned incidents by the date/time that the incident was created (“asc” - ascending, “desc” - descending). Possible values are: asc, desc. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| ASM.RemediationRule.rule_id | String | Remediation path rule UUID. |
| ASM.RemediationRule.rule_name | String | Remediation path rule name. |
| ASM.RemediationRule.description | String | Remediation path rule description. |
| ASM.RemediationRule.attack_surface_rule_id | String | Association ASM rule ID for the remediation path rules. |
| ASM.RemediationRule.criteria | Unknown | Array of remediation path rule criteria. |
| ASM.RemediationRule.criteria_conjunction | String | Whether criteria is processed with AND or OR. |
| ASM.RemediationRule.action | String | Action to take on rule match. |
| ASM.RemediationRule.created_by | String | Email of who created the rule. |
| ASM.RemediationRule.created_by_pretty | String | Readable name of who created the rule. |
| ASM.RemediationRule.created_at | Date | Date the rule was created. |
Command example
!asm-list-remediation-rule asm_rule_id=RdpServer sort_by_creation_time=desc
Context Example
{
"ASM": {
"RemediationRule": {
"action": "Email",
"attack_surface_rule_id": "RdpServer",
"created_at": 1672897301000,
"created_by": "test@test.com",
"created_by_pretty": "Test User",
"criteria": [
{
"field": "severity",
"operator": "eq",
"value": "high"
},
{
"field": "isCloudManaged",
"operator": "eq",
"value": "true"
}
],
"criteria_conjunction": "AND",
"description": "for testing",
"rule_id": "b935cf69-add9-4e75-8c3d-fe32ee471554",
"rule_name": "TestRule"
}
}
}
Human Readable Output
Remediation Rules
Action Attack Surface Rule Id Created At Created By Created By Pretty Criteria Criteria Conjunction Description Rule Id Rule Name RdpServer 1672897301000 test@test.com Test User {‘field’: ‘severity’, ‘value’: ‘high’, ‘operator’: ‘eq’},
{‘field’: ‘isCloudManaged’, ‘value’: ‘true’, ‘operator’: ‘eq’}AND for testing b935cf69-add9-4e75-8c3d-fe32ee471554 TestRule
asm-start-remediation-confirmation-scan
Starts a new Remediation Confirmation Scan or gets an existing scan ID.
Base Command
asm-start-remediation-confirmation-scan
Input
| Argument Name | Description | Required |
|---|---|---|
| service_id | The ID of the service in Cortex Xpanse associated with the alert. | Required |
| attack_surface_rule_id | The Cortex Xpanse attack surface rule associated with the alert. | Required |
| alert_internal_id | The Cortex Xpanse alert ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| ASM.RemediationScan.scanId | string | The ID returned for the created or existing scan. |
| ASM.RemediationScan.scan_creation_status | string | The creation status of the scan (based on HTTP status). |
Command example
!asm-start-remediation_confirmation_scan service_id="abc12345-abab-1212-1212-abc12345abcd" attack_surface_rule_id="InsecureOpenSSH" alert_internal_id="1"
Context Example
{
"ASM": {
"RemediationScan": {
"scanId": "abcdef12-3456-789a-bcde-fgh012345678",
"scan_creation_status": "created"
}
}
}
Human Readable Output
Creation of Remediation Confirmation Scan
Scanid Scan Creation Status abcdef12-3456-789a-bcde-fgh012345678 created
asm-get-remediation-confirmation-scan-status
Get the status of an existing Remediation Confirmation Scan.
Base Command
asm-get-remediation-confirmation-scan-status
Input
| Argument Name | Description | Required |
|---|---|---|
| scan_id | The ID of an existing remediation confirmation scan. | Required |
| interval_in_seconds | The interval, in seconds, to poll for scan results of an existing Remediation Confirmation Scan. Default is 600. | Optional |
| timeout_in_seconds | The timeout, in seconds, for polling for scan results of an existing Remediation Confirmation Scan. Default is 11000. | Optional |
| hide_polling_output | Whether to hide the polling result (automatically filled by polling). | Optional |
| polling | Whether to poll until there is at least one result. Possible values are: true, false. Default is true. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| ASM.RemediationScan.status | string | Status of the Remediation Confirmation Scan. |
| ASM.RemediationScan.result | string | Result of the Remediation Confirmation Scan. |
Command example
!asm-get-remediation-confirmation-scan-status scan_id="abcdef12-3456-789a-bcde-fgh012345678"
Context Example
{
"ASM": {
"RemediationScan": {
"status": "SUCCESS", // Required
"result": "REMEDIATED" // Optional (If not SUCCESS)
}
}
}
Human Readable Output
Status of Remediation Confirmation Scan
status result SUCCESS REMEDIATED
asm-get-attack-surface-rule
Get information of an attack surface rule ID.
Base Command
asm-get-attack-surface-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| attack_surface_rule_id | A comma-separated list of attack surface rule IDs. For example: RdpServer,InsecureOpenSSH. | Optional |
| enabled_status | Get the info about rule IDs with enabled status on or off. Has to be comma separated. For example: on,off. | Optional |
| priority | Get the info about rule IDs with a priority. Has to be comma separated. For example: high,medium. | Optional |
| category | Get the info about rule IDs of a category. Has to be comma separated. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| ASM.AttackSurfaceRule.attack_surface_rule_id | unknown | Attack surface rule ID. |
| ASM.AttackSurfaceRule.attack_surface_rule_name | unknown | Attack surface rule name. |
| ASM.AttackSurfaceRule.category | unknown | Attack surface rule category. |
| ASM.AttackSurfaceRule.enabled_status | unknown | Attack surface rule status. |
| ASM.AttackSurfaceRule.priority | unknown | Attack surface rule priority. |
| ASM.AttackSurfaceRule.remediation_guidance | unknown | Remediation guidance of attack surface rule. |
Command example
!asm-get-attack-surface-rule attack_surface_rule_id=RdpServer raw-response=true
Context Example
{
"reply": {
"attack_surface_rules": [
{
"attack_surface_rule_id": "RdpServer",
"attack_surface_rule_name": "RDP Server",
"category": "Attack Surface Reduction",
"created": 1698113023000,
"description": "Remote Desktop Protocol (RDP) servers provide remote access to a computer over a network connection. Externally accessible RDP servers pose a significant security risk as they are frequent targets for attackers and can be vulnerable to a variety of documented exploits.",
"enabled_status": "ON",
"knowledge_base_link": null,
"modified": 1605140275000,
"modified_by": null,
"priority": "High",
"remediation_guidance": "Recommendations to reduce the likelihood of malicious RDP attempts are as follows:\n\n1. Best practice is to not have RDP publicly accessible on the Internet and instead only on trusted local networks.\n2. Implement a risk-based approach that prioritizes patching RDP vulnerabilities that have known weaponized public exploits.\n3. Limit RDP access to a specific user group and implementing lockout policies is an additional measure to protect against RDP brute-forcing which is another common tactic used by attackers. In addition, enable NLA (Network Level Authentication) which is non-default on older versions.\n4. If remote access to RDP or terminal services is a business requirement, it should only be made accessible through a secure Virtual Private Network (VPN) connection with multi-factor authentication (MFA) to the corporate network or through a zero-trust remote access gateway."
}
],
"result_count": 1,
"total_count": 1
}
}
Human Readable Output
Results
ATTACK_SURFACE_RULE_ID ATTACK_SURFACE_RULE_NAME CATEGORY CREATED DESCRIPTION ENABLED_STATUS KNOWLEDGE_BASE_LINK MODIFIED MODIFIED_BY PRIORITY REMEDIATION_GUIDANCE RdpServer RDP Server Attack Surface Reduction 1698113023000 Remote Desktop Protocol (RDP) servers provide remote access to a computer over a network connection. Externally accessible RDP servers pose a significant security risk as they are frequent targets for attackers and can be vulnerable to a variety of documented exploits. ON 1605140275000 High Recommendations to reduce the likelihood of malicious RDP attempts are as follows:\n\n1. Best practice is to not have RDP publicly accessible on the Internet and instead only on trusted local networks.\n2. Implement a risk-based approach that prioritizes patching RDP vulnerabilities that have known weaponized public exploits.\n3. Limit RDP access to a specific user group and implementing lockout policies is an additional measure to protect against RDP brute-forcing which is another common tactic used by attackers. In addition, enable NLA (Network Level Authentication) which is non-default on older versions.\n4. If remote access to RDP or terminal services is a business requirement, it should only be made accessible through a secure Virtual Private Network (VPN) connection with multi-factor authentication (MFA) to the corporate network or through a zero-trust remote access gateway
Configuration parameters
url— Server URL (required)credentials— API Key ID (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (10)
-
asm-get-asset-internet-exposureGet internet exposure asset details according to the asset ID.
-
asm-get-attack-surface-ruleGet information of an attack surface rule ID.
-
asm-get-external-ip-address-rangeGet the external IP address range details according to the range IDs.
-
asm-get-external-serviceGet service details according to the service ID.
-
asm-get-remediation-confirmation-scan-statusGet the status of an existing Remediation Confirmation Scan.
-
asm-list-asset-internet-exposureGet a list of all your internet exposure filtered by IP address, domain, type, asm id, IPv6 address, AWS/GCP/Azure tags, has XDR agent, Externally detected providers, Externally inferred cves, Business units list, has BU overrides and/or if there is an active external service. Maximum result limit is 100 assets.
-
asm-list-external-ip-address-rangeGet a list of all your internet exposure filtered by business units and organization handles. Maximum result limit is 100 ranges.
-
asm-list-external-serviceGet a list of all your external services filtered by business units, externally detected providers, domain, externally inferred CVEs, active classifications, inactive classifications, service name, service type, protocol, IP address, is active, and discovery type. Maximum result limit is 100 assets.
-
asm-list-remediation-ruleReturns the list of remediation path rules. This command applies only to Expander v2.
-
asm-start-remediation-confirmation-scanStarts a new Remediation Confirmation Scan or gets an existing scan ID.
import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 import urllib3 from typing import Any from requests import Response # Used to typing Response as a return from functions # Disable insecure warnings urllib3.disable_warnings() DEFAULT_SEARCH_LIMIT = 100 class NotFoundError(Exception): """Exception raised when an error is encountered that does not have an error message, like with a waitress error""" class ProcessingError(Exception): """Exception raised when a 500 error is returned from the API with a json body containing an error code and message""" class Client(BaseClient): """ Client class to interact with the service API. """ def __init__(self, base_url, verify, proxy, headers): """ Class initialization. """ super().__init__(base_url, verify=verify, proxy=proxy, headers=headers) def list_remediation_rule_request(self, request_data: dict) -> dict[str, Any]: """Get a list of all your remediation rules using the 'xpanse_remediation_rules/rules/' endpoint. Args: request_data (dict): dict of parameters for API call. Returns: dict: dict containing list of external services. """ response = self._http_request( "POST", "/xpanse_remediation_rules/rules/", json_data=request_data, error_handler=get_api_error, ) return response def list_external_service_request(self, search_params: list[dict]) -> dict[str, Any]: """Get a list of all your external services using the '/assets/get_external_services/' endpoint. Args: search_params (list): list of search parameters to add to the API call body. Returns: dict: dict containing list of external services. """ data = {"request_data": {"filters": search_params, "search_to": DEFAULT_SEARCH_LIMIT}} response = self._http_request( "POST", "/assets/get_external_services/", json_data=data, error_handler=get_api_error, ) return response def get_external_service_request(self, service_id_list: list[str]) -> dict[str, Any]: """Get service details using the '/assets/get_external_service/' endpoint. Args: service_id_list (list): single service id in list format. Returns: dict: dict containing information on single external service. """ data = {"request_data": {"service_id_list": service_id_list}} response = self._http_request( "POST", "/assets/get_external_service", json_data=data, error_handler=get_api_error, ) return response def list_external_ip_address_range_request(self) -> dict[str, Any]: """Get a list of all your internet exposure IP ranges using the '/assets/get_external_ip_address_ranges/' endpoint. Returns: dict: dict containing list of external ip address ranges. """ data = {"request_data": {"search_to": DEFAULT_SEARCH_LIMIT}} response = self._http_request( "POST", "/assets/get_external_ip_address_ranges/", json_data=data, error_handler=get_api_error, ) return response def get_external_ip_address_range_request(self, range_id_list: list[str]) -> dict[str, Any]: """Get external IP address range details using the '/assets/get_external_ip_address_range/' endpoint. Args: range_id_list (list): single range id in list format. Returns: dict: dict containing information on external ip address range. """ data = {"request_data": {"range_id_list": range_id_list}} response = self._http_request( "POST", "/assets/get_external_ip_address_range/", json_data=data, error_handler=get_api_error, ) return response def get_attack_surface_rule_request(self, search_params: list[dict]) -> dict[str, Any]: """Get Attack Surface Rule details for an attack surface rule id using the '/get_attack_surface_rules/' endpoint. Args: attack_surface_rule_id (str): Coma separated attack surface rule ids. Returns: dict: dict containing information about Attack surface rule. """ data = {"request_data": {"filters": search_params}} response = self._http_request("POST", "/get_attack_surface_rules/", json_data=data, error_handler=get_api_error) return response def list_asset_internet_exposure_request(self, search_params: list[dict]) -> dict[str, Any]: """Get a list of all your internet exposure assets using the '/assets/get_assets_internet_exposure/' endpoint. Args: search_params (list): list of search parameters to add to the API call body. Returns: dict: dict containing list of internet exposure assets. """ data = {"request_data": {"filters": search_params, "search_to": DEFAULT_SEARCH_LIMIT}} response = self._http_request( "POST", "/assets/get_assets_internet_exposure/", json_data=data, error_handler=get_api_error, ) return response def get_asset_internet_exposure_request(self, asm_id_list: list[str]) -> dict[str, Any]: """Get internet exposure asset details using the '/assets/get_asset_internet_exposure/' endpoint. Args: asm_id_list (list): single attack surface management id in list format. Returns: dict: dict containing information on an internet exposure asset. """ data = {"request_data": {"asm_id_list": asm_id_list}} response = self._http_request( "POST", "/assets/get_asset_internet_exposure/", json_data=data, error_handler=get_api_error, ) return response def start_remediation_confirmation_scan( self, alert_internal_id: int, service_id: str, attack_surface_rule_id: str ) -> Response: """Retrieves ID of active (running) scan if it already exists for the given service; otherwise, creates new a scan. Args: alert_internal_id (str): _description_ service_id (str): _description_ attack_surface_rule_id (str): _description_ Returns: Dict[str, Any]: dictionary containing response information that includes a scan ID. """ data = { "request_data": { "filters": [ { "field": "attack_surface_rule_id", "operator": "EQ", "value": attack_surface_rule_id, }, { "field": "alert_internal_id", "operator": "EQ", "value": alert_internal_id, }, {"field": "service_id", "operator": "EQ", "value": service_id}, ] } } response = self._http_request( method="POST", url_suffix="remediation_confirmation_scanning/requests/get_or_create/", json_data=data, resp_type="response", error_handler=get_api_error, ) return response def get_remediation_confirmation_scan_status(self, scan_id: str) -> Response: """Retrieves ID of active (running) scan if it already exists for the given service; otherwise, creates new a scan. Args: alert_internal_id (str): _description_ service_id (str): _description_ attack_surface_rule_id (str): _description_ Returns: Dict[str, Any]: dictionary containing response information that includes a scan ID. """ data = {"request_data": {"filters": [{"field": "id", "operator": "EQ", "value": scan_id}]}} response = self._http_request( method="POST", url_suffix="/remediation_confirmation_scanning/requests/get/", json_data=data, resp_type="response", error_handler=get_api_error, ) return response """ HELPER FUNCTIONS """ def append_search_param(search_params, field, operator, value): """ Appends a search parameter to the given list of search parameters. Args: search_params (list): The list of search parameters to append to. field (str): The name of the field to search on. operator (str): The operator to use for the search (e.g. "eq", "contains", "in"). value (any): The value to search for. Returns: None """ search_params.append({"field": field, "operator": operator, "value": value}) def format_asm_id(formatted_response: list[dict]) -> list[dict]: """ Takes the response from the asm-list-asset-internet-exposure command and converts `asm_id` key from list to str Args: formatted_response (list): response from asm-list-asset-internet-exposure command (json) Returns: list: list of dictionaries of parsed/formatted json object """ if formatted_response: for entry in formatted_response: if entry.get("asm_ids"): entry["asm_ids"] = entry["asm_ids"][0] return formatted_response def get_api_error(response: Response): """Raises a formatted error based on the response from the base_error file from the server. Args: response: Response object from an API endpoint. Raises: NotFoundError: Exception for when an API endpoint returns an error that does not have a corresponding error message. ProcessingError: Exception for when an API endpoint returns an error message. """ error_code, error_message, extra_message, rcs_err_msg = "", "", "", "" try: json_response = response.json() error_code = json_response.get("reply", {}).get("err_code", {}) error_message = json_response.get("reply", {}).get("err_msg", {}) extra_message = json_response.get("reply", {}).get("err_extra", {}) rcs_err_msg = f"{error_message}. {extra_message}" response.raise_for_status() except requests.exceptions.HTTPError as err: if "Forbidden" not in str(err): raise ProcessingError(f"{error_code} - Received error message: '{rcs_err_msg}'.") else: pass except (AttributeError, TypeError) as err: if "Forbidden" not in str(err): raise NotFoundError(f"{type(err).__name__} - {str(err)}") """ COMMAND FUNCTIONS """ def list_remediation_rule_command(args: dict[str, Any], client: Client) -> CommandResults: """ asm-list-remediation-rule command: Returns list of remediation path rules. Args: client (Client): CortexAttackSurfaceManagment client to use. args (dict): all command arguments, usually passed from ``demisto.args()``. ``args['asm_rule_id']`` A string representing the ASM Rule ID you want to get association remediation path rules for. ``args['sort_by_creation_time']`` optional - enum (asc,desc). Returns: CommandResults: A ``CommandResults`` object that is then passed to ``return_results``, that contains list of remediation path rules. """ asm_rule_id = str(args.get("asm_rule_id")) sort_by_creation_time = args.get("sort_by_creation_time") # create list of search parameters or pass empty list. search_params = [] if asm_rule_id: search_params.append({"field": "attack_surface_rule_id", "operator": "eq", "value": asm_rule_id}) if sort_by_creation_time: request_data = { "request_data": { "filters": search_params, "search_from": 0, "search_to": DEFAULT_SEARCH_LIMIT, "sort": {"field": "created_at", "keyword": sort_by_creation_time}, } } else: request_data = { "request_data": { "filters": search_params, "search_from": 0, "search_to": DEFAULT_SEARCH_LIMIT, } } response = client.list_remediation_rule_request(request_data) parsed = response.get("reply", {}).get("remediation_rules") markdown = tableToMarkdown( "Remediation Rules", parsed, removeNull=True, headerTransform=string_to_table_header, ) command_results = CommandResults( outputs_prefix="ASM.RemediationRule", outputs_key_field="rule_id", outputs=parsed, raw_response=response, readable_output=markdown, ) return command_results def list_external_service_command(args: dict[str, Any], client: Client) -> CommandResults: """ asm-list-external-service command: Returns list of external services. Args: client (Client): CortexAttackSurfaceManagment client to use. args (dict): all command arguments, usually passed from ``demisto.args()``. ``args['ip_address']`` IP Address to search on. ``args['domain']`` Domain to search on. ``args['is_active']`` If the service active or not. ``args['discovery_type']`` how service was discovered. Returns: CommandResults: A ``CommandResults`` object that is then passed to ``return_results``, that contains external services. """ ip_address = args.get("ip_address") domain = args.get("domain") is_active = args.get("is_active") discovery_type = args.get("discovery_type") # create list of search parameters or pass empty list. search_params = [] if ip_address: search_params.append({"field": "ip_address", "operator": "eq", "value": ip_address}) if domain: search_params.append({"field": "domain", "operator": "contains", "value": domain}) if is_active: search_params.append({"field": "is_active", "operator": "in", "value": [is_active]}) if discovery_type: search_params.append({"field": "discovery_type", "operator": "in", "value": [discovery_type]}) response = client.list_external_service_request(search_params) parsed = response.get("reply", {}).get("external_services") markdown = tableToMarkdown( "External Services", parsed, removeNull=True, headerTransform=string_to_table_header, ) command_results = CommandResults( outputs_prefix="ASM.ExternalService", outputs_key_field="service_id", outputs=parsed, raw_response=response, readable_output=markdown, ) return command_results def get_external_service_command(args: dict[str, Any], client: Client) -> CommandResults: """ asm-get-external-service command: Returns details of single external service. Returns error if more than one service_id was provided in comma separated format. Args: client (Client): CortexAttackSurfaceManagment client to use. args (dict): all command arguments, usually passed from ``demisto.args()``. ``args['service_id']`` A string representing the service ID you want to get details for. Returns: CommandResults: A ``CommandResults`` object that is then passed to ``return_results``, that contains external service information. """ # assume that only one service_id was passed in or fail. service_id = str(args.get("service_id")) service_id_list = service_id.split(",") if len(service_id_list) > 1: raise ValueError("This command only supports one service_id at this time") response = client.get_external_service_request(service_id_list) parsed = response.get("reply", {}).get("details") markdown = tableToMarkdown( "External Service", parsed, removeNull=True, headerTransform=string_to_table_header, ) command_results = CommandResults( outputs_prefix="ASM.ExternalService", outputs_key_field="service_id", outputs=parsed, raw_response=response, readable_output=markdown, ) return command_results def list_external_ip_address_range_command(args: dict[str, Any], client: Client) -> CommandResults: """ asm-list-external-ip-address-range command: Returns list of external ip ranges. Args: client (Client): CortexAttackSurfaceManagment client to use. args (dict): all command arguments, usually passed from ``demisto.args()`` (not used in this function). Returns: CommandResults: A ``CommandResults`` object that is then passed to ``return_results``, that contains external IP address ranges. """ response = client.list_external_ip_address_range_request() parsed = response.get("reply", {}).get("external_ip_address_ranges") markdown = tableToMarkdown( "External IP Address Ranges", parsed, removeNull=True, headerTransform=string_to_table_header, ) command_results = CommandResults( outputs_prefix="ASM.ExternalIpAddressRange", outputs_key_field="range_id", outputs=parsed, raw_response=response, readable_output=markdown, ) return command_results def get_external_ip_address_range_command(args: dict[str, Any], client: Client) -> CommandResults: """ asm-get-external-ip-address-range command: Returns details of single external ip range. Returns error if more than one range_id was provided in comma separated format. Args: client (Client): CortexAttackSurfaceManagment client to use. args (dict): all command arguments, usually passed from ``demisto.args()``. ``args['range_id']`` A string representing the range ID for which you want to get the details for. Returns: CommandResults: A ``CommandResults`` object that is then passed to ``return_results``, that contains external ip range information. """ # assume that only one range_id was passed in or fail. range_id = str(args.get("range_id")) range_id_list = range_id.split(",") if len(range_id_list) > 1: raise ValueError("This command only supports one range_id at this time") response = client.get_external_ip_address_range_request(range_id_list) parsed = response.get("reply", {}).get("details") markdown = tableToMarkdown( "External IP Address Range", parsed, removeNull=True, headerTransform=string_to_table_header, ) command_results = CommandResults( outputs_prefix="ASM.ExternalIpAddressRange", outputs_key_field="range_id", outputs=parsed, raw_response=response, readable_output=markdown, ) return command_results def get_attack_surface_rule_command(args: dict[str, Any], client: Client) -> CommandResults: """ asm-get-attack-surface-rule command: Returns attack surface rule details. Args: client (Client): CortexAttackSurfaceManagment client to use. args (dict): all command arguments, usually passed from ``demisto.args()`` Returns: CommandResults: A ``CommandResults`` object that is then passed to ``return_results``, that contains Remediation guidance information. """ attack_surface_rule_id = args.get("attack_surface_rule_id") enabled_status = args.get("enabled_status") priority = args.get("priority") category = args.get("category") search_params = [] if attack_surface_rule_id: search_params.append({"field": "attack_surface_rule_id", "operator": "in", "value": attack_surface_rule_id.split(",")}) if enabled_status: search_params.append({"field": "enabled_status", "operator": "in", "value": enabled_status.split(",")}) if priority: search_params.append({"field": "priority", "operator": "in", "value": priority.split(",")}) if category: search_params.append({"field": "category", "operator": "in", "value": category.split(",")}) response = client.get_attack_surface_rule_request(search_params) parsed = response.get("reply", {}).get("attack_surface_rules") command_results = CommandResults( outputs_prefix="ASM.AttackSurfaceRule", outputs_key_field="attack_surface_rule", outputs=parsed, raw_response=response, ) return command_results def list_asset_internet_exposure_command(args: dict[str, Any], client: Client) -> CommandResults: """ asm-list-asset-internet-exposure command: Returns list of external internet exposures. Args: client (Client): CortexAttackSurfaceManagment client to use. args (dict): all command arguments, usually passed from ``demisto.args()``. ``args['ip_address']`` IP Address to search on. ``args['name']`` name of asset to search on. ``args['type']`` type of external service. ``args['has_active_external_services']`` if the internet exposure have an active external service. Returns: CommandResults: A ``CommandResults`` object that is then passed to ``return_results``, that contains external internet exposures. """ ip_address = args.get("ip_address") name = args.get("name") asm_type = args.get("type") has_active_external_services = args.get("has_active_external_services") asm_id_list = args.get("asm_id_list") ipv6_address = args.get("ipv6_address") gcp_cloud_tags = args.get("gcp_cloud_tags") azure_cloud_tags = args.get("azure_cloud_tags") aws_cloud_tags = args.get("aws_cloud_tags") has_xdr_agent = args.get("has_xdr_agent") externally_detected_providers = args.get("externally_detected_providers") externally_inferred_cves = args.get("externally_inferred_cves") business_units_list = args.get("business_units_list") has_bu_overrides = args.get("has_bu_overrides") mac_addresses = args.get("mac_addresses") # create list of search parameters or pass empty list. search_params: list[dict[str, Any]] = [] if ip_address: append_search_param(search_params, "ip_address", "eq", ip_address) if name: append_search_param(search_params, "name", "contains", name) if asm_type: append_search_param(search_params, "type", "in", [asm_type]) if has_active_external_services: append_search_param(search_params, "has_active_external_services", "in", [has_active_external_services]) if asm_id_list: append_search_param(search_params, "asm_id_list", "in", str(asm_id_list).split(",")) if ipv6_address: append_search_param(search_params, "ipv6_address", "eq", str(ipv6_address)) if aws_cloud_tags: append_search_param(search_params, "aws_cloud_tags", "in", str(aws_cloud_tags).split(",")) if gcp_cloud_tags: append_search_param(search_params, "gcp_cloud_tags", "in", str(gcp_cloud_tags).split(",")) if azure_cloud_tags: append_search_param(search_params, "azure_cloud_tags", "in", str(azure_cloud_tags).split(",")) if has_xdr_agent: append_search_param(search_params, "has_xdr_agent", "in", str(has_xdr_agent).split(",")) if externally_detected_providers: append_search_param(search_params, "externally_detected_providers", "contains", externally_detected_providers) if externally_inferred_cves: append_search_param(search_params, "externally_inferred_cves", "contains", str(externally_inferred_cves)) if business_units_list: append_search_param(search_params, "business_units_list", "in", str(business_units_list).split(",")) if has_bu_overrides: append_search_param(search_params, "has_bu_overrides", "eq", has_bu_overrides.lower() != "false") if mac_addresses: append_search_param(search_params, "mac_addresses", "contains", mac_addresses) response = client.list_asset_internet_exposure_request(search_params) formatted_response = response.get("reply", {}).get("assets_internet_exposure", []) parsed = format_asm_id(formatted_response) markdown = tableToMarkdown( "Asset Internet Exposures", parsed, removeNull=True, headerTransform=string_to_table_header, ) command_results = CommandResults( outputs_prefix="ASM.AssetInternetExposure", outputs_key_field="asm_ids", outputs=parsed, raw_response=response, readable_output=markdown, ) return command_results def get_asset_internet_exposure_command(args: dict[str, Any], client: Client) -> CommandResults: """ asm-get-asset-internet-exposure command: Returns details of single external internet exposure. Returns error if more than one asm_id was provided in comma separated format. Args: client (Client): CortexAttackSurfaceManagment client to use. args (dict): all command arguments, usually passed from ``demisto.args()``. ``args['asm_id']`` A string representing the asset ID for which you want to get the details for. Returns: CommandResults: A ``CommandResults`` object that is then passed to ``return_results``, that contains internet exposure information. """ # assume that only one asm_id was passed in or fail. asm_id = str(args.get("asm_id")) asm_id_list = asm_id.split(",") if len(asm_id_list) > 1: raise ValueError("This command only supports one asm_id at this time") response = client.get_asset_internet_exposure_request(asm_id_list) parsed = response.get("reply", {}).get("details") markdown = tableToMarkdown( "Asset Internet Exposure", parsed, removeNull=True, headerTransform=string_to_table_header, ) command_results = CommandResults( outputs_prefix="ASM.AssetInternetExposure", outputs_key_field="asm_ids", outputs=parsed, raw_response=response, readable_output=markdown, ) return command_results def start_remediation_confirmation_scan_command(args: dict[str, Any], client: Client) -> CommandResults: """ asm-start-remediation-confirmation-scan command: Starts a new scan or gets an existing scan ID. Args: client (Client): CortexAttackSurfaceManagment client to use. args (dict): all command arguments, usually passed from ``demisto.args()`` (not used in this function). Returns: CommandResults: A ``CommandResults`` object that is then passed to ``return_results``, that contains the ID of the Remediation Confirmation Scan. """ service_id = str(args.get("service_id")) attack_surface_rule_id = str(args.get("attack_surface_rule_id")) alert_internal_id = int(args.get("alert_internal_id", "")) if alert_internal_id < 0: raise ValueError(f"Expected a non-negative integer, but got {alert_internal_id}.") response = client.start_remediation_confirmation_scan( alert_internal_id=alert_internal_id, service_id=service_id, attack_surface_rule_id=attack_surface_rule_id, ) demisto.debug(response.status_code) json_response = response.json() formatted_outputs = json_response.get("reply", {}) if response.status_code == 201: formatted_outputs.update({"scan_creation_status": "created"}) elif response.status_code == 200: formatted_outputs.update({"scan_creation_status": "existing"}) markdown = tableToMarkdown( "Creation of Remediation Confirmation Scan", formatted_outputs, removeNull=True, headerTransform=string_to_table_header, ) command_results = CommandResults( outputs_prefix="ASM.RemediationScan", outputs_key_field="", outputs=formatted_outputs, raw_response=json_response, readable_output=markdown, ) return command_results @polling_function( name=demisto.command(), interval=arg_to_number(demisto.args().get("interval_in_seconds", 600)), timeout=arg_to_number(demisto.args().get("timeout_in_seconds", 11000)), requires_polling_arg=False, # This means it will always be default to poll, poll=true ) def get_remediation_confirmation_scan_status_command(args: dict[str, Any], client: Client): """ asm-get-remediation-confirmation-scan-status command: Polls for status of an existing remediation confirmation scan. Args: client (Client): CortexAttackSurfaceManagment client to use. args (dict): all command arguments, usually passed from ``demisto.args()`` (not used in this function). Returns: PollResult: A ``PollResult`` object that is then passed to ``return_results``, that contains the ID of the Remediation Confirmation Scan and a success or failure message. """ scan_id = str(args.get("scan_id")) response = client.get_remediation_confirmation_scan_status(scan_id=scan_id) json_response = response.json() scan_status = json_response.get("reply").get("status") if scan_status == "IN_PROGRESS": return PollResult( response=None, partial_result=CommandResults( outputs_prefix="ASM.RemediationScan", outputs_key_field="scan_id", readable_output="Waiting for remediation confirmation scan to finish...", ), continue_to_poll=True, args_for_next_run={"scan_id": scan_id, **args}, ) elif scan_status == "SUCCESS": formatted_outputs = json_response.get("reply", {}) markdown = tableToMarkdown( "Status of Remediation Confirmation Scan", formatted_outputs, removeNull=True, headerTransform=string_to_table_header, ) command_results = CommandResults( outputs_prefix="ASM.RemediationScan", outputs_key_field="", outputs=formatted_outputs, raw_response=json_response, readable_output=markdown, ) return PollResult(response=command_results, continue_to_poll=False) elif scan_status == "FAILED_TIMEOUT" or scan_status == "FAILED_ERROR": formatted_outputs = json_response.get("reply", {}) command_results = CommandResults( outputs_prefix="ASM.RemediationScan", outputs_key_field="", outputs=formatted_outputs, raw_response=json_response, readable_output="The remediation confirmation scan timed out or failed.", ) return PollResult(response=command_results, continue_to_poll=False) else: formatted_outputs = json_response.get("reply", {}) command_results = CommandResults( outputs_prefix="ASM.RemediationScan", outputs_key_field="", outputs=formatted_outputs, raw_response=json_response, readable_output="The remediation confirmation scan timed out or failed.", ) return PollResult(response=command_results, continue_to_poll=False) def test_module(client: Client) -> None: """ Tests API connectivity and authentication' When 'ok' is returned it indicates the integration works like it is supposed to and connection to the service is successful. Raises exceptions if something goes wrong. Args: client (Client): CortexAttackSurfaceManagment client to use. Returns: str: 'ok' if test passed, anything else will raise an exception and will fail the test. """ try: client.list_external_service_request([]) except DemistoException as e: if "Forbidden" in str(e): raise DemistoException("Authorization Error: make sure API Key is correctly set") else: raise e return_results("ok") def main() -> None: """ main function """ params: dict[str, Any] = demisto.params() args: dict[str, Any] = demisto.args() command = demisto.command() demisto.debug(f"Command being called is {command}") try: creds = params.get("credentials", {}) api = creds.get("password", "") auth_id = creds.get("identifier", "") headers = { "Authorization": f"{api}", "x-xdr-auth-id": f"{auth_id}", "Content-Type": "application/json", } proxy = params.get("proxy", False) handle_proxy() verify_certificate = not params.get("insecure", False) url_suffix = "/public_api/v1" url = params.get("url", "") add_sensitive_log_strs(api) base_url = urljoin(url, url_suffix) client = Client(base_url=base_url, verify=verify_certificate, headers=headers, proxy=proxy) commands = { "asm-list-external-service": list_external_service_command, "asm-get-external-service": get_external_service_command, "asm-list-external-ip-address-range": list_external_ip_address_range_command, "asm-get-external-ip-address-range": get_external_ip_address_range_command, "asm-get-attack-surface-rule": get_attack_surface_rule_command, "asm-list-asset-internet-exposure": list_asset_internet_exposure_command, "asm-get-asset-internet-exposure": get_asset_internet_exposure_command, "asm-list-remediation-rule": list_remediation_rule_command, "asm-start-remediation-confirmation-scan": start_remediation_confirmation_scan_command, "asm-get-remediation-confirmation-scan-status": get_remediation_confirmation_scan_status_command, } if command == "test-module": test_module(client) elif command in commands: return_results(commands[command](args, client)) else: raise NotImplementedError(f"{command} command is not implemented.") except Exception as e: return_error(f"Failed to execute {command} command.\nError:\n{str(e)}") """ ENTRY POINT """ if __name__ in ["__main__", "builtin", "builtins"]: main()