AutoFocus V2 Deprecated
Deprecated. Use the Unit 42 Intelligence integration instead.
Data Enrichment & Threat Intelligence · AutoFocus by Palo Alto Networks
Details
| ID | AutoFocus V2 |
|---|---|
| Provider | Palo Alto Networks |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.8.3296088 |
| Supported Modules | Agentix Cortex Cloud Cloud Runtime Security Cloud Posture Security XSIAM EDR |
README
Use the AutoFocus v2 integration to contextualize threat intelligence and bring speed, consistency, and precision to threat investigation.
TIM customers that upgraded to version 6.2 or above, can have the API Key pre-configured in their main account so no additional input is needed. To use this feature, upgrade your license so it includes the license key.
Use Cases
- Query samples / sessions
- Get sample analysis
- Get session details
- Get tag details
- Get top tags
Get Your API Key
To get your API key, you need to add an authorization code, and then activate the API.
Add your authorization code
- Go to the Palo Alto Networks support site.
- Select Assets > Site Licenses tab.
- Select Add Site License.
- Enter the authorization code.
Activate the API
- in Site Licenses, select Enable.
- Click the API Key link.
Use the API key when configuring the integration.
For more information on activating the license see Activating AutoFocus Licenses.
Configure AutoFocus V2 on Cortex XSOAR
- Navigate to Settings > Integrations > Servers & Services.
- Search for AutoFocus V2.
-
Click Add instance to create and configure a new integration instance.
Parameter Description Example Name A meaningful name for the integration instance. AutoFocus V2_instance_2 API Key Account’s private token. N/A Source Reliability Reliability of the source providing the intelligence data. B - Usually reliable Additional Malicious Verdicts A comma-separated list of Palo Alto Networks verdicts to consider as malicious when calculating the DBot score. malware,phishing,c2 Override default credentials Whether to override the default AutoFocus API key given by the Cortex XSOAR platform. False Trust any certificate (not secure) When selected, certificates are not checked. N/A Use System Proxy Settings Runs the integration instance using the proxy server (HTTP or HTTPS) that you defined in the server configuration. N/A handle_error Suppress errors for non found indicators. N/A - Click Test to validate the URLs, token, and connection.
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.
Search for samples
Searches for samples. To view the results provide polling=true, or run the autofocus-samples-search-results command with the returned Af Cookie. The AF Cookie expires 120 seconds after the search completes. Use the query that was created in AutoFocus within playbooks “as-is”. To run the command with the query in Cortex XSOAR, wrap the query in backticks ``. For example:
!autofocus-search-samples query=`{"operator":"all","children":[{"field":"sample.malware","operator":"is","value":1}]}` scope=Global sort="First Seen (Create Date)" order=Ascending
Base Command
autofocus-search-samples
Input
| Argument Name | Description | Required |
|---|---|---|
| query | The query for which to retrieve samples. For additional information on how to build your query using the AF GUI, see the detailed description. | Optional |
| max_results | The number of results to return. | Optional |
| sort | The field by which to sort the results. | Optional |
| order | The order of the results. Can be “Ascending” or “Descending”. | Optional |
| scope | The scope of the search. Can be “Private”, “Public”, or “Global”. | Required |
| file_hash | The MD5, SHA1 or SHA256 hash of the file. | Optional |
| domain | The domain to search. | Optional |
| ip | The IP address to search. | Optional |
| url | The URL to search. | Optional |
| artifact | Whether to return artifacts of samples. | Optional |
| wildfire_verdict | The WildFire verdict. Can be “Malware”, “Grayware”, “Benign”, or “Phishing”. | Optional |
| first_seen | The date range of the creation date. Format: YYY Y-MM-DDTHH:MM:SS,YYYY-MM-DDTHH:MM:SS where the first date is the beginning and the second is the end. Example: 2019-09-09T00:00:00,2019-09-09T23:01:59 | Optional |
| last_updated | The date range of the last updated date. Format: YYY Y-MM-DDTHH:MM:SS,YYYY-MM-DDTHH:MM:SS where the first date is the beginning and the second is the end. Example: 2019-09-09T00:00:00,2019-09-09T23:01:59 | Optional |
| af_cookie | The AF Cookie for retrieving results of previous searches. The AF Cookie expires 120 seconds after the search completes. | Optional |
| polling | Use XSOAR built-in polling to retrieve the result when it’s ready. | Optional |
| retry_on_rate_limit | Whether an auto retry of the command will be executed once the quota is refreshed if the API points have run out. Possible values are: true, false. Default is false. |
Optional |
Using polling
The polling argument was added in XSOAR 6.2.0. It enables to handle the search in a single command, foregoing the need to run autofocus-samples-search-results.
For more info see Scheduled Commands.
How to Build a Query
- Go to the AutoFocus platform search screen.
- Click the Advanced… button on the top right.
- Build a query by selecting the fields operators and relevant values. To add another condition, click the + button. For more information on how to use the search editor, see Work with the Search Editor.
- To get the query, open the API syntax, and click the >_API button.
Copy the query value from the opening curly bracket{until the,"scope"parameter, and paste it as the value for thequeryargument for both search commands. For example:
{"operator":"all","children":[{"field":"sample.malware","operator":"is","value":1},{"field":"sample.create_date","operator":"is after","value":["2019-06-13","2019-06-13"]}]}
Context Output
| Path | Type | Description |
|---|---|---|
| AutoFocus.SamplesSearch.AFCookie | String | The ID of the search. Use this ID to get search results. The AF Cookie expires 120 seconds after the search completes. |
| AutoFocus.SamplesSearch.Status | String | The search status. Can be “in progress” or “complete”. |
| AutoFocus.SamplesResults.Size | String | The file size in bytes. |
| AutoFocus.SamplesResults.SHA1 | String | The SHA1 hash of the file. |
| AutoFocus.SamplesResults.SHA256 | String | The SHA256 hash of the file. |
| AutoFocus.SamplesResults.Created | Date | The date that the file was created. |
| AutoFocus.SamplesResults.Finished | Date | The date the file was finished. |
| AutoFocus.SamplesResults.Region | String | The region of the sample. |
| AutoFocus.SamplesResults.FileType | String | The file type. |
| AutoFocus.SamplesResults.Tags | String | The tags attached to the sample. |
| AutoFocus.SamplesResults.Verdict | Number | The verdict of the sample. |
| AutoFocus.SamplesResults.TagGroups | String | The groups of relevant tags. |
| AutoFocus.SamplesSearch.Status | String | The search status. Can be “in progress” or “complete”. |
| AutoFocus.SamplesSearch.Artifact.b | Number | How many set the artifact as benign. |
| AutoFocus.SamplesSearch.Artifact.g | Number | How many set the artifact as grayware. |
| AutoFocus.SamplesSearch.Artifact.m | Number | How many set the artifact as malicious. |
| AutoFocus.SamplesSearch.Artifact.confidence | String | How confident the decision. |
| AutoFocus.SamplesSearch.Artifact.indicator | String | The indicator that was tested. |
| AutoFocus.SamplesSearch.Artifact.indicator_type | String | The indicator type, for example: Mutex, User agent, IPv4, Domain. |
| File.Size | Number | The size of the file in bytes. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.Type | String | The file type, as determined by libmagic (same as displayed in file entries). |
| File.Tags | String | The tags of the file. |
| AutoFocus.Quota.minute_points | Number | Total number of AutoFocus API points alloted per minute |
| AutoFocus.Quota.daily_points | Number | Total number of AutoFocus API points alloted per day |
| AutoFocus.Quota.minute_points_remaining | Number | Remaining number of AutoFocus API points per minute |
| AutoFocus.Quota.daily_points_remaining | Number | Remaining number of AutoFocus API points per day |
| AutoFocus.Quota.minute_bucket_start | Date | Timestamp for when the current minute allotment started |
| AutoFocus.Quota.daily_bucket_start | Date | Timestamp for when the current daily allotment started |
Command Example
!autofocus-search-samples query=`{"operator":"all","children":[{"field":"sample.malware","operator":"is","value":1}]}` scope=Global sort="First Seen (Create Date)" order=Ascending
Context Example
{
"AutoFocus.SamplesSearch": {
"Status": "in progress",
"AFCookie": "2-78049b80-9c18-47e7-835e-d31ca8bd48aa+0"
}
}
Human Readable Output
Search Samples Info
| AFCookie | Status |
|---|---|
| 2-78049b80-9c18-47e7-835e-d31ca8bd48aa+0 | in progress |
Search for sessions
Searches for sessions. To view the results provide polling=true, or run the autofocus-sessions-search-results command with the returned AF Cookie. The AF Cookie expires 120 seconds after the search completes.
Base Command
autofocus-search-sessions
Input
| Argument Name | Description | Required |
|---|---|---|
| query | The query for which to retrieve samples. For additional information on how to build your query using the AF GUI, see the detailed description section. | Optional |
| max_results | The maximum number of results to return. The default is 30. | Optional |
| sort | The field by which to sort the results. | Optional |
| order | The order of the results. Can be “Ascending” or “Descending”. | Optional |
| file_hash | The MD5, SHA1 or SHA256 hash of the file. | Optional |
| domain | The domain to search. | Optional |
| ip | The IP address to search. | Optional |
| url | The URL to search. | Optional |
| time_range | The date range in which to search for sessions. Format: YYY Y-MM-DDTHH:MM:SS,YYYY-MM-DDTHH:MM:SS where the first date is the beginning and the second is the end. Example: 2019-09-09T00:00:00,2019-09-09T23:01:59 | Optional |
| time_after | The date after which to search for sessions. Format: YYYY-MM-DDTHH:MM:SS Example: 2019-09-09T23:01:59 | Optional |
| time_before | The date before which to search for sessions. Format: YYYY-MM-DDTHH:MM:SS Example: 2019-09-09T23:01:59 | Optional |
| polling | Use XSOAR built-in polling to retrieve the result when it’s ready. | Optional |
| retry_on_rate_limit | Whether an auto retry of the command will be executed once the quota is refreshed if the API points have run out. Possible values are: true, false. Default is false. |
Optional |
Using polling
The polling argument was added in XSOAR 6.2.0. It enables to handle the search in a single command, foregoing the need for autofocus-sessions-search-results.
For more info see Scheduled Commands.
How to Build a Query
- Go to the AutoFocus platform search screen.
- Select the Advanced… button on the top right.
- Build a query by selecting fields operators and relevant values. To add another condition, click the + button. For more information on how to use the search editor, see Work with the Search Editor.
- To get the query you built, open the API syntax, and click the >_API button.
- Copy the query value from the opening curly bracket
{until the,"scope"parameter, and paste it as the value for thequeryargument for both search commands. For example:
{"operator":"all","children":[{"field":"sample.malware","operator":"is","value":1},{"field":"sample.create_date","operator":"is after","value":["2019-06-13","2019-06-13"]}]}
Context Output
| Path | Type | Description |
|---|---|---|
| AutoFocus.SessionsSearch.AFCookie | String | The ID of the search. Use the ID to get search results. The AF Cookie expires 120 seconds after the search completes. |
| AutoFocus.SessionsSearch.Status | String | The status of the search. Can be “in progress” or “complete”. |
| AutoFocus.SessionsResults.FileName | String | The name of the file.. |
| AutoFocus.SessionsResults.ID | String | The ID of the session. Used to get session details. |
| AutoFocus.SessionsResults.Industry | String | The related industry. |
| AutoFocus.SessionsResults.Region | String | The regions of the sessions. |
| AutoFocus.SessionsResults.SHA256 | String | The SHA256 hash of the file. |
| AutoFocus.SessionsResults.Seen | Date | The seen date. |
| AutoFocus.SessionsResults.UploadSource | String | The source of the uploaded sample. |
| AutoFocus.SessionsResults.FileURL | String | The URL of the file. |
| AutoFocus.SessionsResults.Tags | String | The relevant tags. |
| AutoFocus.SessionsSearch.Status | String | The search status. Can be “in progress” or “complete”. |
| File.Name | String | The full file name (including file extension). |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.Tags | String | The tags of the file. |
| AutoFocus.Quota.minute_points | Number | Total number of AutoFocus API points alloted per minute |
| AutoFocus.Quota.daily_points | Number | Total number of AutoFocus API points alloted per day |
| AutoFocus.Quota.minute_points_remaining | Number | Remaining number of AutoFocus API points per minute |
| AutoFocus.Quota.daily_points_remaining | Number | Remaining number of AutoFocus API points per day |
| AutoFocus.Quota.minute_bucket_start | Date | Timestamp for when the current minute allotment started |
| AutoFocus.Quota.daily_bucket_start | Date | Timestamp for when the current daily allotment started |
Command Example
!autofocus-search-sessions query={"operator":"all","children":[{"field":"sample.malware","operator":"is","value":1}]} max_results="30" sort="Application" order="Ascending"
Context Example
{
"AutoFocus.SessionsSearch": {
"Status": "in progress",
"AFCookie": "2-2d70539d-26af-40d2-b80b-16be60dabbaf+0"
}
}
Human Readable Output
Search Sessions Info
| AFCookie | Status |
|---|---|
| 2-2d70539d-26af-40d2-b80b-16be60dabbaf+0 | in progress |
Get results of a samples search
Returns the results of a previous samples search.
Base Command
autofocus-samples-search-results
Input
| Argument Name | Description | Required |
|---|---|---|
| af_cookie | The AF Cookie for retrieving results of previous searches. The AF Cookie expires 120 seconds after the search completes. | Required |
| retry_on_rate_limit | Whether an auto retry of the command will be executed once the quota is refreshed if the API points have run out. Possible values are: true, false. Default is false. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AutoFocus.SamplesResults.Size | String | The file size in bytes. |
| AutoFocus.SamplesResults.SHA1 | String | The SHA1 hash of the file. |
| AutoFocus.SamplesResults.SHA256 | String | The SHA256 hash of the file. |
| AutoFocus.SamplesResults.Created | Date | The date that the file was created. |
| AutoFocus.SamplesResults.Finished | Date | The date the file was finished. |
| AutoFocus.SamplesResults.Region | String | The region of the sample. |
| AutoFocus.SamplesResults.FileType | String | The file type. |
| AutoFocus.SamplesResults.Tags | String | The tags attached to the sample. |
| AutoFocus.SamplesResults.Verdict | Number | The verdict of the sample. |
| AutoFocus.SamplesResults.TagGroups | String | The groups of relevant tags. |
| AutoFocus.SamplesSearch.Status | String | The search status. Can be “in progress” or “complete”. |
| AutoFocus.SamplesSearch.Artifact.b | Number | How many set the artifact as benign. |
| AutoFocus.SamplesSearch.Artifact.g | Number | How many set the artifact as grayware. |
| AutoFocus.SamplesSearch.Artifact.m | Number | How many set the artifact as malicious. |
| AutoFocus.SamplesSearch.Artifact.confidence | String | How confident the decision. |
| AutoFocus.SamplesSearch.Artifact.indicator | String | The indicator that was tested. |
| AutoFocus.SamplesSearch.Artifact.indicator_type | String | The indicator type, for example: Mutex, User agent, IPv4, Domain. |
| File.Size | Number | The size of the file in bytes. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.Type | String | The file type, as determined by libmagic (same as displayed in file entries). |
| File.Tags | String | The tags of the file. |
| AutoFocus.Quota.minute_points | Number | Total number of AutoFocus API points alloted per minute |
| AutoFocus.Quota.daily_points | Number | Total number of AutoFocus API points alloted per day |
| AutoFocus.Quota.minute_points_remaining | Number | Remaining number of AutoFocus API points per minute |
| AutoFocus.Quota.daily_points_remaining | Number | Remaining number of AutoFocus API points per day |
| AutoFocus.Quota.minute_bucket_start | Date | Timestamp for when the current minute allotment started |
| AutoFocus.Quota.daily_bucket_start | Date | Timestamp for when the current daily allotment started |
Command Example
!autofocus-samples-search-results af_cookie=2-c0a49ebb-2fee-4423-9bd3-76004d5878ba+1
Context Example
{
"File": [
{
"SHA256": "55f66d613414b35d46e48b952541403a5b2a5d1a1e3c0bef2bd76607b41400b9",
"Type": "PE",
"Size": 28832
},
],
"AutoFocus.SamplesResults": [
{
"Artifact": [
{
"b": 914,
"confidence": "interesting",
"g": 25,
"indicator": "1048576",
"indicator_type": "Mutex",
"m": 292
},
{
"b": 120,
"confidence": "interesting",
"g": 0,
"indicator": "1048577",
"indicator_type": "Mutex",
"m": 179
},
{
"b": 64605,
"confidence": "suspect",
"g": 7095,
"indicator": "ZonesCacheCounterMutex",
"indicator_type": "Mutex",
"m": 512566
}
],
"Created": "2020-04-03T00:35:53",
"FileType": "PE",
"Finished": "2020-04-03T00:43:33",
"ID": "2dfb6b0cb24d745fa412479ea3b0cabe9d2b57e008016656af55a6d3832c2091",
"MD5": "ef05777192cccc6502609dbdf0dc6149",
"Region": [
"us"
],
"SHA1": "c23fe9ce9c9f6260c5eb385cbb71fa1f6817cca5",
"SHA256": "2dfb6b0cb24d745fa412479ea3b0cabe9d2b57e008016656af55a6d3832c2091",
"Size": 234505,
"Tags": [
"Unit42.InitialSystemDataEnumeration",
"Unit42.RunOnce",
"Unit42.GandCrab"
],
"Verdict": 1,
"imphash": "af2a98692b8b30d8401f26d24a673b23",
"ssdeep": "3072:kKogwq8P3Nm0ZSLPjerAg0FuD5HibZ6nEdMmgcUUcNS7FY+qTtwuz0f8TpIe8OuW:CvqqAOF+640UcSFNuzokpIx95K3",
"tag_groups": [
"Ransomware"
],
"tasks": [
{
"metadata_compilation_ts": "2018-05-14T22:05:59"
}
]
}
],
"AutoFocus.SamplesSearch": {
"Status": "complete",
"AFCookie": "2-c0a49ebb-2fee-4423-9bd3-76004d5878ba+1"
}
}
Human Readable Output
Search Samples Result is in progress
| Created | FileType | Finished | ID | MD5 | Region | SHA1 | SHA256 | Size | Tags | Verdict | imphash | ssdeep | tag_groups | tasks |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2020-04-05T00:03:49 | PE | 2020-04-05T00:11:59 | d455abd39edc7a2f03fa43b4d0f9194a11e73fce9c794021b5ca050dd0bc156d | 77c94c76214c7069b7fc5e7634b7e225 | us | 1460b6a9a0955f0d5c011edba569786c13b6d8a6 | d455abd39edc7a2f03fa43b4d0f9194a11e73fce9c794021b5ca050dd0bc156d | 362331 | Unit42.IPAddressLookup,Unit42.InitialSystemDataEnumeration,Unit42.RunOnce,Unit42.GandCrab | 1 | f456e8b8fd5e0768c2e3120e086c8ebc | 6144 | Ransomware | {‘metadata_compilation_ts’: ‘2018-06-11T11:15:25’} |
Artifacts for Sample
| b | g | m | indicator_type | confidence | indicator |
|---|---|---|---|---|---|
| 1 | 0 | 145006 | Domain | suspect | carder.bit |
| 1 | 0 | 208393 | Domain | suspect | ransomware.bit |
| 373 | 67 | 317773 | IPv4 | suspect | 66.171.248.178 |
Get results of a sessions search
Returns the results of a previous session’s search.
Base Command
autofocus-sessions-search-results
Input
| Argument Name | Description | Required |
|---|---|---|
| af_cookie | The AF Cookie for retrieving the results of a previous search. The AF Cookie expires 120 seconds after the search completes. | Required |
| retry_on_rate_limit | Whether an auto retry of the command will be executed once the quota is refreshed if the API points have run out. Possible values are: true, false. Default is false. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AutoFocus.SessionsResults.FileName | String | The name of the file.. |
| AutoFocus.SessionsResults.ID | String | The ID of the session. Used to get session details. |
| AutoFocus.SessionsResults.Industry | String | The related industry. |
| AutoFocus.SessionsResults.Region | String | The regions of the sessions. |
| AutoFocus.SessionsResults.SHA256 | String | The SHA256 hash of the file. |
| AutoFocus.SessionsResults.Seen | Date | The seen date. |
| AutoFocus.SessionsResults.UploadSource | String | The source of the uploaded sample. |
| AutoFocus.SessionsResults.FileURL | String | The URL of the file. |
| AutoFocus.SessionsResults.Tags | String | The relevant tags. |
| AutoFocus.SessionsSearch.Status | String | The search status. Can be “in progress” or “complete”. |
| File.Name | String | The full file name (including file extension). |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.Tags | String | The tags of the file. |
| AutoFocus.Quota.minute_points | Number | Total number of AutoFocus API points alloted per minute |
| AutoFocus.Quota.daily_points | Number | Total number of AutoFocus API points alloted per day |
| AutoFocus.Quota.minute_points_remaining | Number | Remaining number of AutoFocus API points per minute |
| AutoFocus.Quota.daily_points_remaining | Number | Remaining number of AutoFocus API points per day |
| AutoFocus.Quota.minute_bucket_start | Date | Timestamp for when the current minute allotment started |
| AutoFocus.Quota.daily_bucket_start | Date | Timestamp for when the current daily allotment started |
Command Example
!autofocus-sessions-search-results af_cookie=2-f2c742b6-a363-4eb9-a313-63a99c376081+0
Context Example
{
"AutoFocus.SessionsSearch": {
"Status": "complete",
"AFCookie": "2-f2c742b6-a363-4eb9-a313-63a99c376081+0"
},
"File": [
{
"SHA256": "2eb355b54855c7531a811d435b2ff4dc74d377bfed98fd1ad03caa591f5555bd",
"Name": "wildfire-test-pe-file.exe",
"Tags": [
"Commodity.WildFireTest"
]
},
{
"SHA256": "f29192fba1064d582cddc85ef3bcf37fa8e9b7d5faddb3e67d241d472e66ab38",
"Name": "wildfire-test-pe-file (4).exe",
"Tags": [
"Commodity.WildFireTest"
]
}
],
"AutoFocus.SessionsResults": [
{
"tag_groups": [],
"Tags": [
"Commodity.WildFireTest"
],
"Industry": "High Tech",
"FileName": "wildfire-test-pe-file.exe",
"ID": "u_56095401643",
"UploadSource": "Manual API",
"Seen": "2019-12-11T08:52:16",
"SHA256": "2eb355b54855c7531a811d435b2ff4dc74d377bfed98fd1ad03caa591f5555bd",
"Region": "us"
}
]
}
Human Readable Output
Search Sessions Results is complete
| FileName | ID | Industry | Region | SHA256 | Seen | Tags | UploadSource | tag_groups |
|---|---|---|---|---|---|---|---|---|
| wildfire-test-pe-file.exe | u_56095401643 | High Tech | us | 2eb355b54855c7531a811d435b2ff4dc74d377bfed98fd1ad03caa591f5555bd | 2019-12-11T08:52:16 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (4).exe | u_49158137853 | High Tech | us | f29192fba1064d582cddc85ef3bcf37fa8e9b7d5faddb3e67d241d472e66ab38 | 2019-10-02T11:04:05 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (4).exe | u_49159945553 | High Tech | us | f29192fba1064d582cddc85ef3bcf37fa8e9b7d5faddb3e67d241d472e66ab38 | 2019-10-02T11:19:21 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (4).exe | u_48980717523 | High Tech | us | f29192fba1064d582cddc85ef3bcf37fa8e9b7d5faddb3e67d241d472e66ab38 | 2019-09-30T23:58:00 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (4).exe | u_48980935123 | High Tech | us | f29192fba1064d582cddc85ef3bcf37fa8e9b7d5faddb3e67d241d472e66ab38 | 2019-10-01T00:02:36 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (4).exe | u_48980770253 | High Tech | us | f29192fba1064d582cddc85ef3bcf37fa8e9b7d5faddb3e67d241d472e66ab38 | 2019-09-30T23:59:18 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (4).exe | u_48980686453 | High Tech | us | f29192fba1064d582cddc85ef3bcf37fa8e9b7d5faddb3e67d241d472e66ab38 | 2019-09-30T23:57:10 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (4).exe | u_49128586383 | High Tech | us | f29192fba1064d582cddc85ef3bcf37fa8e9b7d5faddb3e67d241d472e66ab38 | 2019-10-02T08:44:04 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (4).exe | u_49129503223 | High Tech | us | f29192fba1064d582cddc85ef3bcf37fa8e9b7d5faddb3e67d241d472e66ab38 | 2019-10-02T08:49:24 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (4).exe | u_49122514613 | High Tech | us | f29192fba1064d582cddc85ef3bcf37fa8e9b7d5faddb3e67d241d472e66ab38 | 2019-10-02T07:39:45 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (4).exe | u_49145687573 | High Tech | us | f29192fba1064d582cddc85ef3bcf37fa8e9b7d5faddb3e67d241d472e66ab38 | 2019-10-02T09:52:36 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (4).exe | u_49158441703 | High Tech | us | f29192fba1064d582cddc85ef3bcf37fa8e9b7d5faddb3e67d241d472e66ab38 | 2019-10-02T11:06:29 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file.exe | u_47517508773 | High Tech | us | cafa7f3adaace43042e5f85328ddf1d6f0d8109e65f7e6c0b87676a9a7479733 | 2019-09-17T01:59:31 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file.exe | u_47515984893 | High Tech | us | 4851a140be5af4acf3d85621d99c177fd6e1403e8e93c9cba6037459c802382f | 2019-09-17T01:32:11 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file.exe | u_47517298263 | High Tech | us | 5d3725fe649e3a1244fe50cd23b2e558594753d7579c30214da293566d6afa3b | 2019-09-17T01:56:51 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file.exe | u_47541182333 | High Tech | us | 51a93620c2c1456081f91bad64e537724a0d93dcf55face4f1d33df9a91486f1 | 2019-09-17T06:05:21 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file.exe | u_47518135653 | High Tech | us | b39a6bf99de8dd7e55d22ee0732ea3582536a0615dab86e3d36010fe0d4ecf2a | 2019-09-17T02:04:56 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file.exe | u_47516600663 | High Tech | us | 7078f4e2c5d8038bd875e3a6dfd09c9014573c5d3c155f27c3acd1073c05d16f | 2019-09-17T01:46:01 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file.exe | u_47561050553 | High Tech | us | c14646114c390027d373cbd5af7d31d952ab6acd86d5157bb174b19792e557f2 | 2019-09-17T08:14:56 | 41453.TestElena,Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file.exe | u_47517909453 | High Tech | us | 2499501bebcc6ff59d3f0028f760e0433ee3a9415e916d1278a70c474690869d | 2019-09-17T02:02:46 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file.exe | u_47559447933 | High Tech | us | 12f198c65cbdf49972b7432291dad4d2fae7cbb77a35cda1cc28ab2b83d1e2b5 | 2019-09-17T08:08:39 | Commodity.WildFireTest | Manual API | |
| https://wildfire.paloaltonetworks.com/publicapi/test/pe | u_46060032683 | High Tech | us | 2e40edcf77d95173463ca4bfaf833a6a1860ffa4e7b03c3fded8de08ee2be27f | 2019-09-01T04:34:48 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (2).exe | u_45811064553 | High Tech | us | f27069e200ed14c56b1b91285ea3c061aa0e4ca53d9056fed9cc0c9c3e98e961 | 2019-08-28T21:17:33 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (2).exe | u_45810946733 | High Tech | us | f27069e200ed14c56b1b91285ea3c061aa0e4ca53d9056fed9cc0c9c3e98e961 | 2019-08-28T21:14:17 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (2).exe | u_45810992703 | High Tech | us | f27069e200ed14c56b1b91285ea3c061aa0e4ca53d9056fed9cc0c9c3e98e961 | 2019-08-28T21:15:31 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (2).exe | u_45811012343 | High Tech | us | f27069e200ed14c56b1b91285ea3c061aa0e4ca53d9056fed9cc0c9c3e98e961 | 2019-08-28T21:16:06 | Commodity.WildFireTest | Manual API | |
| https://wildfire.paloaltonetworks.com/publicapi/test/pe | u_45835887733 | High Tech | us | bfdc97ecc0d1e19d17cffe856b33c41883520d7b38daa77af03bb42ef83bc680 | 2019-08-29T05:19:21 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (3).exe | u_45811604063 | High Tech | us | 409eb2fa745b4bd804bb3ebdd48f0107bd9c6471a9447a61f68c1a32c480f0f9 | 2019-08-28T21:32:05 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (3).exe | u_45811375593 | High Tech | us | 409eb2fa745b4bd804bb3ebdd48f0107bd9c6471a9447a61f68c1a32c480f0f9 | 2019-08-28T21:25:36 | Commodity.WildFireTest | Manual API | |
| wildfire-test-pe-file (3).exe | u_45811208463 | High Tech | us | 409eb2fa745b4bd804bb3ebdd48f0107bd9c6471a9447a61f68c1a32c480f0f9 | 2019-08-28T21:20:56 | Commodity.WildFireTest | Manual API |
Get session details
Returns session details by session ID.
Base Command
autofocus-get-session-details
Input
| Argument Name | Description | Required |
|---|---|---|
| session_id | The ID of the session. | Required |
| retry_on_rate_limit | Whether an auto retry of the command will be executed once the quota is refreshed if the API points have run out. Possible values are: true, false. Default is false. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AutoFocus.Sessions.FileName | String | The name of the file. |
| AutoFocus.Sessions.ID | String | The ID of the session. |
| AutoFocus.Sessions.Industry | String | The related industry. |
| AutoFocus.Sessions.Region | String | The session’s regions. |
| AutoFocus.Sessions.SHA256 | String | The SHA256 hash of the file. |
| AutoFocus.Sessions.Seen | Date | The seen date. |
| AutoFocus.Sessions.UploadSource | String | The source that uploaded the sample. |
| File.Name | String | The full file name (including file extension). |
| File.SHA256 | String | The SHA256 hash of the file. |
| AutoFocus.Quota.minute_points | Number | Total number of AutoFocus API points alloted per minute |
| AutoFocus.Quota.daily_points | Number | Total number of AutoFocus API points alloted per day |
| AutoFocus.Quota.minute_points_remaining | Number | Remaining number of AutoFocus API points per minute |
| AutoFocus.Quota.daily_points_remaining | Number | Remaining number of AutoFocus API points per day |
| AutoFocus.Quota.minute_bucket_start | Date | Timestamp for when the current minute allotment started |
| AutoFocus.Quota.daily_bucket_start | Date | Timestamp for when the current daily allotment started |
Command Example
!autofocus-get-session-details session_id="u_39605858263"
Context Example
{
"File": [
{
"SHA256": "8d4241654449c63f70dabd83483f8ca8bd8e8e6a8d0679639eb061b3b6dbcfec",
"Name": "wildfire-test-apk-file.apk"
}
],
"AutoFocus.Sessions": [
{
"Industry": "High Tech",
"FileName": "wildfire-test-apk-file.apk",
"ID": "u_39605858263",
"UploadSource": "Manual API",
"Seen": "2019-05-29T15:25:26",
"SHA256": "8d4241654449c63f70dabd83483f8ca8bd8e8e6a8d0679639eb061b3b6dbcfec",
"Region": "us"
}
]
}
Human Readable Output
Session u_39605858263
| FileName | ID | Industry | Region | SHA256 | Seen | UploadSource |
|---|---|---|---|---|---|---|
| wildfire-test-apk-file.apk | u_39605858263 | High Tech | us | 8d4241654449c63f70dabd83483f8ca8bd8e8e6a8d0679639eb061b3b6dbcfec | 2019-05-29T15:25:26 | Manual API |
Get analysis details
Returns properties, behaviors, and activities observed for a sample. Runs the command a single time to get the fields and operating systems under HTTP, Coverage, Behavior, Registry, Files, Processes, Connections, and DNS.
Base Command
autofocus-sample-analysis
Input
| Argument Name | Description | Required |
|---|---|---|
| sample_id | The SHA256 hash of the sample to analyze. | Required |
| os | The analysis environment. Can be “win7”, “winxp”, “android”, “static_analyzer”, “mac”, or “bare_metal”. | Optional |
| filter_data | Whether to smartly filter the data. If “False”, the data returned will not be smartly filtered, and will significantly reduce integration performance. The recommended setting is “True”. | Optional |
| retry_on_rate_limit | Whether an auto retry of the command will be executed once the quota is refreshed if the API points have run out. Possible values are: true, false. Default is false. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AutoFocus.SampleAnalysis.Analysis.Http | Unknown | The HTTP requests made when the sample was executed. |
| AutoFocus.SampleAnalysis.Analysis.Coverage | Unknown | The WildFire signatures that matched the sample. |
| AutoFocus.SampleAnalysis.Analysis.Behavior | Unknown | The sample behavior: created or modified files, started a process, spawned new processes, modified the registry, or installed browser help objects. |
| AutoFocus.SampleAnalysis.Analysis.Registry | Unknown | The registry settings and options that showed activity when the sample was executed in the analysis environment. |
| AutoFocus.SampleAnalysis.Analysis.Files | Unknown | The files that showed activity as a result of the sample being executed. |
| AutoFocus.SampleAnalysis.Analysis.Processes | Unknown | The processes that showed activity when the sample was executed. |
| AutoFocus.SampleAnalysis.Analysis.Connections | Unknown | The connections to other hosts on the network when the sample was executed. |
| AutoFocus.SampleAnalysis.Analysis.Dns | Unknown | The DNS activity observed when the sample was executed. |
| AutoFocus.SampleAnalysis.Analysis.Mutex | Unknown | The mutex created when the program’s start is listed with the parent process if the sample generates other program threads when executed in the analysis environment. |
| AutoFocus.Quota.minute_points | Number | Total number of AutoFocus API points alloted per minute |
| AutoFocus.Quota.daily_points | Number | Total number of AutoFocus API points alloted per day |
| AutoFocus.Quota.minute_points_remaining | Number | Remaining number of AutoFocus API points per minute |
| AutoFocus.Quota.daily_points_remaining | Number | Remaining number of AutoFocus API points per day |
| AutoFocus.Quota.minute_bucket_start | Date | Timestamp for when the current minute allotment started |
| AutoFocus.Quota.daily_bucket_start | Date | Timestamp for when the current daily allotment started |
Command Example
!autofocus-sample-analysis sample_id=dd0d26ceea034b3ae32a4f6a477466ac598ee17f811f88cf14b2c708240fb993
Context Example
{
"AutoFocus.SampleAnalysis": {
"ID": "dd0d26ceea034b3ae32a4f6a477466ac598ee17f811f88cf14b2c708240fb993",
"Analysis": {
"Files": {
"win7": [
{
"action": " Create ",
"parent_process": "svchost.exe "
},
{
"action": " Create ",
"parent_process": "na.exe "
},
{
"action": " Create ",
"parent_process": "svchost.exe "
},
{
"action": " Create ",
"parent_process": "users\\administrator\\sample.dll:DllInstall "
},
{
"action": " Create ",
"parent_process": "users\\administrator\\sample.dll:DllInstall "
}
],
"winxp": []
},
"Processes": {
"win7": [
{
"action": " created ",
"parent_process": "svchost.exe "
},
{
"action": " created ",
"parent_process": "services.exe "
},
{
"action": " created ",
"parent_process": "TrustedInstaller.exe "
},
{
"action": " CreateProcessInternalW ",
"parent_process": "<null> "
}
],
"winxp": [
{
"action": " created ",
"parent_process": "explorer.exe "
},
{
"action": " created ",
"parent_process": "svchost.exe "
},
{
"action": " created ",
"parent_process": "winlogon.exe "
}
]
},
"Http": {
"win7": [
{
"url": " / ",
"host": "sp1.eventincoandhar.info ",
"method": " POST "
},
{
"url": " / ",
"host": "sc1.eventincoandhar.info ",
"method": " POST "
},
{
"url": " / ",
"host": "www.bbc.com ",
"method": " HEAD "
}
]
},
"Coverage": {
"url_categories": [
{
"url": "ns-154-b.gandi.net",
"cat": "Computer and Internet Info"
},
{
"url": "ns3.fastly.net",
"cat": "Computer and Internet Info"
},
{
"url": "aiden.ns.cloudflare.com",
"cat": "Computer and Internet Info"
},
{
"url": "b.iana-servers.net",
"cat": "Unknown"
},
{
"url": "aningtofrebri.info",
"cat": "Unknown"
}
],
"fileurl_signatures": [],
"wildfire_signatures": [],
"dns_signatures": [
{
"create_date": "2016-03-30 07:32:49",
"name": "generic:a.iana-servers.net"
},
{
"create_date": "2016-03-30 07:53:34",
"name": "generic:b.iana-servers.net"
},
{
"create_date": "2017-12-13 22:55:29",
"name": "Trojan-Downloader.adload:housandry.info"
},
{
"create_date": "2017-12-13 22:55:29",
"name": "Trojan-Downloader.adload:whereason.info"
},
{
"create_date": "2018-04-07 10:05:16",
"name": "Virus.ramnit:mrsewic.com"
},
{
"create_date": "2018-04-07 10:05:16",
"name": "generic:ylsuest.com"
},
{
"create_date": "2018-04-07 10:15:23",
"name": "generic:knsemis.com"
},
{
"create_date": "2019-02-07 09:00:08",
"name": "Trojan.bsymem:inf2.aningtofrebri.info"
}
]
},
"Mutex": {
"win7": [
{
"action": " CreateMutexW ",
"process": "msiexec.exe ",
"parameters": " Global\\_MSIExecute"
}
]
},
"Registry": {
"win7": [
{
"action": " CreateKey ",
"parameters": " HKLM\\System\\CurrentControlSet\\Services\\Tcpip\\Parameters"
},
{
"action": " RegSetValueEx ",
"parameters": " HKLM\\SYSTEM\\ControlSet001\\services\\Tcpip\\Parameters\\Interfaces\\{FF885F56-91B0-47CA-837A-F293CA541A1F} "
},
{
"action": " RegSetValueEx ",
"parameters": " HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall "
},
{
"action": " RegSetValueEx ",
"parameters": " HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{5129CAA8-E24B-2AEE-652F-C652FBF1E9BB} "
},
{
"action": " RegSetValueEx ",
"parameters": " HKLM\\SOFTWARE\\Wow6432Node\\$(brand_name) "
}
],
"winxp": [
{
"action": " SetValueKey ",
"parameters": " HKCU\\SessionInformation\\ProgramCount "
},
{
"action": " SetValueKey ",
"parameters": " HKLM\\SOFTWARE\\Microsoft\\WBEM\\CIMOM\\List of event-active namespaces "
},
{
"action": " SetValueKey ",
"parameters": " HKLM\\SOFTWARE\\Microsoft\\WZCSVC\\Parameters\\Interfaces\\ControlFlags "
},
{
"action": " SetValueKey ",
"parameters": " HKLM\\SOFTWARE\\Microsoft\\WZCSVC\\Parameters\\Interfaces\\ActiveSettings "
}
]
},
"Behavior": {
"static_analyzer": [],
"win7": [
{
"risk": "high ",
"behavior": " Connected to a non-standard HTTP port"
},
{
"risk": "medium ",
"behavior": " Created or modified a file in the Windows system folder"
},
{
"risk": "high ",
"behavior": " Connected to a malicious IP"
},
{
"risk": "high ",
"behavior": " Connected to a malicious URL"
}
],
"winxp": [
{
"risk": "medium ",
"behavior": " Created or modified a file in the Windows system folder"
},
{
"risk": "low ",
"behavior": " Started a process from a user folder"
}
]
}
}
}
}
Human Readable Output
Sample Analysis results for dd0d26ceea034b3ae32a4f6a477466ac598ee17f811f88cf14b2c708240fb993:### Behavior Static Analyzer
No entries
Behavior Win7
| Behavior | Risk |
|---|---|
| Connected to a non-standard HTTP port | high |
| Created or modified a file in the Windows system folder | medium |
| Generated unknown TCP or UDP traffic | medium |
| Downloaded an executable | high |
| Used a short HTTP header | high |
| Used the HTTP POST method | medium |
| Initiated a failed HTTP connection | low |
| Sent an HTTP response before receiving a request | high |
| Generated unknown HTTP traffic | high |
| Connected to a malicious domain | high |
| Created an executable file in a user folder | low |
| Started a process from a user folder | low |
| Deleted itself | high |
| Registered an OLE control with regsvr32.exe | medium |
| Started or stopped a Windows system service | high |
| Attempted to determine public IP address via IP-checking website | high |
| Connected to a malicious IP | high |
| Connected to a malicious URL | high |
Behavior Winxp
| Behavior | Risk |
|---|---|
| Created or modified a file in the Windows system folder | medium |
| Started a process from a user folder | low |
Processes Win7
| Action | Parent Process |
|---|---|
| created | svchost.exe |
| created | services.exe |
| created | TrustedInstaller.exe |
| created | csrss.exe |
| created | TrustedInstaller.exe |
| created | services.exe |
| created | svchost.exe |
| created | services.exe |
Processes Winxp
| Action | Parent Process |
|---|---|
| created | explorer.exe |
| created | svchost.exe |
| created | winlogon.exe |
Files Win7
| Action | Parent Process |
|---|---|
| Create | svchost.exe |
| Create | na.exe |
| Create | svchost.exe |
| Create | na.exe |
| Create | na.exe |
| Create | na.exe |
| Create | users\administrator\sample.dll:DllInstall |
| Create | users\administrator\sample.dll:DllInstall |
Files Winxp
No entries
###
33 Registry Win7:
| Action | Parameters |
|---|---|
| CreateKey | HKLM\System\CurrentControlSet\Services\Tcpip\Parameters |
| SetValueKey | HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall{5129CAA8-E24B-2AEE-652F-C652FBF1E9BB}\cd77f991 |
| CreateKey | \Registry\Machine\System\CurrentControlSet\Services\RdyBoost\Parameters |
| CreateKey | \Registry\Machine\System\CurrentControlSet\Services\RdyBoost\AttachState |
| SetValueKey | HKLM\COMPONENTS\ServicingStackVersions\6.1.7601.17514 (win7sp1_rtm.101119-1850) |
| SetValueKey | HKLM\SOFTWARE\Microsoft\Microsoft Antimalware\Exclusions\Paths\ProgramData\1560740575 |
| SetValueKey | HKLM\SOFTWARE\Microsoft\Microsoft Antimalware\Exclusions\Paths\Users\ADMINI~1\AppData\Local\Temp{F5743266-6DFF-3433-4CE4-56028389CD67} |
| RegSetValueEx | HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall |
| RegSetValueEx | HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall{5129CAA8-E24B-2AEE-652F-C652FBF1E9BB} |
| RegSetValueEx | HKLM\SOFTWARE\Wow6432Node$(brand_name) |
Registry Winxp
| Action | Parameters |
|---|---|
| SetValueKey | HKCU\SessionInformation\ProgramCount |
| SetValueKey | HKLM\SOFTWARE\Microsoft\WBEM\CIMOM\List of event-active namespaces |
| SetValueKey | HKCU\SessionInformation\ProgramCount |
| SetValueKey | HKLM\SOFTWARE\Microsoft\WZCSVC\Parameters\Interfaces\ActiveSettings |
Mutex Win7
| Action | Parameters | Process |
|---|---|---|
| CreateMutexW | Global_MSIExecute | msiexec.exe |
Http Win7
| Host | Method | Url |
|---|---|---|
| sp1.eventincoandhar.info | POST | / |
| ip-api.com | GET | /json |
| knsemis.com | POST | /tickets |
| www.cnn.com | HEAD | / |
| www.bbc.com | HEAD | / |
Get tag details
Returns details about the given tag.
Base Command
autofocus-tag-details
Input
| Argument Name | Description | Required |
|---|---|---|
| tag_name | The public tag name. Can be retrieved from the top-tags command. | Required |
| retry_on_rate_limit | Whether an auto retry of the command will be executed once the quota is refreshed if the API points have run out. Possible values are: true, false. Default is false. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AutoFocus.Tag.TagName | String | The simple name of the tag. |
| AutoFocus.Tag.PublicTagName | String | The public name of the tag. This is used as an ID of the tag. |
| AutoFocus.Tag.Count | Number | The number of samples that matched this tag. |
| AutoFocus.Tag.Lasthit | Date | The date that the tag was last encountered. |
| AutoFocus.Tag.TagDefinitionScope | String | The scope of the tag. Can be “public”, “private”, or “Unit42”. |
| AutoFocus.Tag.CustomerName | String | The organization that created the tag. |
| AutoFocus.Tag.Source | String | The organization or individual that discovered the threat that is defined in the tag. |
| AutoFocus.Tag.TagClass | String | The classification of the tag. |
| AutoFocus.Tag.TagDefinitionStatus | String | The status of the tag definition. Can be “enabled”, “disabled”, “removing”, or “rescoping”. |
| AutoFocus.Tag.TagGroup | String | The tag group of the tag. |
| AutoFocus.Tag.Description | String | The tag description. |
| AutoFocus.Quota.minute_points | Number | Total number of AutoFocus API points alloted per minute |
| AutoFocus.Quota.daily_points | Number | Total number of AutoFocus API points alloted per day |
| AutoFocus.Quota.minute_points_remaining | Number | Remaining number of AutoFocus API points per minute |
| AutoFocus.Quota.daily_points_remaining | Number | Remaining number of AutoFocus API points per day |
| AutoFocus.Quota.minute_bucket_start | Date | Timestamp for when the current minute allotment started |
| AutoFocus.Quota.daily_bucket_start | Date | Timestamp for when the current daily allotment started |
Command Example
!autofocus-tag-details tag_name=490082.Pastebin_Raw
Context Example
{
"AutoFocus.Tag": {
"Count": 84674,
"Lasthit": "2020-01-02 05:22:18",
"CustomerName": "Squadra Solutions",
"PublicTagName": "490082.Pastebin_Raw",
"TagDefinitionScope": "public",
"Source": "Squadra Solutions",
"TagDefinitionStatus": "enabled",
"TagName": "Pastebin_Raw",
"TagClass": "malicious_behavior",
"Description": "Malicious actors may post raw code to Pastebin which can then be downloaded for further use or as a C2 channel. Some code are also encoded in base64 for further obfuscation"
}
}
Human Readable Output
Tag 490082.Pastebin_Raw details
| Count | Customer Name | Description | Lasthit | Public Tag Name | Source | Tag Class | Tag Definition Scope | Tag Definition Status | Tag Name |
|---|---|---|---|---|---|---|---|---|---|
| 84674 | Squadra Solutions | Malicious actors may post raw code to Pastebin which can then be downloaded for further use or as a C2 channel. Some code are also encoded in base64 for further obfuscation | 2020-01-02 05:22:18 | 490082.Pastebin_Raw | Squadra Solutions | malicious_behavior | public | enabled | Pastebin_Raw |
Search for the most popular tags
Performs a search to identify the most popular tags.
Base Command
autofocus-top-tags-search
Input
| Argument Name | Description | Required |
|---|---|---|
| scope | The scope of the search. Can be “industry”, “organization”, “all”, or “global”. | Required |
| class | The tag class. Can be “Malware Family”, “Campaign”, “Actor”, “Exploit”, or Malicious Behavior”. See Tag Classes below for more information. | Required |
| private | Whether the tag scope is “private”. If “True”, the tag scope is private. The default is “False”. | Optional |
| public | Whether the tag scope is “public”. If “True”, the tag scope is public. The default is “False”. | Optional |
| commodity | Whether the tag scope is “commodity”. If “True”, the tag scope is commodity. The default is “False”. | Optional |
| unit42 | Whether the tag scope is “Unit42”. If “True”, the tag scope is unit42. The default is “False”. | Optional |
| af_cookie | The AF Cookie for retrieving results of previous searches. The AF Cookie expires 120 seconds after the search completes. | Optional |
| polling | Use XSOAR built-in polling to retrieve the result when it’s ready. | Optional |
| retry_on_rate_limit | Whether an auto retry of the command will be executed once the quota is refreshed if the API points have run out. Possible values are: true, false. Default is false. |
Optional |
Using polling
The polling argument was added in XSOAR 6.2.0. It enables to handle the search in a single command, foregoing the need to run autofocus-samples-search-results.
For more info see Scheduled Commands.
Tag Classes
- Malware Family: group of malware that have shared properties or common functions.
- Campaign: targeted attack, which might include several incidents or sets of activities.
- Actor: individual or group that initiates a campaign using malware families.
- Exploit: an attack, which takes advantage of a software or network weakness, bug, or vulnerability to manipulate the behavior of the system.
- Malicious Behavior: behavior that is not specific to a malware family or campaign, but indicates that your system has been compromised.
Context Output
| Path | Type | Description |
|---|---|---|
| AutoFocus.TopTagsSearch.AFCookie | String | The ID of the search. Use this ID to get search results. The AF Cookie expires 120 seconds after the search completes. |
| AutoFocus.TopTagsSearch.Status | String | The status of the search. Can be “in progress” or “complete”. |
| AutoFocus.TopTagsResults.Count | Number | The number of samples that matched this tag. |
| AutoFocus.TopTagsResults.PublicTagName | String | The public name of the tag. This is used as an ID of the tag. |
| AutoFocus.TopTagsResults.TagName | String | The simple name of the tag. |
| AutoFocus.TopTagsResults.Lasthit | Date | The last encounter date of the tag. |
| AutoFocus.TopTagsSearch.Status | String | The search status. Can be “in progress” or “complete”. |
| AutoFocus.Quota.minute_points | Number | Total number of AutoFocus API points alloted per minute |
| AutoFocus.Quota.daily_points | Number | Total number of AutoFocus API points alloted per day |
| AutoFocus.Quota.minute_points_remaining | Number | Remaining number of AutoFocus API points per minute |
| AutoFocus.Quota.daily_points_remaining | Number | Remaining number of AutoFocus API points per day |
| AutoFocus.Quota.minute_bucket_start | Date | Timestamp for when the current minute allotment started |
| AutoFocus.Quota.daily_bucket_start | Date | Timestamp for when the current daily allotment started |
Command Example
!autofocus-top-tags-search scope="all" class="Malicious Behavior" private="True" public="True" commodity="False" unit42="False"
Context Example
{
"AutoFocus.TopTagsSearch": {
"Status": "in progress",
"AFCookie": "2-1caadf19-2e94-4742-b9cf-da8b2d90988c+0"
}
}
Human Readable Output
Top tags search Info
| AFCookie | Status |
|---|---|
| 2-1caadf19-2e94-4742-b9cf-da8b2d90988c+0 | in progress |
Get results of a top tags search
Returns the results of a previous top tags search.
Base Command
autofocus-top-tags-results
Input
| Argument Name | Description | Required |
|---|---|---|
| af_cookie | The AF Cookie for retrieving results of the previous search. The AF Cookie expires 120 seconds after the search completes. | Required |
| retry_on_rate_limit | Whether an auto retry of the command will be executed once the quota is refreshed if the API points have run out. Possible values are: true, false. Default is false. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AutoFocus.TopTagsResults.Count | Number | The number of samples that matched this tag. |
| AutoFocus.TopTagsResults.PublicTagName | String | The public name of the tag. This is used as an ID of the tag. |
| AutoFocus.TopTagsResults.TagName | String | The simple name of the tag. |
| AutoFocus.TopTagsResults.Lasthit | Date | The last encounter date of the tag. |
| AutoFocus.TopTagsSearch.Status | String | The search status. Can be “in progress” or “complete”. |
| AutoFocus.Quota.minute_points | Number | Total number of AutoFocus API points alloted per minute |
| AutoFocus.Quota.daily_points | Number | Total number of AutoFocus API points alloted per day |
| AutoFocus.Quota.minute_points_remaining | Number | Remaining number of AutoFocus API points per minute |
| AutoFocus.Quota.daily_points_remaining | Number | Remaining number of AutoFocus API points per day |
| AutoFocus.Quota.minute_bucket_start | Date | Timestamp for when the current minute allotment started |
| AutoFocus.Quota.daily_bucket_start | Date | Timestamp for when the current daily allotment started |
Command Example
!autofocus-top-tags-results af_cookie=2-2190f844-7c0a-42e7-b4be-5f7d83c9b05c+0
Context Example
{
"AutoFocus.TopTagsSearch": {
"Status": "in progress",
"AFCookie": "2-2190f844-7c0a-42e7-b4be-5f7d83c9b05c+0"
},
"AutoFocus.TopTagsResults": [
{
"Count": 84674,
"Lasthit": "2020-01-02 05:22:18",
"TagName": "Pastebin_Raw",
"PublicTagName": "490082.Pastebin_Raw"
},
{
"Count": 25288,
"Lasthit": "2020-01-01 18:36:12",
"TagName": "ServiceDllUnloadOnStop",
"PublicTagName": "46640.ServiceDllUnloadOnStop"
},
{
"Count": 20912,
"Lasthit": "2020-01-01 16:09:10",
"TagName": "hupigon_mutex",
"PublicTagName": "104.hupigon_mutex"
},
{
"Count": 68694,
"Lasthit": "2020-01-01 19:18:09",
"TagName": "Modify_ComputerName",
"PublicTagName": "490082.Modify_ComputerName"
},
{
"Count": 18740,
"Lasthit": "2020-01-01 07:09:55",
"TagName": "Modify_TermServ_RDP",
"PublicTagName": "490082.Modify_TermServ_RDP"
},
{
"Count": 53921,
"Lasthit": "2020-01-02 00:02:21",
"TagName": "Modify_Permission",
"PublicTagName": "46640.Modify_Permission"
},
{
"Count": 11078,
"Lasthit": "2020-01-02 07:40:39",
"TagName": "MSOfficeResiliency",
"PublicTagName": "490082.MSOfficeResiliency"
},
{
"Count": 18857,
"Lasthit": "2020-01-01 10:06:58",
"TagName": "SecurityProviders_Persistence_LoadDLL",
"PublicTagName": "490082.SecurityProviders_Persistence_LoadDLL"
},
{
"Count": 100001,
"Lasthit": "2019-06-20 12:59:58",
"TagName": "Modify_AttachmentManager",
"PublicTagName": "490082.Modify_AttachmentManager"
},
{
"Count": 15820,
"Lasthit": "2020-01-02 07:22:46",
"TagName": "Cygwin",
"PublicTagName": "490082.Cygwin"
},
{
"Count": 7233,
"Lasthit": "2019-12-30 12:31:47",
"TagName": "SecureCRT",
"PublicTagName": "490082.SecureCRT"
},
{
"Count": 13855,
"Lasthit": "2020-01-02 05:55:01",
"TagName": "Add_PKI_Cert_or_CA",
"PublicTagName": "490082.Add_PKI_Cert_or_CA"
},
{
"Count": 40197,
"Lasthit": "2020-01-01 09:17:34",
"TagName": "Add_IE_EnhancedSecurityConfig",
"PublicTagName": "46640.Add_IE_EnhancedSecurityConfig"
},
{
"Count": 35839,
"Lasthit": "2020-01-01 06:11:35",
"TagName": "WiresharkPCAP_DLL",
"PublicTagName": "490082.WiresharkPCAP_DLL"
},
{
"Count": 6582,
"Lasthit": "2019-12-30 06:28:59",
"TagName": "ArdamaxKeyLogger",
"PublicTagName": "46640.ArdamaxKeyLogger"
},
{
"Count": 26159,
"Lasthit": "2019-12-30 15:18:59",
"TagName": "Pastebin_Dropper",
"PublicTagName": "490082.Pastebin_Dropper"
},
{
"Count": 24331,
"Lasthit": "2020-01-02 01:04:47",
"TagName": "Sandboxie",
"PublicTagName": "490082.Sandboxie"
},
{
"Count": 6137,
"Lasthit": "2020-01-01 17:50:37",
"TagName": "FTP_Suspicious",
"PublicTagName": "490082.FTP_Suspicious"
},
{
"Count": 9793,
"Lasthit": "2020-01-02 05:02:33",
"TagName": "AppCertDLL_Persistence_LoadDLL",
"PublicTagName": "490082.AppCertDLL_Persistence_LoadDLL"
},
{
"Count": 2578,
"Lasthit": "2020-01-01 21:28:20",
"TagName": "MSIEXEC_Web_Install",
"PublicTagName": "46640.MSIEXEC_Web_Install"
}
]
}
Human Readable Output
Search Top Tags Results is in progress
| Count | Lasthit | Public Tag Name | Tag Name |
|---|---|---|---|
| 84674 | 2020-01-02 05:22:18 | 490082.Pastebin_Raw | Pastebin_Raw |
| 25288 | 2020-01-01 18:36:12 | 46640.ServiceDllUnloadOnStop | ServiceDllUnloadOnStop |
| 20912 | 2020-01-01 16:09:10 | 104.hupigon_mutex | hupigon_mutex |
| 68694 | 2020-01-01 19:18:09 | 490082.Modify_ComputerName | Modify_ComputerName |
| 18740 | 2020-01-01 07:09:55 | 490082.Modify_TermServ_RDP | Modify_TermServ_RDP |
| 53921 | 2020-01-02 00:02:21 | 46640.Modify_Permission | Modify_Permission |
| 11078 | 2020-01-02 07:40:39 | 490082.MSOfficeResiliency | MSOfficeResiliency |
| 18857 | 2020-01-01 10:06:58 | 490082.SecurityProviders_Persistence_LoadDLL | SecurityProviders_Persistence_LoadDLL |
| 100001 | 2019-06-20 12:59:58 | 490082.Modify_AttachmentManager | Modify_AttachmentManager |
| 15820 | 2020-01-02 07:22:46 | 490082.Cygwin | Cygwin |
| 7233 | 2019-12-30 12:31:47 | 490082.SecureCRT | SecureCRT |
| 13855 | 2020-01-02 05:55:01 | 490082.Add_PKI_Cert_or_CA | Add_PKI_Cert_or_CA |
| 40197 | 2020-01-01 09:17:34 | 46640.Add_IE_EnhancedSecurityConfig | Add_IE_EnhancedSecurityConfig |
| 35839 | 2020-01-01 06:11:35 | 490082.WiresharkPCAP_DLL | WiresharkPCAP_DLL |
| 6582 | 2019-12-30 06:28:59 | 46640.ArdamaxKeyLogger | ArdamaxKeyLogger |
| 26159 | 2019-12-30 15:18:59 | 490082.Pastebin_Dropper | Pastebin_Dropper |
| 24331 | 2020-01-02 01:04:47 | 490082.Sandboxie | Sandboxie |
| 6137 | 2020-01-01 17:50:37 | 490082.FTP_Suspicious | FTP_Suspicious |
| 9793 | 2020-01-02 05:02:33 | 490082.AppCertDLL_Persistence_LoadDLL | AppCertDLL_Persistence_LoadDLL |
| 2578 | 2020-01-01 21:28:20 | 46640.MSIEXEC_Web_Install | MSIEXEC_Web_Install |
Get the reputation for an IP address
Returns the reputation of an IP address.
Base Command
ip
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | The IP address to check. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Indicator | String | The indicator that was tested. |
| IP.Address | String | The IP address. |
| IP.Tags | String | Tags that are associated with the IP. |
| IP.MalwareFamily | String | The malware family associated with the IP. |
| IP.Relationships.EntityA | String | The source of the relationship. |
| IP.Relationships.EntityAType | String | The type of the source of the relationship. |
| IP.Relationships.EntityB | String | The destination of the relationship. |
| IP.Relationships.EntityBType | String | The type of the destination of the relationship. |
| IP.Relationships.Relationship | String | The name of the relationship. |
| AutoFocus.IP.IndicatorValue | String | The IP address value. |
| AutoFocus.IP.IndicatorType | String | The indicator type. |
| AutoFocus.IP.LatestPanVerdicts | Unknown | The latest verdicts from Palo Alto Networks products. Can be either “PAN_DB” or “WF_SAMPLE”(WildFire). |
| IP.Malicious.Vendor | String | The vendor that decided the file is malicious. |
| AutoFocus.IP.Tags.PublicTagName | String | The public name of the tag. This is used as the tag ID. |
| AutoFocus.IP.Tags.TagName | String | The simple name of the tag. |
| AutoFocus.IP.Tags.CustomerName | String | The organization that created the tag. |
| AutoFocus.IP.Tags.Source | String | The organization or individual that discovered the threat that is defined in the tag. |
| AutoFocus.IP.Tags.TagDefinitionScopeID | Number | The scope ID of the tag. |
| AutoFocus.IP.Tags.TagDefinitionStatusID | Number | The definition status ID of the tag. |
| AutoFocus.IP.Tags.TagClassID | Number | The classification ID of the tag. |
| AutoFocus.IP.Tags.Count | Number | The number of samples that matched this tag. |
| AutoFocus.IP.Tags.Lasthit | Date | The date that the tag was last encountered. |
| AutoFocus.IP.Tags.Description | String | The description of the tag. |
Command Example
!ip ip=127.0.0.1 using-brand="AutoFocus V2"
Context Example
{
"AutoFocus.IP": [
{
"SeenBy": [],
"LatestPanVerdicts": {
"PAN_DB": "BENIGN"
},
"WildfireRelatedSampleVerdictCounts": {},
"IndicatorValue": "127.0.0.1",
"IndicatorType": "IPV4_ADDRESS"
}
],
"IP": [
{
"Address": "127.0.0.1"
}
],
"DBotScore": [
{
"Vendor": "AutoFocus V2",
"Indicator": "127.0.0.1",
"Score": 1,
"Type": "ip"
}
]
}
Human Readable Output
AutoFocus V2 IP reputation for: 127.0.0.1
| Indicatortype | Indicatorvalue | Latestpanverdicts | Seenby | Wildfirerelatedsampleverdictcounts |
|---|---|---|---|---|
| IPV4_ADDRESS | 127.0.0.1 | PAN_DB: BENIGN |
Get the reputation of a URL
Returns the reputation of a URL.
Base Command
url
Input
| Argument Name | Description | Required |
|---|---|---|
| url | The URL to check. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Indicator | String | The indicator that was tested. |
| URL.Data | String | The URL address. |
| URL.Tags | String | Tags that are associated with the URL. |
| URL.MalwareFamily | String | The malware family associated with the URL. |
| URL.Relationships.EntityA | String | The source of the relationship. |
| URL.Relationships.EntityAType | String | The type of the source of the relationship. |
| URL.Relationships.EntityB | String | The destination of the relationship. |
| URL.Relationships.EntityBType | String | The type of the destination of the relationship. |
| URL.Relationships.Relationship | String | The name of the relationship. |
| AutoFocus.URL.IndicatorValue | String | The URL value. |
| AutoFocus.URL.IndicatorType | String | The indicator type. |
| AutoFocus.URL.LatestPanVerdicts | Unknown | The latest verdicts from Palo Alto Networks products. Can be either “PAN_DB” or “WF_SAMPLE”(WildFire). |
| URL.Malicious.Vendor | String | The vendor that decided the file is malicious. |
| AutoFocus.URL.Tags.PublicTagName | String | The public name of the tag. This is used as an ID of the tag. |
| AutoFocus.URL.Tags.TagName | String | The simple name of the tag. |
| AutoFocus.URL.Tags.CustomerName | String | The organization that created the tag. |
| AutoFocus.URL.Tags.Source | String | The organization or individual that discovered the threat that is defined in the tag. |
| AutoFocus.URL.Tags.TagDefinitionScopeID | Number | The scope ID of the tag. |
| AutoFocus.URL.Tags.TagDefinitionStatusID | Number | The definition status ID of the tag. |
| AutoFocus.URL.Tags.TagClassID | Number | The classification ID of the tag. |
| AutoFocus.URL.Tags.Count | Number | The number of samples that matched this tag. |
| AutoFocus.URL.Tags.Lasthit | Date | The date that the tag was last encountered. |
| AutoFocus.URL.Tags.Description | String | The description of the tag. |
Command Example
!url url=www.andromedaa.ir/ir/andromedaa/likebegir/ap.smali/ using-brand="AutoFocus V2"
Context Example
{
"URL": [
{
"Malicious": {
"Vendor": "AutoFocus V2"
},
"Data": "www.andromedaa.ir/ir/andromedaa/likebegir/ap.smali/"
}
],
"DBotScore": [
{
"Vendor": "AutoFocus V2",
"Indicator": "www.andromedaa.ir/ir/andromedaa/likebegir/ap.smali/",
"Score": 3,
"Type": "url"
}
],
"AutoFocus.URL": [
{
"SeenBy": [],
"LatestPanVerdicts": {
"PAN_DB": "MALWARE"
},
"WildfireRelatedSampleVerdictCounts": {},
"IndicatorValue": "www.andromedaa.ir/ir/andromedaa/likebegir/ap.smali/",
"IndicatorType": "URL"
}
]
}
Human Readable Output
AutoFocus V2 URL reputation for: www.andromedaa.ir/ir/andromedaa/likebegir/ap.smali/
| Indicatortype | Indicatorvalue | Latestpanverdicts | Seenby | Wildfirerelatedsampleverdictcounts |
|---|---|---|---|---|
| URL | www.andromedaa.ir/ir/andromedaa/likebegir/ap.smali/ | PAN_DB: MALWARE |
Get the reputation of a file
Returns the reputation of a file.
Base Command
file
Input
| Argument Name | Description | Required |
|---|---|---|
| file | The SHA256 hash of the file. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Indicator | String | The indicator that was tested. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.Tags | String | Tags that are associated with the file. |
| File.MalwareFamily | String | The malware family associated with the file. |
| File.Relationships.EntityA | String | The source of the relationship. |
| File.Relationships.EntityAType | String | The type of the source of the relationship. |
| File.Relationships.EntityB | String | The destination of the relationship. |
| File.Relationships.EntityBType | String | The type of the destination of the relationship. |
| File.Relationships.Relationship | String | The name of the relationship. |
| AutoFocus.File.IndicatorValue | String | The SHA256 hash value of the file. |
| AutoFocus.File.IndicatorType | String | The indicator type. |
| AutoFocus.File.LatestPanVerdicts | Unknown | The latest verdicts from Palo Alto Networks products. Can be either “PAN_DB” or “WF_SAMPLE”(WildFire). |
| File.Malicious.Vendor | String | The vendor that decided the file is malicious. |
| AutoFocus.File.Tags.PublicTagName | String | The public name of the tag. This is used as an ID of the tag. |
| AutoFocus.File.Tags.TagName | String | The simple name of the tag. |
| AutoFocus.File.Tags.CustomerName | String | The organization that created the tag. |
| AutoFocus.File.Tags.Source | String | The organization or individual that discovered the threat that is defined in the tag. |
| AutoFocus.File.Tags.TagDefinitionScopeID | Number | The scope ID of the tag. |
| AutoFocus.File.Tags.TagDefinitionStatusID | Number | The definition status ID of the tag. |
| AutoFocus.File.Tags.TagClassID | Number | The classification ID of the tag. |
| AutoFocus.File.Tags.Count | Number | The number of samples that matched this tag. |
| AutoFocus.File.Tags.Lasthit | Date | The date that the tag was last encountered. |
| AutoFocus.File.Tags.Description | String | The description of the tag. |
Command Example
!file file=9040e9fda52931c9472c90ecad5b74295cdb9cf7b68e2b89219700f6a8bff5ac using-brand="AutoFocus V2"
Context Example
{
"DBotScore": [
{
"Vendor": "AutoFocus V2",
"Indicator": "9040e9fda52931c9472c90ecad5b74295cdb9cf7b68e2b89219700f6a8bff5ac",
"Score": 3,
"Type": "file"
}
],
"File": [
{
"Malicious": {
"Vendor": "AutoFocus V2"
},
"SHA256": "9040e9fda52931c9472c90ecad5b74295cdb9cf7b68e2b89219700f6a8bff5ac"
}
],
"AutoFocus.File": [
{
"SeenBy": [
"WF_SAMPLE"
],
"LatestPanVerdicts": {
"WF_SAMPLE": "MALWARE"
},
"WildfireRelatedSampleVerdictCounts": "",
"IndicatorType": "FILEHASH",
"IndicatorValue": "9040e9fda52931c9472c90ecad5b74295cdb9cf7b68e2b89219700f6a8bff5ac",
"LastSeen": "2019-12-29T08:52:27.000Z",
"FirstSeen": "2019-09-24T06:46:21.000Z"
}
]
}
Human Readable Output
AutoFocus V2 File reputation for: 9040e9fda52931c9472c90ecad5b74295cdb9cf7b68e2b89219700f6a8bff5ac
| Firstseen | Indicatortype | Indicatorvalue | Lastseen | Latestpanverdicts | Seenby | Wildfirerelatedsampleverdictcounts |
|---|---|---|---|---|---|---|
| 2019-09-24T06:46:21.000Z | FILEHASH | 9040e9fda52931c9472c90ecad5b74295cdb9cf7b68e2b89219700f6a8bff5ac | 2019-12-29T08:52:27.000Z | WF_SAMPLE: MALWARE | WF_SAMPLE |
Get the reputation of a domain name
Returns the reputation of a domain.
Base Command
domain
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | The domain to check. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Indicator | String | The indicator that was tested. |
| Domain.Name | String | The name of the domain. |
| Domain.Tags | String | Tags that are associated with the domain. |
| Domain.MalwareFamily | String | The malware family associated with the domain. |
| Domain.Relationships.EntityA | String | The source of the relationship. |
| Domain.Relationships.EntityAType | String | The type of the source of the relationship. |
| Domain.Relationships.EntityB | String | The destination of the relationship. |
| Domain.Relationships.EntityBType | String | The type of the destination of the relationship. |
| Domain.Relationships.Relationship | String | The name of the relationship. |
| AutoFocus.Domain.IndicatorValue | String | The value of the domain. |
| AutoFocus.Domain.IndicatorType | String | The indicator type. |
| AutoFocus.Domain.LatestPanVerdicts | Unknown | The latest verdicts from Palo Alto Networks products. Can be either “PAN_DB” or “WF_SAMPLE”(WildFire). |
| Domain.Malicious.Vendor | String | The vendor that decided the file is malicious. |
| AutoFocus.Domain.Tags.PublicTagName | String | The public name of the tag. This is used as an ID of the tag. |
| AutoFocus.Domain.Tags.TagName | String | The simple name of the tag. |
| AutoFocus.Domain.Tags.CustomerName | String | The organization that created the tag. |
| AutoFocus.Domain.Tags.Source | String | The organization or individual that discovered the threat that is defined in the tag. |
| AutoFocus.Domain.Tags.TagDefinitionScopeID | Number | The scope ID of the tag. |
| AutoFocus.Domain.Tags.TagDefinitionStatusID | Number | The definition status ID of the tag. |
| AutoFocus.Domain.Tags.TagClassID | Number | The classification ID of the tag. |
| AutoFocus.Domain.Tags.Count | Number | The number of samples that matched this tag. |
| AutoFocus.Domain.Tags.Lasthit | Date | The date that the tag was last encountered. |
| AutoFocus.Domain.Tags.Description | String | The description of the tag. |
| AutoFocus.Domain.WhoisAdminCountry | String | The country of the domain administrator. |
| AutoFocus.Domain.WhoisAdminEmail | String | The email address of the domain administrator. |
| AutoFocus.Domain.WhoisAdminName | String | The name of the domain administrator. |
| AutoFocus.Domain.WhoisDomainCreationDate | Date | The date that the domain was created. |
| AutoFocus.Domain.WhoisDomainExpireDate | Date | The date that the domain expires. |
| AutoFocus.Domain.WhoisDomainUpdateDate | Date | The date that the domain was last updated. |
| AutoFocus.Domain.WhoisRegistrar | String | The name of the registrar. |
| AutoFocus.Domain.WhoisRegistrarUrl | String | The email address of the registrar. |
| AutoFocus.Domain.WhoisRegistrant | String | The name of the registrant. |
Command Example
!domain domain=google.com using-brand="AutoFocus V2"
Context Example
{
"Domain": [
{
"Name": "google.com",
"WHOIS": {
"Admin": {
"Email": null,
"Name": null
},
"UpdatedDate": "2018-02-21",
"Registrar": {
"Name": "markdownguide Inc."
},
"ExpirationDate": "2020-09-14",
"CreationDate": "1997-09-15",
"Registrant": {
"Name": null
}
}
}
],
"AutoFocus.Domain": [
{
"SeenBy": [],
"LatestPanVerdicts": {
"PAN_DB": "BENIGN"
},
"WhoisAdminName": null,
"WhoisDomainExpireDate": "2020-09-14",
"WhoisRegistrarUrl": "www.markdownguide.org",
"WildfireRelatedSampleVerdictCounts": {},
"IndicatorType": "DOMAIN",
"WhoisRegistrant": null,
"WhoisRegistrar": "markdownguide Inc.",
"IndicatorValue": "google.com",
"WhoisAdminEmail": null,
"WhoisDomainCreationDate": "1997-09-15",
"WhoisAdminCountry": null,
"WhoisDomainUpdateDate": "2018-02-21"
}
],
"DBotScore": [
{
"Vendor": "AutoFocus V2",
"Indicator": "google.com",
"Score": 1,
"Type": "domain"
}
]
}
Human Readable Output
AutoFocus V2 Domain reputation for: google.com
| Indicatortype | Indicatorvalue | Latestpanverdicts | Seenby | Whoisadmincountry | Whoisadminemail | Whoisadminname | Whoisdomaincreationdate | Whoisdomainexpiredate | Whoisdomainupdatedate | Whoisregistrant | Whoisregistrar | Whoisregistrarurl | Wildfirerelatedsampleverdictcounts |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| DOMAIN | google.com | PAN_DB: BENIGN | 1997-09-15 | 2020-09-14 | 2018-02-21 | markdownguide Inc. | http://www.markdownguide.org |
autofocus-get-export-list-indicators
Gets export list indicators from AutoFocus.
Base Command
autofocus-get-export-list-indicators
Input
| Argument Name | Description | Required |
|---|---|---|
| label | The label of the exported list. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| AutoFocus.ExportListIndicator.Type | String | The indicator type in the export list. |
| AutoFocus.ExportListIndicator.Value | String | The value of the indicator in the export list. |
| IP.Address | String | The IP address. |
| URL.Data | String | The URL address. |
| File.SHA256 | String | The SHA256 hash of the file. |
| Domain.Name | String | The domain name. |
Configuration parameters
credentials—api_key— API KeyintegrationReliability— Source Reliabilityinsecure— Trust any certificate (not secure)proxy— Use system proxy settingshandle_error— Suppress errors for non found indicatorsmark_as_malicious— Additional malicious verdictscreate_relationships— Create relationships
Commands (14)
-
autofocus-get-export-list-indicatorsGets export list indicators from AutoFocus.
-
autofocus-get-session-detailsGet session details by session ID.
-
autofocus-sample-analysisReturns properties, behaviors, and activities observed for a sample. Run the command a single time to get the fields and operating systems under HTTP, Coverage, Behavior, Registry, Files, Processes, Connections, and DNS.
-
autofocus-samples-search-resultsReturns results of a previous samples search. `Autofocus Query Samples, Sessions and Tags` Playbook is recommended for querying and polling.
-
autofocus-search-samplesSearches for samples in AutoFocus. To view results, run the autofocus-samples-search-results command with the returned AF Cookie. The AF Cookie expires 120 seconds after the search completes. `Autofocus Query Samples, Sessions and Tags` Playbook is recommended for querying and polling.
-
autofocus-search-sessionsSearches for sessions in AutoFocus. To view results, run the autofocus-sessions-search-results command with the returned AF Cookie. The AF Cookie expires 120 seconds after the search completes. The `polling` argument was added in XSOAR 6.2.0. It enables handling the search in a single command, rather than using the `Autofocus Query Samples, Sessions and Tags` Playbook.
-
autofocus-sessions-search-resultsReturns results of a previous sessions search. `Autofocus Query Samples, Sessions and Tags` Playbook is recommended for querying and polling.
-
autofocus-tag-detailsReturns details about the given tag.
-
autofocus-top-tags-resultsReturns the results of a previous top tags search. `Autofocus Query Samples, Sessions and Tags` Playbook is recommended for querying and polling.
-
autofocus-top-tags-searchPerforms a search to identify the most popular tags. `Autofocus Query Samples, Sessions and Tags` Playbook is recommended for querying and polling.
-
domainChecks the reputation of a domain in AutoFocus.
-
fileChecks the reputation of a file in AutoFocus.
-
ipChecks the reputation of an IP address in AutoFocus.
-
urlChecks the reputation of a URL in AutoFocus.
from requests import Response from CommonServerPython import * """ IMPORTS """ import socket import traceback from collections.abc import Callable """ GLOBALS/PARAMS """ PARAMS = demisto.params() API_KEY = AutoFocusKeyRetriever(PARAMS.get("credentials", {}).get("password") or PARAMS.get("api_key")).key # Remove trailing slash to prevent wrong URL path to service SERVER = "https://autofocus.paloaltonetworks.com" # Service base URL BASE_URL = SERVER + "/api/v1.0" VENDOR_NAME = "AutoFocus V2" # Headers to be sent in requests HEADERS = {"Content-Type": "application/json"} RELATIONSHIP_TYPE_BY_TAG_CLASS_ID = { 1: {"entity_b_type": "STIX Threat Actor", "name": "indicator-of"}, 2: {"entity_b_type": "Campaign", "name": "indicator-of"}, 3: {"entity_b_type": "STIX Malware", "name": "indicator-of"}, 5: {"entity_b_type": "STIX Attack Pattern", "name": "indicator-of"}, } API_PARAM_DICT = { "scope": {"Private": "private", "Public": "public", "Global": "global"}, "order": {"Ascending": "asc", "Descending": "desc"}, "artifact": "artifactSource", "sort": { "App Name": "app_name", "App Packagename": "app_packagename", "File type": "filetype", "Size": "size", "Finish Date": "finish_date", "First Seen (Create Date)": "create_date", "Last Updated (Update Date)": "update_date", "MD5": "md5", "SHA1": "sha1", "SHA256": "sha256", "Ssdeep Fuzzy Hash": "ssdeep", "Application": "app", "Device Country": "device_country", "Device Country Code": "device_countrycode", "Device Hostname": "device_hostname", "Device Serial": "device_serial", "Device vsys": "vsys", "Destination Country": "dst_country", "Destination Country Code": "dst_countrycode", "Destination IP": "dst_ip", "Destination Port": "dst_port", "Email Charset": "emailsbjcharset", "Industry": "device_industry", "Source Country": "src_country", "Source Country Code": "src_countrycode", "Source IP": "src_ip", "Source Port": "src_port", "Time": "tstamp", "Upload source": "upload_srcPossible", }, "tag_class": { "Actor": "actor", "Campaign": "campaign", "Exploit": "exploit", "Malicious Behavior": "malicious_behavior", "Malware Family": "malware_family", }, "search_arguments": { "file_hash": {"api_name": "alias.hash_lookup", "operator": "is"}, "domain": {"api_name": "alias.domain", "operator": "contains"}, "ip": {"api_name": "alias.ip_address", "operator": "contains"}, "url": {"api_name": "alias.url", "operator": "contains"}, "wildfire_verdict": { "api_name": "sample.malware", "operator": "is", "translate": { "Malware": 1, "Grayware": 2, "Benign": 3, "Phishing": 4, }, }, "first_seen": {"api_name": "sample.create_date", "operator": "is in the range"}, "last_updated": {"api_name": "sample.update_date", "operator": "is in the range"}, "time_range": {"api_name": "session.tstamp", "operator": "is in the range"}, "time_after": {"api_name": "session.tstamp", "operator": "is after"}, "time_before": {"api_name": "session.tstamp", "operator": "is before"}, }, "file_indicators": { "Size": "Size", "SHA1": "SHA1", "SHA256": "SHA256", "FileType": "Type", "Tags": "Tags", "FileName": "Name", }, "search_results": { "sha1": "SHA1", "sha256": "SHA256", "filetype": "FileType", "malware": "Verdict", "size": "Size", "create_date": "Created", "finish_date": "Finished", "md5": "MD5", "region": "Region", "tag": "Tags", "_id": "ID", "tstamp": "Seen", "filename": "FileName", "device_industry": "Industry", "upload_src": "UploadSource", "fileurl": "FileURL", "artifact": "Artifact", }, } SAMPLE_ANALYSIS_LINE_KEYS = { "behavior": {"display_name": "behavior", "indexes": {"risk": 0, "behavior": -1}}, "process": {"display_name": "processes", "indexes": {"parent_process": 0, "action": 1}}, "file": {"display_name": "files", "indexes": {"parent_process": 0, "action": 1}}, "registry": {"display_name": "registry", "indexes": {"action": 1, "parameters": 2}}, "dns": {"display_name": "DNS", "indexes": {"query": 0, "response": 1}}, "http": {"display_name": "HTTP", "indexes": {"host": 0, "method": 1, "url": 2}}, "connection": {"display_name": "connections", "indexes": {"destination": 2}}, "mutex": {"display_name": "mutex", "indexes": {"process": 0, "action": 1, "parameters": 2}}, } SAMPLE_ANALYSIS_COVERAGE_KEYS = { "wf_av_sig": {"display_name": "wildfire_signatures", "fields": ["name", "create_date"]}, "fileurl_sig": {"display_name": "fileurl_signatures", "fields": ["name", "create_date"]}, "dns_sig": {"display_name": "dns_signatures", "fields": ["name", "create_date"]}, "url_cat": {"display_name": "url_categories", "fields": ["url", "cat"]}, } VERDICTS_TO_DBOTSCORE = {"benign": 1, "malware": 3, "grayware": 2, "phishing": 3, "c2": 3} ERROR_DICT = { 404: "Invalid URL.", 408: "Invalid URL.", 409: "Invalid message or missing parameters.", 500: "Internal error.", 503: "Rate limit exceeded.", } if PARAMS.get("mark_as_malicious"): verdicts = argToList(PARAMS.get("mark_as_malicious")) VERDICTS_TO_DBOTSCORE.update(dict.fromkeys(verdicts, 3)) DEFAULT_BUCKET_INFO = dict.fromkeys( ( "minute_points", "daily_points", "minute_points_remaining", "daily_points_remaining", "minute_bucket_start", "daily_bucket_start", ), "Unavailable", ) EXECUTION_METRICS = ExecutionMetrics() API_POINTS_TABLE = CommandResults(outputs_prefix="AutoFocus.Quota", replace_existing=True) """ CLIENT CLASS """ class Client(BaseClient): def __init__(self, url: str, verify: bool = True, proxy: bool = False): super().__init__(base_url=url, verify=verify, proxy=proxy) def parse_response(self, resp: requests.Response, err_operation: str | None) -> dict: try: res_json = resp.json() save_api_metrics(res_json) # type: ignore if resp.status_code == 503: EXECUTION_METRICS.quota_error += 1 raise RateLimitExceededError(res_json) # Handle error responses gracefully if demisto.params().get("handle_error", True) and resp.status_code == 409: EXECUTION_METRICS.service_error += 1 raise Exception("Response status code: 409 \nRequested sample not found") resp.raise_for_status() if "x-trace-id" in resp.headers: # this debug log was request by autofocus team for debugging on their end purposes demisto.debug(f'x-trace-id: {resp.headers["x-trace-id"]}') EXECUTION_METRICS.success += 1 return res_json # Errors returned from AutoFocus except requests.exceptions.HTTPError: EXECUTION_METRICS.general_error += 1 raise DemistoException(f'{err_operation}: {res_json.get("message")}') # Unexpected errors (where no json object was received) except Exception as err: EXECUTION_METRICS.general_error += 1 raise DemistoException(f"{err_operation}: {err}") def http_request( self, url_suffix, method="POST", data={}, err_operation=None, ok_codes=(200, 409, 503), headers=HEADERS, params={} ): """A general http request. Args: method: str - the method to perform in the http request (GET, POST, etc.) url_suffix: str - the url_suffix for the http request. data: Any - the data for the request. err_operation: str - The string that will be in the exception in case one occurred. ok_codes: tuple - a list of status codes that we want to handle in the code and not raise automatic exception about. headers: dict - the headers of the request params: dict - the parameters of the request Returns: A response object in case of a GET method (url, ip, domain, file), otherwise a dict. """ # The GET method is used only in search_indicator commands (url, ip, domain, file), and they have the API key in # the headers instead of data. if method == "POST": data.update({"apiKey": API_KEY}) try: demisto.debug("http_request: before the request") res = self._http_request( method=method, url_suffix=url_suffix, data=json.dumps(data), headers=headers, resp_type="response", ok_codes=ok_codes, retries=3, params=params, ) demisto.debug(f"http_request: {res=}") # Handle with connection error except requests.exceptions.ConnectionError as err: demisto.debug("http_request in requests.exceptions.ConnectionError") EXECUTION_METRICS.connection_error += 1 raise DemistoException(f"Error connecting to server. Check your URL/Proxy/Certificate settings: {err}") # for the different search_indicator commands (url, ip, domain, file) the calling function handles the different # status codes. if method == "GET": return res return self.parse_response(res, err_operation) """ HELPER FUNCTIONS """ class RateLimitExceededError(BaseException): def __init__(self, api_res: dict) -> None: super().__init__() self.api_res = api_res def return_metrics(): if EXECUTION_METRICS.metrics is not None and ExecutionMetrics.is_supported(): return_results(EXECUTION_METRICS.metrics) if API_POINTS_TABLE.readable_output: return_results(API_POINTS_TABLE) """ COMMAND FUNCTIONS """ def rerun_command_if_required(api_res: dict, retry_on_rate_limit: bool): daily_points_remaining = dict_safe_get(api_res, ("bucket_info", "daily_points_remaining"), 0) next_run = int(dict_safe_get(api_res, ("bucket_info", "wait_in_seconds"), 70, (int, float))) # type: ignore if retry_on_rate_limit and daily_points_remaining and next_run < 300: results = CommandResults( readable_output="API Rate limit exceeded, rerunning command.", scheduled_command=ScheduledCommand( command=demisto.command(), args=(demisto.args() | {"retry_on_rate_limit": "false"}), next_run_in_seconds=(next_run + 20), ), ) else: results = CommandResults( readable_output=f'Error in API call to AutoFocus.\nMessage: {api_res.get("message")}', entry_type=EntryType.ERROR, raw_response=f'Error in API call to AutoFocus.\nMessage: {api_res.get("message")}', ) return_results(results) def save_api_metrics(res_obj: dict): if bucket_info := res_obj.get("bucket_info"): demisto.debug(f"save_api_metrics: {bucket_info=}") API_POINTS_TABLE.readable_output = tableToMarkdown( "Autofocus API Points", { "Daily points used": "{daily_points_remaining}/{daily_points}", "Daily allotment started": "{daily_bucket_start}", "Minute points used": "{minute_points_remaining}/{minute_points}", "Minute allotment started": "{minute_bucket_start}", }, ).format(**(DEFAULT_BUCKET_INFO | bucket_info)) API_POINTS_TABLE.outputs = bucket_info else: demisto.debug("save_api_metrics: no bucket_info") def run_polling_command(client: Client, args: dict, cmd: str, search_function: Callable, results_function: Callable): interval_in_secs = arg_to_number(args.get("interval_in_seconds", 60)) if "af_cookie" not in args: # create new search command_results = search_function(client, args) outputs = command_results.outputs af_cookie = outputs.get("AFCookie") if outputs.get("Status") != "complete": polling_args = {"af_cookie": af_cookie, "interval_in_seconds": interval_in_secs, "polling": True, **args} command_results.scheduled_command = ScheduledCommand( command=cmd, next_run_in_seconds=interval_in_secs, # type: ignore args=polling_args, timeout_in_seconds=600, ) return command_results else: # continue to look for search results args["af_cookie"] = af_cookie # get search status command_results, status = results_function(client, args) if status != "complete": # schedule next poll polling_args = {"af_cookie": args.get("af_cookie"), "interval_in_seconds": interval_in_secs, "polling": True, **args} scheduled_command = ScheduledCommand( command=cmd, next_run_in_seconds=interval_in_secs, # type: ignore args=polling_args, timeout_in_seconds=600, ) # result with scheduled_command only - no update to the war room command_results = CommandResults(scheduled_command=scheduled_command) return command_results def validate_sort_and_order_and_artifact( sort: Optional[str] = None, order: Optional[str] = None, artifact_source: Optional[str] = None ) -> bool: """ Function that validates the arguments combination. sort and order arguments must be defined together. Sort and order can't appear with artifact. Args: sort: variable to sort by. order: the order which the results is ordered by. artifact_source: true if artifacts are needed and false otherwise. Returns: true if arguments are valid for the request, false otherwise. """ if artifact_source == "true" and sort: raise Exception("Please remove or disable one of sort or artifact, As they are not supported in the api together.") elif sort and not order: raise Exception("Please specify the order of sorting (Ascending or Descending).") elif order and not sort: raise Exception("Please specify a field to sort by.") return bool(sort and order) def do_search( client: Client, search_object: str, query: dict, scope: Optional[str], size: Optional[str] = None, sort: Optional[str] = None, order: Optional[str] = None, err_operation: Optional[str] = None, artifact_source: Optional[str] = None, ) -> dict: """ This function created the data to be sent in http request and sends it. Args: client: The client to make the requests with. search_object: Type of search sessions or samples. query: Query based on conditions specified within this object. scope: Scope of the search. Only available and required for: samples. e.g. Public, Global, Private. size: Number of results to provide. sort: Sort based on the provided artifact. order: How to display sort results in ascending or descending order. err_operation: String error which specificed which command failed. artifact_source: Whether artifacts are wanted or not. Returns: raw response of the http request. """ path = "/samples/search" if search_object == "samples" else "/sessions/search" data = {"query": query, "size": size} if scope: data.update({"scope": API_PARAM_DICT["scope"][scope]}) # type: ignore if validate_sort_and_order_and_artifact(sort, order, artifact_source): data.update({"sort": {API_PARAM_DICT["sort"][sort]: {"order": API_PARAM_DICT["order"][order]}}}) # type: ignore if artifact_source == "true": data.update({"artifactSource": "af"}) data.update({"type": "scan"}) # Remove nulls data = createContext(data, removeNull=True) demisto.debug(f"do_search: {path=} {data=} {err_operation=}") result = client.http_request(url_suffix=path, data=data, err_operation=err_operation) return result def run_search( client: Client, search_object: str, query: str, scope: Optional[str] = None, size: str = None, sort: str = None, order: str = None, artifact_source: str = None, ) -> dict: """ This function searches the relevent search and returns search info for result command. Args: client: The client to make the requests with. search_object: Type of search sessions or samples. query: Query based on conditions specified within this object. scope: Scope of the search. Only available and required for: samples. e.g. Public, Global, Private. size: Number of results to provide. sort: Sort based on the provided artifact. order: How to display sort results in ascending or descending order. artifact_source: Whether artifacts are wanted or not. Returns: dict of response for result commands. """ result = do_search( client, search_object, query=json.loads(query), scope=scope, size=size, sort=sort, order=order, artifact_source=artifact_source, err_operation="Search operation failed", ) in_progress = result.get("af_in_progress") status = "in progress" if in_progress else "complete" search_info = { "AFCookie": result.get("af_cookie"), "Status": status, "SessionStart": datetime.now().strftime("%Y-%m-%dT%H:%M:%S"), } return search_info def run_get_search_results(client: Client, search_object, af_cookie): path = f"/samples/results/{af_cookie}" if search_object == "samples" else f"/sessions/results/{af_cookie}" results = client.http_request(url_suffix=path, err_operation="Fetching search results failed") return results def get_fields_from_hit_object(result_object, response_dict_name): new_object = {} af_params_dict = API_PARAM_DICT.get(response_dict_name) for key, value in result_object.items(): if key in af_params_dict: # type: ignore new_key = af_params_dict.get(key) # type: ignore new_object[new_key] = value else: new_object[key] = value return new_object def parse_hits_response(hits, response_dict_name): parsed_objects = [] # type: ignore if not hits: return parsed_objects else: for hit in hits: flattened_obj = {} # type: ignore flattened_obj.update(hit.get("_source")) flattened_obj["_id"] = hit.get("_id") parsed_obj = get_fields_from_hit_object(flattened_obj, response_dict_name) parsed_objects.append(parsed_obj) return parsed_objects def get_search_results(client: Client, search_object, af_cookie): results = run_get_search_results(client, search_object, af_cookie) retry_count = 0 # Checking if the query has no results because the server has not fetched them yet. # In this case, the complete percentage would be 0 (or lower than 100). # In a case where there really aren't results (hits), the af_complete_percentage would be 100. while (not results.get("hits") and (results.get("af_complete_percentage", 0) != 100)) and retry_count < 10: time.sleep(5) results = run_get_search_results(client, search_object, af_cookie) retry_count += 1 parsed_results = parse_hits_response(results.get("hits"), "search_results") in_progress = results.get("af_in_progress") status = "in progress" if in_progress else "complete" return parsed_results, status def get_session_details(client: Client, session_id): path = f"/session/{session_id}" result = client.http_request(url_suffix=path, err_operation="Get session failed") parsed_result = parse_hits_response(result.get("hits"), "search_results") return parsed_result def validate_if_line_needed(category, info_line): line = info_line.get("line") line_values = line.split(",") category_indexes = SAMPLE_ANALYSIS_LINE_KEYS.get(category).get("indexes") # type: ignore if category == "behavior": risk_index = category_indexes.get("risk") # type: ignore risk = line_values[risk_index].strip() # only lines with risk higher the informational are considered return risk != "informational" elif category == "registry": action_index = category_indexes.get("action") # type: ignore action = line_values[action_index].strip() # Only lines with actions SetValueKey, CreateKey or RegSetValueEx are considered return action in ("SetValueKey", "CreateKey", "RegSetValueEx") elif category == "file": action_index = category_indexes.get("action") # type: ignore action = line_values[action_index].strip() benign_count = info_line.get("b") if info_line.get("b") else 0 malicious_count = info_line.get("m") if info_line.get("m") else 0 # Only lines with actions Create or CreateFileW where malicious count is grater than benign count are considered return action in ("Create", "CreateFileW") and malicious_count > benign_count elif category == "process": action_index = category_indexes.get("action") # type: ignore action = line_values[action_index].strip() # Only lines with actions created, CreateKey or CreateProcessInternalW are considered return action in ("created", "CreateProcessInternalW") else: return True def get_data_from_line(line, category_name): category_indexes = SAMPLE_ANALYSIS_LINE_KEYS.get(category_name).get("indexes") # type: ignore values = line.split(",") sub_categories = {} # type: ignore if not category_indexes: return sub_categories else: for sub_category in category_indexes: # type: ignore sub_category_index = category_indexes.get(sub_category) # type: ignore sub_categories.update({sub_category: values[sub_category_index]}) return sub_categories def get_data_from_coverage_sub_category(sub_category_name, sub_category_data): sub_categories_list = [] for item in sub_category_data: new_sub_category = {} fields_to_extract = SAMPLE_ANALYSIS_COVERAGE_KEYS.get(sub_category_name).get("fields") # type: ignore for field in fields_to_extract: # type: ignore new_sub_category[field] = item.get(field) # type: ignore sub_categories_list.append(new_sub_category) return sub_categories_list def parse_coverage_sub_categories(coverage_data): new_coverage = {} for sub_category_name, sub_category_data in coverage_data.items(): if sub_category_name in SAMPLE_ANALYSIS_COVERAGE_KEYS and isinstance(sub_category_data, dict): new_sub_category_data = get_data_from_coverage_sub_category(sub_category_name, sub_category_data) new_sub_category_name = SAMPLE_ANALYSIS_COVERAGE_KEYS.get(sub_category_name).get( # type: ignore "display_name" ) # type: ignore new_coverage[new_sub_category_name] = new_sub_category_data return {"coverage": new_coverage} def parse_lines_from_os(category_name, data, filter_data_flag): new_lines = [] for info_line in data: if not filter_data_flag or validate_if_line_needed(category_name, info_line): new_sub_categories = get_data_from_line(info_line.get("line"), category_name) new_lines.append(new_sub_categories) return new_lines def parse_sample_analysis_response(resp, filter_data_flag): analysis = {} for category_name, category_data in resp.items(): if category_name in SAMPLE_ANALYSIS_LINE_KEYS: new_category = {} for os_name, os_data in category_data.items(): os_sanitized_data = parse_lines_from_os(category_name, os_data, filter_data_flag) new_category[os_name] = os_sanitized_data category_dict = SAMPLE_ANALYSIS_LINE_KEYS.get(category_name) analysis.update({category_dict["display_name"]: new_category}) # type: ignore elif category_name == "coverage": new_category = parse_coverage_sub_categories(category_data) analysis.update(new_category) return analysis def sample_analysis(client: Client, sample_id, os, filter_data_flag): path = f"/sample/{sample_id}/analysis" data = {"coverage": "true"} if os: data["platforms"] = [os] # type: ignore result = client.http_request(url_suffix=path, data=data, err_operation="Sample analysis failed") if "error" in result: return demisto.results(result["error"]) analysis_obj = parse_sample_analysis_response(result, filter_data_flag) return analysis_obj def parse_tag_details_response(resp): tag_details = resp.get("tag") fields_to_extract_from_tag_details = [ "public_tag_name", "tag_name", "customer_name", "source", "tag_definition_scope", "tag_definition_status", "tag_class", "count", "lasthit", "description", ] new_tag_info = {} for field in fields_to_extract_from_tag_details: new_tag_info[field] = tag_details.get(field) tag_group_details = resp.get("tag_groups") if tag_group_details: new_tag_info["tag_group"] = tag_group_details return new_tag_info def autofocus_tag_details(client: Client, tag_name): path = f"/tag/{tag_name}" resp = client.http_request(url_suffix=path, err_operation="Tag details operation failed") tag_info = parse_tag_details_response(resp) return tag_info def validate_tag_scopes(private, public, commodity, unit42): if not any((private, public, commodity, unit42)): raise DemistoException("Add at least one Tag scope by setting `commodity`, `private`, `public` or `unit42` to True") def autofocus_top_tags_search(client: Client, scope, tag_class_display, private, public, commodity, unit42): validate_tag_scopes(private, public, commodity, unit42) tag_class = API_PARAM_DICT["tag_class"][tag_class_display] # type: ignore query = {"operator": "all", "children": [{"field": "sample.tag_class", "operator": "is", "value": tag_class}]} tag_scopes = [] if private: tag_scopes.append("private") if public: tag_scopes.append("public") if commodity: tag_scopes.append("commodity") if unit42: tag_scopes.append("unit42") data = {"query": query, "scope": scope, "tagScopes": tag_scopes} path = "/top-tags/search/" resp = client.http_request(url_suffix=path, data=data, err_operation="Top tags operation failed") in_progress = resp.get("af_in_progress") status = "in progress" if in_progress else "complete" search_info = {"AFCookie": resp.get("af_cookie"), "Status": status} return search_info def parse_top_tags_response(response): top_tags_list = [] # type: ignore top_tags = response.get("top_tags") if not top_tags: return top_tags_list else: for tag in top_tags: fields_to_extract_from_top_tags = ["tag_name", "public_tag_name", "count", "lasthit"] new_tag = {} for field in fields_to_extract_from_top_tags: new_tag[field] = tag[field] top_tags_list.append(new_tag) return top_tags_list def get_top_tags_results(client: Client, af_cookie): path = f"/top-tags/results/{af_cookie}" results = client.http_request(url_suffix=path, err_operation="Fetching top tags results failed") top_tags = parse_top_tags_response(results) in_progress = results.get("af_in_progress") status = "in progress" if in_progress else "complete" return top_tags, status def print_hr_by_category(category_name, category_data): hr = content = f"### {string_to_table_header(category_name)}:\nNo entries" if category_name == "coverage": content = category_data if category_data: hr = tableToMarkdown( f"{string_to_table_header(category_name)}:", category_data, headerTransform=string_to_table_header ) else: hr = f"### {string_to_table_header(category_name)}:\nNo entries" demisto.results({"Type": entryTypes["note"], "ContentsFormat": formats["text"], "Contents": content, "HumanReadable": hr}) else: for os_name, os_data in category_data.items(): content = os_data table_header = f"{category_name}_{os_name}" if os_data: hr = tableToMarkdown(f"{string_to_table_header(table_header)}:", os_data, headerTransform=string_to_table_header) else: hr = f"### {string_to_table_header(table_header)}:\nNo entries" demisto.results( {"Type": entryTypes["note"], "ContentsFormat": formats["text"], "Contents": content, "HumanReadable": hr} ) def get_files_data_from_results(results): """ Gets a list of results and for each result returns a file object includes all relevant file indicators exists in that result :param results: a list of dictionaries :return: a list of file objects """ files = [] if results: for result in results: raw_file = get_fields_from_hit_object(result, "file_indicators") file_data = filter_object_entries_by_dict_values(raw_file, "file_indicators") files.append(file_data) return files def filter_object_entries_by_dict_values(result_object, response_dict_name): """ Gets a dictionary (result_object) and filters it's keys by the values of another dictionary (response_dict_name) input: response_dict_name = 'file_indicators' - see API_PARAM_DICT above result_object = { "app": "web-browsing", "vsys": 1, "SHA256": "18c9acd34a3aea09121f027857e0004a3ea33a372b213a8361e8a978330f0dc8", "UploadSource": "Firewall", "src_port": 80, "device_serial": "007051000050926", "Seen": "2019-07-24T09:37:04", "Name": "wildfire-test-pe-file.exe", "user_id": "unknown", "src_country": "United States", "src_countrycode": "US", "dst_port": 65168, "device_countrycode": "US", "Industry": "High Tech", "Region": "us", "device_country": "United States", "ID": "179972200903" } output: { "SHA256": "18c9acd34a3aea09121f027857e0004a3ea33a372b213a8361e8a978330f0dc8", "Name": "wildfire-test-pe-file.exe" } :param result_object: a dictionary representing an object :param response_dict_name: a dictionary which it's values are the relevant fields (filters) :return: the result_object filtered by the relevant fields """ af_params_dict = API_PARAM_DICT.get(response_dict_name) result_object_filtered = {} if af_params_dict and isinstance(result_object, dict) and isinstance(af_params_dict, dict): for key in result_object: if key in af_params_dict.values(): # type: ignore result_object_filtered[key] = result_object.get(key) return result_object_filtered def search_samples( client: Client, query=None, scope=None, size=None, sort=None, order=None, file_hash=None, domain=None, ip=None, url=None, wildfire_verdict=None, first_seen=None, last_updated=None, artifact_source=None, use_batches=False, ): validate_no_query_and_indicators(query, [file_hash, domain, ip, url, wildfire_verdict, first_seen, last_updated]) if not query: indicator_args_for_query = {"file_hash": file_hash, "domain": domain, "ip": ip, "url": url} used_indicator = validate_no_multiple_indicators_for_search(indicator_args_for_query) if use_batches: search_result = [] for _batch in batch(indicator_args_for_query[used_indicator], batch_size=100): query = build_sample_search_query(used_indicator, _batch, wildfire_verdict, first_seen, last_updated) search_result.append( run_search( client, "samples", query=query, scope=scope, size=size, sort=sort, order=order, artifact_source=artifact_source, ) ) return search_result indicators = indicator_args_for_query[used_indicator] query = build_sample_search_query(used_indicator, indicators, wildfire_verdict, first_seen, last_updated) return run_search( client, "samples", query=query, scope=scope, size=size, sort=sort, order=order, artifact_source=artifact_source ) def build_sample_search_query(used_indicator, indicators_values, wildfire_verdict, first_seen, last_updated): indicator_list = build_indicator_children_query(used_indicator, indicators_values) indicator_query = build_logic_query("OR", indicator_list) filtering_args_for_search = {} # type: ignore if wildfire_verdict: filtering_args_for_search["wildfire_verdict"] = demisto.get( API_PARAM_DICT, f"search_arguments.wildfire_verdict.translate.{wildfire_verdict}" ) if first_seen: filtering_args_for_search["first_seen"] = first_seen if last_updated: filtering_args_for_search["last_updated"] = last_updated filters_list = build_children_query(filtering_args_for_search) filters_list.append(indicator_query) logic_query = build_logic_query("AND", filters_list) return json.dumps(logic_query) def search_sessions( client: Client, query=None, size=None, sort=None, order=None, file_hash=None, domain=None, ip=None, url=None, from_time=None, to_time=None, use_batches=False, ): validate_no_query_and_indicators(query, [file_hash, domain, ip, url, from_time, to_time]) if not query: indicator_args_for_query = {"file_hash": file_hash, "domain": domain, "ip": ip, "url": url} used_indicator = validate_no_multiple_indicators_for_search(indicator_args_for_query) if use_batches: search_result = [] for _batch in batch(indicator_args_for_query[used_indicator], batch_size=100): query = build_session_search_query(used_indicator, _batch, from_time, to_time) search_result.append(run_search(client, "sessions", query=query, size=size, sort=sort, order=order)) return search_result indicators = indicator_args_for_query[used_indicator] query = build_session_search_query(used_indicator, indicators, from_time, to_time) return run_search(client, "sessions", query=query, size=size, sort=sort, order=order) def build_session_search_query(used_indicator, indicators_batch, from_time, to_time): indicator_list = build_indicator_children_query(used_indicator, indicators_batch) indicator_query = build_logic_query("OR", indicator_list) time_filters_for_search = {} # type: ignore if from_time and to_time: time_filters_for_search = {"time_range": [from_time, to_time]} elif from_time: time_filters_for_search = {"time_after": [from_time]} elif to_time: time_filters_for_search = {"time_before": [to_time]} filters_list = build_children_query(time_filters_for_search) filters_list.append(indicator_query) logic_query = build_logic_query("AND", filters_list) return json.dumps(logic_query) def build_logic_query(logic_operator, condition_list): return {"operator": {"AND": "all", "OR": "any"}.get(logic_operator), "children": condition_list} def build_children_query(args_for_query): children_list = [] # type: ignore for key, val in args_for_query.items(): field_api_name = API_PARAM_DICT["search_arguments"][key]["api_name"] # type: ignore operator = API_PARAM_DICT["search_arguments"][key]["operator"] # type: ignore children_list += children_list_generator(field_api_name, operator, [val]) return children_list def build_indicator_children_query(used_indicator, indicators_values): if indicators_values: field_api_name = API_PARAM_DICT["search_arguments"][used_indicator]["api_name"] # type: ignore operator = API_PARAM_DICT["search_arguments"][used_indicator]["operator"] # type: ignore children_list = children_list_generator(field_api_name, operator, indicators_values) else: children_list = [] demisto.debug(f"{indicators_values=} -> {children_list=}") return children_list def children_list_generator(field_name, operator, val_list): query_list = [] for value in val_list: query_list.append({"field": field_name, "operator": operator, "value": value}) return query_list def validate_no_query_and_indicators(query, arg_list): if query and any(arg_list): raise DemistoException( "The search command can either run a search using a custom query or use the builtin arguments, but not both" ) def validate_no_multiple_indicators_for_search(arg_dict): used_arg = None for arg, val in arg_dict.items(): if val and used_arg: raise DemistoException( f"The search command can receive one indicator type at a time, two were given: {used_arg}, {arg}." " For multiple indicator types use the custom query" ) elif val: used_arg = arg if not used_arg: raise DemistoException("In order to perform a samples/sessions search, a query or an indicator must be given.") return used_arg def search_indicator(client, indicator_type, indicator_value): headers = HEADERS | {"apiKey": API_KEY} params = { "indicatorType": indicator_type, "indicatorValue": indicator_value, "includeTags": "true", } demisto.debug(f"search_indicator: {indicator_value=}") result = Response() try: # 404, 409, 503 a list of status codes that we want to handle in the code and not raise automatic exception about. ok_codes = (200, 404, 409, 503) demisto.debug(f"search_indicator: using the client with {ok_codes=}") result = client.http_request(method="GET", url_suffix="/tic", headers=headers, params=params, ok_codes=ok_codes) demisto.debug(f"search_indicator: {result.status_code=} {result=}") try: result_json = result.json() except ValueError: result_json = {} demisto.debug(f"search_indicator {result_json=}") save_api_metrics(result_json) if result.status_code == 503: demisto.debug("search_indicator: result.status_code == 503") EXECUTION_METRICS.quota_error += 1 raise RateLimitExceededError(result_json) # Handle error responses gracefully result.raise_for_status() # Handle with connection error except requests.exceptions.ConnectionError as err: demisto.debug("search_indicator: in requests.exceptions.ConnectionError") EXECUTION_METRICS.connection_error += 1 raise DemistoException(f"Error connecting to server. Check your URL/Proxy/Certificate settings: {err}") # Unexpected errors (where no json object was received) except Exception as err: demisto.debug(f"search_indicator: Unexpected errors {err}") EXECUTION_METRICS.general_error += 1 try: if demisto.params().get("handle_error", True) and (result.status_code == 404 or result.status_code == 409): return { "indicator": { "indicatorType": indicator_type, "indicatorValue": indicator_value, "latestPanVerdicts": {"PAN_DB": "UNKNOWN"}, } } text_error = result.json() except ValueError: text_error = {} error_message = text_error.get("message") if error_message: raise DemistoException(f"Request Failed with status: {result.status_code}.\nReason is: {error_message}.") elif result.status_code in ERROR_DICT: raise DemistoException( f"Request Failed with status: {result.status_code}.\nReason is: {ERROR_DICT[result.status_code]}." ) else: err_msg = f"Request Failed with message: {err}." raise DemistoException(err_msg) EXECUTION_METRICS.success += 1 return result_json def parse_indicator_response(res, raw_tags, indicator_type): indicator = {} indicator["IndicatorValue"] = res.get("indicatorValue", "") indicator["IndicatorType"] = res.get("indicatorType", "") indicator["LatestPanVerdicts"] = res.get("latestPanVerdicts", "") indicator["WildfireRelatedSampleVerdictCounts"] = res.get("wildfireRelatedSampleVerdictCounts", "") indicator["SeenBy"] = res.get("seenByDataSourceIds", "") first_seen = res.get("firstSeenTsGlobal", "") last_seen = res.get("lastSeenTsGlobal", "") if first_seen: indicator["FirstSeen"] = timestamp_to_datestring(first_seen) if last_seen: indicator["LastSeen"] = timestamp_to_datestring(last_seen) if raw_tags: tags = [] for tag in raw_tags: tags.append( { "PublicTagName": tag.get("public_tag_name", ""), "TagName": tag.get("tag_name", ""), "CustomerName": tag.get("customer_name", ""), "Source": tag.get("source", ""), "TagDefinitionScopeID": tag.get("tag_definition_scope_id", ""), "TagDefinitionStatusID": tag.get("tag_definition_status_id", ""), "TagClassID": tag.get("tag_class_id", ""), "Count": tag.get("count", ""), "Lasthit": tag.get("lasthit", ""), "Description": tag.get("description", ""), } ) indicator["Tags"] = tags if indicator_type == "Domain": indicator["WhoisAdminCountry"] = res.get("whoisAdminCountry", "") indicator["WhoisAdminEmail"] = res.get("whoisAdminEmail", "") indicator["WhoisAdminName"] = res.get("whoisAdminName", "") indicator["WhoisDomainCreationDate"] = res.get("whoisDomainCreationDate", "") indicator["WhoisDomainExpireDate"] = res.get("whoisDomainExpireDate", "") indicator["WhoisDomainUpdateDate"] = res.get("whoisDomainUpdateDate", "") indicator["WhoisRegistrar"] = res.get("whoisRegistrar", "") indicator["WhoisRegistrarUrl"] = res.get("whoisRegistrarUrl", "") indicator["WhoisRegistrant"] = res.get("whoisRegistrant", "") return indicator def calculate_dbot_score(indicator_response, indicator_type): latest_pan_verdicts = indicator_response["latestPanVerdicts"] if not latest_pan_verdicts: raise Exception("latestPanVerdicts value is empty in indicator response.") pan_db = latest_pan_verdicts.get("PAN_DB") wf_sample = latest_pan_verdicts.get("WF_SAMPLE") # use WF_SAMPLE value for file indicator and PAN_DB for domain,url and ip indicators if indicator_type == "File" and wf_sample: return VERDICTS_TO_DBOTSCORE.get(wf_sample.lower(), 0) elif pan_db: return VERDICTS_TO_DBOTSCORE.get(pan_db.lower(), 0) else: score = next(iter(latest_pan_verdicts.values())) if score: return VERDICTS_TO_DBOTSCORE.get(score.lower(), 0) return 0 def check_for_ip(indicator): if "-" in indicator: # check for address range ip1, ip2 = indicator.split("-", 1) if re.match(ipv4Regex, ip1) and re.match(ipv4Regex, ip2): return FeedIndicatorType.IP elif re.match(ipv6Regex, ip1) and re.match(ipv6Regex, ip2): return FeedIndicatorType.IPv6 elif re.match(ipv4cidrRegex, ip1) and re.match(ipv4cidrRegex, ip2): return FeedIndicatorType.CIDR elif re.match(ipv6cidrRegex, ip1) and re.match(ipv6cidrRegex, ip2): return FeedIndicatorType.IPv6CIDR return None if "/" in indicator: if re.match(ipv4cidrRegex, indicator): return FeedIndicatorType.CIDR elif re.match(ipv6cidrRegex, indicator): return FeedIndicatorType.IPv6CIDR return None else: if re.match(ipv4Regex, indicator): return FeedIndicatorType.IP elif re.match(ipv6Regex, indicator): return FeedIndicatorType.IPv6 return None def find_indicator_type(indicator): """Infer the type of the indicator. Args: indicator(str): The indicator whose type we want to check. Returns: str. The type of the indicator. """ # trying to catch X.X.X.X:portNum if ":" in indicator and "/" not in indicator: sub_indicator = indicator.split(":", 1)[0] ip_type = check_for_ip(sub_indicator) if ip_type: return ip_type ip_type = check_for_ip(indicator) if ip_type: # catch URLs of type X.X.X.X/path/url or X.X.X.X:portNum/path/url if "/" in indicator and (ip_type not in [FeedIndicatorType.IPv6CIDR, FeedIndicatorType.CIDR]): return FeedIndicatorType.URL else: return ip_type elif re.match(sha256Regex, indicator): return FeedIndicatorType.File # in AutoFocus, URLs include a path while domains do not - so '/' is a good sign for us to catch URLs. elif "/" in indicator: return FeedIndicatorType.URL else: return FeedIndicatorType.Domain def resolve_ip_address(ip): if check_for_ip(ip): return socket.gethostbyaddr(ip)[0] return None def convert_url_to_ascii_character(url_name): def convert_non_ascii_chars(non_ascii): # converts non-ASCII chars to IDNA notation return str(non_ascii.group(0)).encode("idna").decode("utf-8") # Regex to catch all non ascii chars (from 0 to 127 in hexadecimal). return re.sub(r"[^\x00-\x7F]+", convert_non_ascii_chars, url_name) """ COMMANDS""" def test_module(client: Client): """ Performs basic get request to get item samples """ query = {"operator": "all", "children": [{"field": "sample.malware", "operator": "is", "value": 1}]} demisto.debug("test-module") do_search(client, "samples", query=query, scope="Public", err_operation="Test module failed") def search_samples_command(client: Client, args): file_hash = argToList(args.get("file_hash")) domain = argToList(args.get("domain")) ip = argToList(args.get("ip")) url = argToList(args.get("url")) wildfire_verdict = args.get("wildfire_verdict") first_seen = argToList(args.get("first_seen")) last_updated = argToList(args.get("last_updated")) query = args.get("query") scope = args.get("scope").capitalize() max_results = args.get("max_results") sort = args.get("sort") order = args.get("order") artifact_source = args.get("artifact") use_batches = args.get("use_batches") info = search_samples( client, query=query, scope=scope, size=max_results, sort=sort, order=order, file_hash=file_hash, domain=domain, ip=ip, url=url, wildfire_verdict=wildfire_verdict, first_seen=first_seen, last_updated=last_updated, artifact_source=artifact_source, use_batches=use_batches, ) md = tableToMarkdown("Search Samples Info:", info) return CommandResults( outputs=info, readable_output=md, outputs_key_field="AFCookie", outputs_prefix="AutoFocus.SamplesSearch" ) def search_samples_with_polling_command(client: Client, args): return run_polling_command(client, args, "autofocus-search-samples", search_samples_command, samples_search_results_command) def search_sessions_with_polling_command(client: Client, args): return run_polling_command( client, args, "autofocus-search-sessions", search_sessions_command, sessions_search_results_command ) def search_sessions_command(client: Client, args): file_hash = argToList(args.get("file_hash")) domain = argToList(args.get("domain")) ip = argToList(args.get("ip")) url = argToList(args.get("url")) from_time = args.get("time_after") to_time = args.get("time_before") time_range = args.get("time_range") query = args.get("query") max_results = args.get("max_results") sort = args.get("sort") order = args.get("order") use_batches = args.get("use_batches") if time_range: if from_time or to_time: raise DemistoException( "The 'time_range' argument cannot be specified with neither 'time_after' nor 'time_before' arguments." ) else: from_time, to_time = time_range.split(",") info = search_sessions( client, query=query, size=max_results, sort=sort, order=order, file_hash=file_hash, domain=domain, ip=ip, url=url, from_time=from_time, to_time=to_time, use_batches=use_batches, ) md = tableToMarkdown("Search Sessions Info:", info) cmd_results = CommandResults( outputs_prefix="AutoFocus.SessionsSearch", outputs_key_field="AFCookie", outputs=info, readable_output=md ) return cmd_results def samples_search_results_command(client: Client, args): af_cookie = args.get("af_cookie") results, status = get_search_results(client, "samples", af_cookie) files = get_files_data_from_results(results) hr = "" if not results or len(results) == 0: hr = "No entries found that match the query" if status == "complete" else f"Search Sessions Results is {status}" context = { "AutoFocus.SamplesResults(val.ID === obj.ID)": results, "AutoFocus.SamplesSearch(val.AFCookie === obj.AFCookie)": {"Status": status, "AFCookie": af_cookie}, outputPaths["file"]: files, } if not results: return_outputs(readable_output=hr, outputs=context, raw_response={}) else: # for each result a new entry will be set with two tables, one of the result and one of its artifacts for result in results: if "Artifact" in result: hr = samples_search_result_hr(result, status) return_outputs(readable_output=hr, outputs=context, raw_response=results) else: hr = tableToMarkdown(f"Search Samples Result is {status}", result) hr += tableToMarkdown("Artifacts for Sample: ", []) return_outputs(readable_output=hr, outputs=context, raw_response=results) return None, status def samples_search_result_hr(result: dict, status: str) -> str: """ Creates human readable output for a specific entry which contains two tables, one for the result's and another for the artifacts that are related to it. Args: result: one result of the search sample command. status: status of result command. Returns: human readable of two tables for this result. """ artifact = result.pop("Artifact") updated_artifact = [] for indicator in artifact: # Filter on returned indicator types, as we do not support Mutex and User Agent. if "Mutex" not in indicator.get("indicator_type") and "User Agent" not in indicator.get("indicator_type"): updated_artifact.append(indicator) hr = "\n\n".join( ( tableToMarkdown(f"Search Samples Result is {status}", result), tableToMarkdown( "Artifacts for Sample: ", updated_artifact, headers=["b", "g", "m", "indicator_type", "confidence", "indicator"] ), ) ) return hr def sessions_search_results_command(client: Client, args): af_cookie = args.get("af_cookie") results, status = get_search_results(client, "sessions", af_cookie) files = get_files_data_from_results(results) if not results or len(results) == 0: md = results = "No entries found that match the query" else: md = tableToMarkdown(f"Search Samples Results is {status}", results) context = { "AutoFocus.SessionsResults(val.ID === obj.ID)": results, "AutoFocus.SessionsSearch(val.AFCookie === obj.AFCookie)": {"Status": status, "AFCookie": af_cookie}, outputPaths["file"]: files, } return CommandResults(outputs=context, raw_response=results, readable_output=md), status def get_session_details_command(client: Client): args = demisto.args() session_id = args.get("session_id") result = get_session_details(client, session_id) files = get_files_data_from_results(result) md = tableToMarkdown(f"Session {session_id}:", result) context = {"AutoFocus.Sessions(val.ID === obj.ID)": result, outputPaths["file"]: files} demisto.results( { "Type": entryTypes["note"], "ContentsFormat": formats["text"], "Contents": result, "EntryContext": context, "HumanReadable": md, } ) def sample_analysis_command(client: Client): args = demisto.args() sample_id = args.get("sample_id") os = args.get("os") filter_data = args.get("filter_data") != "False" analysis = sample_analysis(client, sample_id, os, filter_data) context = createContext(analysis, keyTransform=string_to_context_key) demisto.results( { "Type": entryTypes["note"], "ContentsFormat": formats["text"], "Contents": {"ID": sample_id, "Analysis": analysis}, "HumanReadable": f"### Sample Analysis results for {sample_id}:", "EntryContext": {"AutoFocus.SampleAnalysis(val.ID == obj.ID)": {"ID": sample_id, "Analysis": context}}, } ) for category_name, category_data in analysis.items(): print_hr_by_category(category_name, category_data) def tag_details_command(client: Client): args = demisto.args() tag_name = args.get("tag_name") result = autofocus_tag_details(client, tag_name) md = tableToMarkdown(f"Tag {tag_name} details:", result, headerTransform=string_to_table_header) context = createContext(result, keyTransform=string_to_context_key) demisto.results( { "Type": entryTypes["note"], "ContentsFormat": formats["text"], "Contents": result, "EntryContext": {"AutoFocus.Tag(val.ID == obj.ID)": context}, "HumanReadable": md, } ) def top_tags_search_command(client: Client, args): scope = args.get("scope") tag_class = args.get("class") private = args.get("private") == "True" public = args.get("public") == "True" commodity = args.get("commodity") == "True" unit42 = args.get("unit42") == "True" info = autofocus_top_tags_search(client, scope, tag_class, private, public, commodity, unit42) md = tableToMarkdown("Top tags search Info:", info) return CommandResults( outputs_prefix="AutoFocus.TopTagsSearch", outputs_key_field="AFCookie", outputs=info, readable_output=md ) def top_tags_results_command(client: Client, args) -> tuple[CommandResults, str]: af_cookie = args.get("af_cookie") results, status = get_top_tags_results(client, af_cookie) md = tableToMarkdown(f"Search Top Tags Results is {status}:", results, headerTransform=string_to_table_header) context = createContext(results, keyTransform=string_to_context_key) outputs = { "AutoFocus.TopTagsResults(val.PublicTagName === obj.PublicTagName)": context, "AutoFocus.TopTagsSearch(val.AFCookie === obj.AFCookie)": {"Status": status, "AFCookie": af_cookie}, } return CommandResults(outputs=outputs, raw_response=results, readable_output=md), status def top_tags_with_polling_command(client: Client, args): return run_polling_command(client, args, "autofocus-top-tags-search", top_tags_search_command, top_tags_results_command) def search_ip_command(client, ip, reliability, create_relationships): indicator_type = "IP" ip_list = argToList(ip) command_results = [] relationships = [] for ip_address in ip_list: ip_type = "ipv6_address" if is_ipv6_valid(ip_address) else "ipv4_address" raw_res = search_indicator(client, ip_type, ip_address) indicator = raw_res.get("indicator") if indicator: raw_tags = raw_res.get("tags") score = calculate_dbot_score(indicator, indicator_type) dbot_score = Common.DBotScore( indicator=ip_address, indicator_type=DBotScoreType.IP, integration_name=VENDOR_NAME, score=score, reliability=reliability, ) if create_relationships: relationships = create_relationships_list( entity_a=ip_address, entity_a_type=indicator_type, tags=raw_tags, reliability=reliability ) ip = Common.IP( ip=ip_address, dbot_score=dbot_score, malware_family=get_tags_for_tags_and_malware_family_fields(raw_tags, True), tags=get_tags_for_tags_and_malware_family_fields(raw_tags), relationships=relationships, ) autofocus_ip_output = parse_indicator_response(indicator, raw_tags, indicator_type) # create human readable markdown for ip tags = autofocus_ip_output.get("Tags") table_name = f"{VENDOR_NAME} {indicator_type} reputation for: {ip_address}" if tags: indicators_data = autofocus_ip_output.copy() del indicators_data["Tags"] md = tableToMarkdown(table_name, indicators_data) md += tableToMarkdown("Indicator Tags:", tags) else: md = tableToMarkdown(table_name, autofocus_ip_output) else: dbot_score = Common.DBotScore( indicator=ip_address, indicator_type=DBotScoreType.IP, integration_name=VENDOR_NAME, score=0, reliability=reliability, ) ip = Common.IP( ip=ip_address, dbot_score=dbot_score, ) md = f"### The IP indicator: {ip_address} was not found in AutoFocus" autofocus_ip_output = {"IndicatorValue": ip_address} command_results.append( CommandResults( outputs_prefix="AutoFocus.IP", outputs_key_field="IndicatorValue", outputs=autofocus_ip_output, readable_output=md, raw_response=raw_res, indicator=ip, relationships=relationships, ) ) return command_results def search_domain_command(client, domain, reliability, create_relationships): indicator_type = "Domain" domain_name_list = argToList(domain) command_results = [] relationships = [] for domain_name in domain_name_list: raw_res = search_indicator(client, "domain", domain_name) indicator = raw_res.get("indicator") if indicator: raw_tags = raw_res.get("tags") score = calculate_dbot_score(indicator, indicator_type) dbot_score = Common.DBotScore( indicator=domain_name, indicator_type=DBotScoreType.DOMAIN, integration_name=VENDOR_NAME, score=score, reliability=reliability, ) if create_relationships: relationships = create_relationships_list( entity_a=domain_name, entity_a_type=indicator_type, tags=raw_tags, reliability=reliability ) domain = Common.Domain( domain=domain_name, dbot_score=dbot_score, # Converting date format from YYYY-MM-DD to DD-MM-YYYY due to a parsing problem on the server later creation_date="-".join((indicator.get("whoisDomainCreationDate") or "").split("-")[::-1]), expiration_date="-".join((indicator.get("whoisDomainExpireDate") or "").split("-")[::-1]), updated_date="-".join((indicator.get("whoisDomainUpdateDate") or "").split("-")[::-1]), admin_email=indicator.get("whoisAdminEmail"), admin_name=indicator.get("whoisAdminName"), admin_country=indicator.get("whoisAdminCountry"), registrar_name=indicator.get("whoisRegistrar"), registrant_name=indicator.get("whoisRegistrant"), malware_family=get_tags_for_tags_and_malware_family_fields(raw_tags, True), tags=get_tags_for_tags_and_malware_family_fields(raw_tags), relationships=relationships, ) autofocus_domain_output = parse_indicator_response(indicator, raw_tags, indicator_type) # create human readable markdown for ip tags = autofocus_domain_output.get("Tags") table_name = f"{VENDOR_NAME} {indicator_type} reputation for: {domain_name}" if tags: indicators_data = autofocus_domain_output.copy() del indicators_data["Tags"] md = tableToMarkdown(table_name, indicators_data) md += tableToMarkdown("Indicator Tags:", tags) else: md = tableToMarkdown(table_name, autofocus_domain_output) else: dbot_score = Common.DBotScore( indicator=domain_name, indicator_type=DBotScoreType.DOMAIN, integration_name=VENDOR_NAME, score=0, reliability=reliability, ) domain = Common.Domain(domain=domain_name, dbot_score=dbot_score) md = f"### The Domain indicator: {domain_name} was not found in AutoFocus" autofocus_domain_output = {"IndicatorValue": domain_name} command_results.append( CommandResults( outputs_prefix="AutoFocus.Domain", outputs_key_field="IndicatorValue", outputs=autofocus_domain_output, readable_output=md, raw_response=raw_res, indicator=domain, relationships=relationships, ) ) return command_results def search_url_command(client, url, reliability, create_relationships, separator=","): indicator_type = "URL" url_list = argToList(url, separator) command_results = [] relationships = [] for url_name in url_list: raw_res = search_indicator(client, "url", convert_url_to_ascii_character(url_name)) indicator = raw_res.get("indicator") if indicator: indicator["indicatorValue"] = url_name raw_tags = raw_res.get("tags") score = calculate_dbot_score(indicator, indicator_type) dbot_score = Common.DBotScore( indicator=url_name, indicator_type=DBotScoreType.URL, integration_name=VENDOR_NAME, score=score, reliability=reliability, ) if create_relationships: relationships = create_relationships_list( entity_a=url_name, entity_a_type=indicator_type, tags=raw_tags, reliability=reliability ) url = Common.URL( url=url_name, dbot_score=dbot_score, malware_family=get_tags_for_tags_and_malware_family_fields(raw_tags, True), tags=get_tags_for_tags_and_malware_family_fields(raw_tags), relationships=relationships, ) autofocus_url_output = parse_indicator_response(indicator, raw_tags, indicator_type) autofocus_url_output = {k: v for k, v in autofocus_url_output.items() if v} tags = autofocus_url_output.get("Tags") table_name = f"{VENDOR_NAME} {indicator_type} reputation for: {url_name}" if tags: indicators_data = autofocus_url_output.copy() del indicators_data["Tags"] md = tableToMarkdown(table_name, indicators_data) md += tableToMarkdown("Indicator Tags:", tags) else: md = tableToMarkdown(table_name, autofocus_url_output) else: dbot_score = Common.DBotScore( indicator=url_name, indicator_type=DBotScoreType.URL, integration_name=VENDOR_NAME, score=0, reliability=reliability, ) url = Common.URL(url=url_name, dbot_score=dbot_score) md = f"### The URL indicator: {url_name} was not found in AutoFocus" autofocus_url_output = {"IndicatorValue": url_name} command_results.append( CommandResults( outputs_prefix="AutoFocus.URL", outputs_key_field="IndicatorValue", outputs=autofocus_url_output, readable_output=md, raw_response=raw_res, indicator=url, relationships=relationships, ) ) return command_results def search_file_command(client, file, reliability, create_relationships): indicator_type = "File" file_list = argToList(file) command_results = [] relationships = [] for file_hash in file_list: raw_res = search_indicator(client, "filehash", file_hash.lower()) indicator = raw_res.get("indicator") if indicator: raw_tags = raw_res.get("tags") score = calculate_dbot_score(indicator, indicator_type) dbot_score = Common.DBotScore( indicator=file_hash, indicator_type=DBotScoreType.FILE, integration_name=VENDOR_NAME, score=score, reliability=reliability, ) if create_relationships: relationships = create_relationships_list( entity_a=file_hash, entity_a_type=indicator_type, tags=raw_tags, reliability=reliability ) autofocus_file_output = parse_indicator_response(indicator, raw_tags, indicator_type) tags = autofocus_file_output.get("Tags") table_name = f"{VENDOR_NAME} {indicator_type} reputation for: {file_hash}" if tags: indicators_data = autofocus_file_output.copy() del indicators_data["Tags"] md = tableToMarkdown(table_name, indicators_data) md += tableToMarkdown("Indicator Tags:", tags) else: md = tableToMarkdown(table_name, autofocus_file_output) hash_type = get_hash_type(file_hash) file = Common.File( md5=file_hash if hash_type == "md5" else None, sha1=file_hash if hash_type == "sha1" else None, sha256=file_hash if hash_type == "sha256" else None, dbot_score=dbot_score, malware_family=get_tags_for_tags_and_malware_family_fields(raw_tags, True), tags=get_tags_for_tags_and_malware_family_fields(raw_tags), relationships=relationships, ) else: dbot_score = Common.DBotScore( indicator=file_hash, indicator_type=DBotScoreType.FILE, integration_name=VENDOR_NAME, score=0, reliability=reliability, ) hash_type = get_hash_type(file_hash) hash_val_arg = {hash_type: file_hash} file = Common.File(dbot_score=dbot_score, **hash_val_arg) md = f"### The File indicator: {file_hash} was not found in AutoFocus" autofocus_file_output = {"IndicatorValue": file_hash} command_results.append( CommandResults( outputs_prefix="AutoFocus.File", outputs_key_field="IndicatorValue", outputs=autofocus_file_output, readable_output=md, raw_response=raw_res, indicator=file, relationships=relationships, ) ) return command_results def get_tags_for_generic_context(tags: Optional[list]): if not tags: return None results = [] keys = ["TagGroups", "Aliases", "PublicTagName", "TagName"] sub_keys = ["TagGroupName"] for item in tags: generic_context_tags = {key: item.get(key) for key in keys} generic_context_tags["tagGroups"] = {key: item.get(key) for key in sub_keys} results.append(remove_empty_elements(generic_context_tags)) return results def get_tags_for_tags_and_malware_family_fields(tags: Optional[list], is_malware_family=False): """get specific tags for the tags and malware_family fields Args tags (Optional[list]): tags from the response is_malware_family (bool): indicating whether it is for the malware_family field return: List[str]: list of tags without duplicates and empty elements """ if not tags: return None results = [] for item in tags: results.append(item.get("tag_name")) results.append(item.get("public_tag_name")) for alias in item.get("aliases", []): results.append(alias) if not is_malware_family: for group in item.get("tagGroups", [{}]): results.append(group.get("tag_group_name")) # Returns a list without duplicates and empty elements return list(set(filter(None, results))) def create_relationships_list(entity_a, entity_a_type, tags, reliability): """ Create a list of relationships objects from the tags. entity_a (str): the entity a of the relation which is the current indicator. entity_a_type (str): the entity a type which is the type of the current indicator (IP/Domain/URL/File) tags (list): list of tags returned from the api. reliability (str): reliability of the source. return: list of EntityRelationship objects containing all the relationships from the enricher. """ if not tags: return [] relationships = [] for tag in tags: tag_class = tag.get("tag_class_id") entity_b = tag.get("tag_name") relation_by_type = RELATIONSHIP_TYPE_BY_TAG_CLASS_ID.get(tag_class) if entity_b and relation_by_type: relationships.append( EntityRelationship( relation_by_type.get("name"), entity_a=entity_a, entity_a_type=entity_a_type, entity_b=entity_b, entity_b_type=FeedIndicatorType.indicator_type_by_server_version(relation_by_type.get("entity_b_type")), source_reliability=reliability, brand=VENDOR_NAME, ) ) return relationships def get_export_list_command(client: Client, args): # the label is the name of the export list we want to fetch. # panosFormatted is a flag stating that only indicators should be returned in the list. data = {"label": args.get("label"), "panosFormatted": True, "apiKey": ""} results = client.http_request( url_suffix="/export", method="POST", data=data, err_operation=f"Failed to fetch export list: {args.get('label')}" ) indicators = [] context_ip = [] context_url = [] context_domain = [] context_file = [] for indicator_value in results.get("export_list"): indicator_type = find_indicator_type(indicator_value) if indicator_type in [FeedIndicatorType.IP, FeedIndicatorType.IPv6, FeedIndicatorType.IPv6CIDR, FeedIndicatorType.CIDR]: if "-" in indicator_value: context_ip.append({"Address": indicator_value.split("-")[0]}) context_ip.append({"Address": indicator_value.split("-")[1]}) elif ":" in indicator_value: context_ip.append({"Address": indicator_value.split(":", 1)[0]}) else: context_ip.append({"Address": indicator_value}) elif indicator_type == FeedIndicatorType.Domain: context_domain.append({"Name": indicator_value}) elif indicator_type == FeedIndicatorType.File: context_file.append({"SHA256": indicator_value}) elif indicator_type == FeedIndicatorType.URL: if ":" in indicator_value: resolved_address = resolve_ip_address(indicator_value.split(":", 1)[0]) semicolon_suffix = indicator_value.split(":", 1)[1] slash_suffix = None else: resolved_address = resolve_ip_address(indicator_value.split("/", 1)[0]) slash_suffix = indicator_value.split("/", 1)[1] semicolon_suffix = None if resolved_address: if semicolon_suffix: indicator_value = resolved_address + ":" + semicolon_suffix else: indicator_value = resolved_address + "/" + slash_suffix context_url.append( { "Data": indicator_value, } ) indicators.append( { "Type": indicator_type, "Value": indicator_value, } ) hr = tableToMarkdown(f"Export list {args.get('label')}", indicators, headers=["Type", "Value"]) return_outputs( hr, { "AutoFocus.Indicator(val.Value == obj.Value && val.Type == obj.Type)": indicators, "IP(obj.Address == val.Address)": context_ip, "URL(obj.Data == val.Data)": context_url, "File(obj.SHA256 == val.SHA256)": context_file, "Domain(obj.Name == val.Name)": context_domain, }, results, ) def main(): if is_demisto_version_ge("8.12.0") and datetime.now() > datetime(2025, 12, 1): return_error("Palo Alto Networks AutoFocus v2 integration is deprecated. Please use Unit 42 Intelligence integration instead.") else: return_warning("AutoFocus v2 is deprecated and will stop working after December 1, 2025. Please migrate to Unit 42 Intelligence integration.") command = demisto.command() demisto.debug(f"Command being called is {command}") reliability = PARAMS.get("integrationReliability", "B - Usually reliable") create_relationships = PARAMS.get("create_relationships", True) proxy = PARAMS.get("proxy", False) USE_SSL = not PARAMS.get("insecure", False) # Should we use SSL if DBotScoreReliability.is_valid_type(reliability): reliability = DBotScoreReliability.get_dbot_score_reliability_from_str(reliability) else: raise Exception("AutoFocus error: Please provide a valid value for the Source Reliability parameter") client = Client(url=BASE_URL, verify=USE_SSL, proxy=proxy) args = demisto.args() | { "reliability": reliability, "create_relationships": create_relationships, } try: if command == "test-module": # This is the call made when pressing the integration test button. test_module(client) demisto.results("ok") elif command == "autofocus-search-samples": if args.get("polling") == "true": cmd_res = search_samples_with_polling_command(client, args) if cmd_res is not None: return_results(cmd_res) else: args["use_batches"] = True return_results(search_samples_command(client, args)) elif command == "autofocus-search-sessions": if args.get("polling") == "true": return_results(search_sessions_with_polling_command(client, args)) else: args["use_batches"] = True return_results(search_sessions_command(client, args)) elif command == "autofocus-samples-search-results": samples_search_results_command(client, args) elif command == "autofocus-sessions-search-results": return_results(sessions_search_results_command(client, args)[0]) # first result is CommandResults elif command == "autofocus-get-session-details": get_session_details_command(client) elif command == "autofocus-sample-analysis": sample_analysis_command(client) elif command == "autofocus-tag-details": tag_details_command(client) elif command == "autofocus-top-tags-search": if args.get("polling") == "true": return_results(top_tags_with_polling_command(client, args)) else: return_results(top_tags_search_command(client, args)) elif command == "autofocus-top-tags-results": return_results(top_tags_results_command(client, args)[0]) elif command == "autofocus-get-export-list-indicators": get_export_list_command(client, args) elif command == "ip": return_results(search_ip_command(client, **args)) elif command == "domain": return_results(search_domain_command(client, **args)) elif command == "url": return_results(search_url_command(client, **args)) elif command == "file": return_results(search_file_command(client, **args)) else: raise NotImplementedError(f"Command {command!r} is not implemented.") except RateLimitExceededError as e: rerun_command_if_required(e.api_res, argToBoolean(args.get("retry_on_rate_limit", False))) except Exception as e: return_error(f"Unexpected error: {e}.\ntraceback: {traceback.format_exc()}") finally: return_metrics() if __name__ in ["__main__", "builtin", "builtins"]: main()