Proofpoint TAP v2
Use the Proofpoint Targeted Attack Protection (TAP) integration to protect against and provide additional visibility into phishing and other malicious email attacks.
Email · Proofpoint TAP
Details
| ID | Proofpoint TAP v2 |
|---|---|
| Provider | Thoma Bravo |
| Category | |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
Proofpoint TAP
Use the Proofpoint Targeted Attack Protection (TAP) integration to protect against and provide additional visibility into phishing and other malicious email attacks.
This integration was integrated and tested with version v2 of Proofpoint TAP v2
Events Fetch Look-Back
Proofpoint’s SIEM API does not always index events the moment they occur. Indexing can lag by up to ~30 minutes, so an event that already happened may not yet be returned when the integration queries for it in real time. Without a safety mechanism, these late-indexed events can be permanently missed.
The Events Fetch Look-Back (minutes) parameter solves this by overlapping fetch cycles:
- Why it’s needed: Compensates for the SIEM API indexing delay so events that are indexed after their occurrence time are still collected.
- How it works: On every fetch cycle the integration requeries the previous N minutes. Built-in deduplication ensures events already fetched are not ingested again, so no duplicates are created.
- Recommended usage: A value of 30 minutes generally covers the typical indexing delay. Set it to 0 to disable look-back entirely.
- Existing instances: For instances that were already configured before version 1.3.0, the look-back window is rolled out gradually rather than all at once. This prevents duplicate events from being created when look-back is first applied against historical data that was already fetched. No action is required on your part — the behavior is automatic and safe.
Configure Proofpoint TAP v2 in Cortex
| Parameter | Description | Required |
|---|---|---|
| Server URL | e.g., https://tap-api-v2.proofpoint.com | True |
| Service Principal | The password refers to secret | True |
| API Version | v1 is deprecated for new instances. The current API version is v2. | False |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False | |
| Threat type | A string specifying which threat type to return. If empty, all threat types are returned. Can be “url”, “attachment”, or “messageText”. | False |
| Threat status | A string specifying which threat statuses to return. If empty, will return “active” and “cleared” threats. Can be “active”, “cleared”, or “falsePositive”. | False |
| Events to fetch | False | |
| Maximum number of incident per fetch | False | |
| First fetch time range | First fetch time range (<number> <time unit>, e.g., 1 hour, 30 minutes). Proofpoint supports a maximum 1 week fetch back. | False |
| Advanced: Raw message encoding | The character encoding to apply on the message fetched (e.g. latin-1). Advanced configuration to be used only if instructed by XSOAR Support | False |
| Events Fetch Look-Back (minutes) | The number of minutes to look back during each fetch to handle the Proofpoint SIEM API indexing delay (up to 30 minutes). When set, each fetch cycle requeries the previous N minutes to catch late-indexing events that would otherwise be missed. Duplicates are filtered automatically. Set to 0 to disable. | False |
| Fetch incidents | False | |
| Incident type | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
proofpoint-get-events
Fetches events for all clicks and messages relating to known threats within the specified time period. Details as per clicks/blocked.
Base Command
proofpoint-get-events
Input
| Argument Name | Description | Required |
|---|---|---|
| interval | A string containing an ISO8601-formatted interval. If this interval overlaps with previous requests for data, records from the previous request might be duplicated. The minimum interval is thirty seconds. The maximum interval is one hour. Examples: 2016-05-01T12:00:00Z/2016-05-01T13:00:00Z - an hour interval, beginning at noon UTC on 05-01-2016 PT30M/2016-05-01T12:30:00Z - the thirty minutes beginning at noon UTC on 05-01-2016 and ending at 12:30pm * UTC 2016-05-01T05:00:00-0700/PT30M - the same interval as above, but using -0700 as the time zone. | Optional |
| threatType | A comma-separated list of the threat types to return. If empty, all threat types are returned. The following values are accepted: “url”, “attachment”, and “messageText”. Possible values are: url, attachment, messageText. | Optional |
| threatStatus | A string specifying which threat statuses to return. If empty, active and cleared threats are returned. Can be “active”, “cleared”, “falsePositive”. Possible values are: active, cleared, falsePositive. | Optional |
| sinceTime | A string containing an ISO8601 date. It represents the start of the data retrieval period. The end of the period is determined by the current API server time rounded to the nearest minute. If JSON output is selected, the end time is included in the returned result. Example: 2016-05-01T12:00:00Z. | Optional |
| sinceSeconds | An integer representing a time window (in seconds) from the current API server time. The start of the window is the current API server time, rounded to the nearest minute, less the number of seconds provided. The end of the window is the current API server time rounded to the nearest minute. If JSON output is selected, the end time is included in the returned result. | Optional |
| eventTypes | Event types to return. Possible values: “All”, “Issues”, “Delivered Messages”, “Blocked Messages”, “Permitted Clicks”, and “Blocked Clicks”. Possible values are: All, Issues, Delivered Messages, Blocked Messages, Permitted Clicks, Blocked Clicks. Default is All. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.MessagesDelivered.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS, which is unique. |
| Proofpoint.MessagesDelivered.QID | String | The queue ID of the message within PPS. It can be used to identify the message in PPS, which is not unique. |
| Proofpoint.MessagesDelivered.ccAddresses | String | A list of email addresses contained within the CC: header, excluding any friendly names. |
| Proofpoint.MessagesDelivered.clusterId | String | The name of the PPS cluster which processed the message. |
| Proofpoint.MessagesDelivered.fromAddress | String | The email address contained in the From: header, excluding any friendly name. |
| Proofpoint.MessagesDelivered.headerCC | String | The CC header. |
| Proofpoint.MessagesDelivered.headerFrom | String | The full content of the From: header, including any friendly name. |
| Proofpoint.MessagesDelivered.headerReplyTo | String | If present, the full content of the Reply-To: header, including any friendly names. |
| Proofpoint.MessagesDelivered.impostorScore | Number | The impostor score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.malwareScore | Number | The malware score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.messageId | String | Message-ID extracted from the headers of the email message. It can be used to look up the associated message in PPS, which is not unique. |
| Proofpoint.MessagesDelivered.threatsInfoMap.threat | String | The artifact which was condemned by Proofpoint. The malicious URL, hash of the attachment threat, or email address of the impostor sender. |
| Proofpoint.MessagesDelivered.threatsInfoMap.threatId | String | The unique identifier associated with this threat. It can be used to query the forensics and campaign endpoints. |
| Proofpoint.MessagesDelivered.threatsInfoMap.threatStatus | String | The current state of the threat (active, expired, false-positive, cleared). |
| Proofpoint.MessagesDelivered.threatsInfoMap.threatTime | Date | The time Proofpoint assigned the threatStatus (ISO8601 format). |
| Proofpoint.MessagesDelivered.threatsInfoMap.threatType | String | Whether the threat was an attachment, URL, or message type. |
| Proofpoint.MessagesDelivered.threatsInfoMap.threatUrl | String | A link to the entry about the threat on the TAP Dashboard. |
| Proofpoint.MessagesDelivered.messageTime | Date | The time the message was delivered to the user or quarantined by PPS. |
| Proofpoint.MessagesDelivered.modulesRun | String | The list of PPS modules that processed the message. |
| Proofpoint.MessagesDelivered.phishScore | Number | The phishing score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.policyRoutes | String | The policy routes that the message matched during processing by PPS. |
| Proofpoint.MessagesDelivered.quarantineFolder | String | The name of the folder that contains the quarantined message. This appears only for messagesBlocked. |
| Proofpoint.MessagesDelivered.quarantineRule | String | The name of the rule that quarantined the message. This appears only for messagesBlocked events. |
| Proofpoint.MessagesDelivered.recipient | String | A list containing the email addresses of the recipients. |
| Proofpoint.MessagesDelivered.replyToAddress | String | The email address contained in the Reply-To: header, excluding any friendly name. |
| Proofpoint.MessagesDelivered.sender | String | The email address of the SMTP (envelope) sender. The user-part is hashed. The domain-part is cleartext. |
| Proofpoint.MessagesDelivered.senderIP | String | The IP address of the sender. |
| Proofpoint.MessagesDelivered.spamScore | Number | The spam score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.subject | String | The subject line of the message, if available. |
| Proofpoint.MessagesBlocked.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS, which is unique. |
| Proofpoint.MessagesBlocked.QID | String | The queue ID of the message within PPS. It can be used to identify the message in PPS, which is not unique. |
| Proofpoint.MessagesBlocked.ccAddresses | String | A list of email addresses contained within the CC: header, excluding any friendly names. |
| Proofpoint.MessagesBlocked.clusterId | String | The name of the PPS cluster that processed the message. |
| Proofpoint.MessagesBlocked.fromAddress | String | The email address contained in the From: header, excluding any friendly name. |
| Proofpoint.MessagesBlocked.headerCC | String | The CC header. |
| Proofpoint.MessagesBlocked.headerFrom | String | The full content of the From: header, including any friendly name. |
| Proofpoint.MessagesBlocked.headerReplyTo | String | If present, the full content of the Reply-To: header, including any friendly names. |
| Proofpoint.MessagesBlocked.impostorScore | Number | The impostor score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesBlocked.malwareScore | Number | The malware score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesBlocked.messageId | String | Message-ID extracted from the headers of the email message. It can be used to look up the associated message in PPS, which is not unique. |
| Proofpoint.MessagesBlocked.threatsInfoMap.threat | String | The artifact which was condemned by Proofpoint. The malicious URL, hash of the attachment threat, or email address of the impostor sender. |
| Proofpoint.MessagesBlocked.threatsInfoMap.threatId | String | The unique identifier associated with this threat. It can be used to query the forensics and campaign endpoints. |
| Proofpoint.MessagesBlocked.threatsInfoMap.threatStatus | String | The current state of the threat (active, expired, false-positive, cleared). |
| Proofpoint.MessagesBlocked.threatsInfoMap.threatTime | Date | The time Proofpoint assigned the threatStatus (ISO8601 format). |
| Proofpoint.MessagesBlocked.threatsInfoMap.threatType | String | Whether the threat was an attachment, URL, or message type. |
| Proofpoint.MessagesBlocked.threatsInfoMap.threatUrl | String | A link to the entry about the threat on the TAP dashboard. |
| Proofpoint.MessagesBlocked.messageTime | Date | The time the message was blocked to the user or quarantined by PPS. |
| Proofpoint.MessagesBlocked.messageTime | String | The list of PPS modules that processed the message. |
| Proofpoint.MessagesBlocked.modulesRun | String | The list of PPS modules that processed the message. |
| Proofpoint.MessagesBlocked.phishScore | Number | The phishing score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesBlocked.policyRoutes | String | The policy routes that the message matched during processing by PPS. |
| Proofpoint.MessagesBlocked.quarantineFolder | String | The name of the folder that contains the quarantined message. This appears only for messagesBlocked. |
| Proofpoint.MessagesBlocked.quarantineRule | String | The name of the rule that quarantined the message. This appears only for messagesBlocked events. |
| Proofpoint.MessagesBlocked.recipient | String | A list containing the email addresses of the recipients. |
| Proofpoint.MessagesBlocked.replyToAddress | String | The email address contained in the Reply-To: header, excluding any friendly name. |
| Proofpoint.MessagesBlocked.sender | String | The email address of the SMTP (envelope) sender. The user-part is hashed. The domain-part is cleartext. |
| Proofpoint.MessagesBlocked.senderIP | String | The IP address of the sender. |
| Proofpoint.MessagesBlocked.spamScore | Number | The spam score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesBlocked.subject | String | The subject line of the message, if available. |
| Proofpoint.ClicksPermitted.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS, which is unique. |
| Proofpoint.ClicksPermitted.campaignId | String | An identifier for the campaign of which the threat is a member, if available at the time of the query. Threats can be linked to campaigns even after these events are retrieved. |
| Proofpoint.ClicksPermitted.classification | String | The threat category of the malicious URL. |
| Proofpoint.ClicksPermitted.clickIP | String | The external IP address of the user who clicked the link. If the user is behind a firewall performing network address translation, the IP address of the firewall will be shown. |
| Proofpoint.ClicksPermitted.clickTime | Date | The time the user clicked the URL. |
| Proofpoint.ClicksPermitted.messageID | String | The Message-ID extracted from the headers of the email message. It can be used to look up the associated message in PPS and is not unique. |
| Proofpoint.ClicksPermitted.recipient | String | The email address of the recipient. |
| Proofpoint.ClicksPermitted.sender | String | The email address of the sender. The user-part is hashed. The domain-part is cleartext. |
| Proofpoint.ClicksPermitted.senderIP | String | The IP address of the sender. |
| Proofpoint.ClicksPermitted.threatID | String | The unique identifier associated with this threat. It can be used to query the forensics and campaign endpoints. |
| Proofpoint.ClicksPermitted.threatTime | Date | The time Proofpoint identified the URL as a threat. |
| Proofpoint.ClicksPermitted.threatURL | String | A link to the entry on the TAP Dashboard for the particular threat. |
| Proofpoint.ClicksPermitted.url | String | The malicious URL which was clicked. |
| Proofpoint.ClicksPermitted.userAgent | String | The User-Agent header from the clicker’s HTTP request. |
| Proofpoint.ClicksBlocked.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS and is guaranteed to be unique. |
| Proofpoint.ClicksBlocked.campaignId | String | An identifier for the campaign of which the threat is a member, if available at the time of the query. Threats can be linked to campaigns even after these events are retrieved. |
| Proofpoint.ClicksBlocked.classification | String | The threat category of the malicious URL. |
| Proofpoint.ClicksBlocked.clickIP | String | The external IP address of the user who clicked the link. If the user is behind a firewall performing network address translation, the IP address of the firewall will be shown. |
| Proofpoint.ClicksBlocked.clickTime | Date | The time the user clicked the URL. |
| Proofpoint.ClicksBlocked.messageID | String | Message-ID extracted from the headers of the email message. It can be used to look up the associated message in PPS and is not unique. |
| Proofpoint.ClicksBlocked.recipient | String | The email address of the recipient. |
| Proofpoint.ClicksBlocked.sender | String | The email address of the sender. The user-part is hashed. The domain-part is cleartext. |
| Proofpoint.ClicksBlocked.senderIP | String | The IP address of the sender. |
| Proofpoint.ClicksBlocked.threatID | String | The unique identifier associated with this threat. It can be used to query the forensics and campaign endpoints. |
| Proofpoint.ClicksBlocked.threatTime | Date | The time Proofpoint identified the URL as a threat. |
| Proofpoint.ClicksBlocked.threatURL | String | A link to the entry on the TAP dashboard for the particular threat. |
| Proofpoint.ClicksBlocked.url | String | The malicious URL that was clicked. |
| Proofpoint.ClicksBlocked.userAgent | String | The User-Agent header from the clicker’s HTTP request. |
Command Example
!proofpoint-get-events interval="2021-06-07T02:00:00Z/2021-06-07T03:00:00Z"
Context Example
{
"Proofpoint": {
"ClicksBlocked": null,
"ClicksPermitted": null,
"MessagesBlocked": [
{
"GUID": "9JRzwqiZEzBesdfnEM48ItsowO9ZJ1jmBbo",
"QID": "3901vhsdfsdfg0q5d-1",
"ccAddresses": [],
"cluster": "hosted",
"completelyRewritten": false,
"fromAddress": [
"xxxx@xxx.com"
],
"headerFrom": "\"xxxx@xxx.com\" <xxxx@xxx.com>",
"headerReplyTo": null,
"id": "867899c4-bbbvnvde-9948-fxv0a2-740c13aafb98",
"impostorScore": 0,
"malwareScore": 0,
"messageID": "<98fd30b9-b15b-b883-ca4xcvxvc8-3a0dsfsf766719bc4@xxxx@xxx.com>",
"messageParts": [
{
"contentType": "text/html",
"disposition": "inline",
"filename": "text.html",
"md5": "af671999d59182d8e66e100d4140b577",
"oContentType": "text/html",
"sandboxStatus": null,
"sha256": "99e2546be00c1c2a763a51861dfgf6b2981871051843dc18542ba1417b0b464c00f"
}
],
"messageSize": 3684,
"messageTime": "2021-06-07T01:50:00.000Z",
"modulesRun": [
"av",
"spf",
"dkimv",
"spam",
"dmarc",
"pdr",
"urldefense"
],
"phishScore": 100,
"policyRoutes": [
"default_inbound"
],
"quarantineFolder": "Phish",
"quarantineRule": "inbound_spam_phish",
"recipient": [
"xxxx@xxx.com"
],
"replyToAddress": [],
"sender": "xxxx@xxx.com",
"senderIP": "000.000.000.000",
"spamScore": 100,
"subject": "Your mailbox is full......",
"threatsInfoMap": [
{
"campaignID": null,
"classification": "phish",
"threat": "io/login/verify",
"threatID": "9a53601a616eb78609e525sdfsdfc0f73356c3d9ff80f00e782105ff08c53ee5a3cfca",
"threatStatus": "active",
"threatTime": "2021-06-07T00:47:12.000Z",
"threatType": "url",
"threatUrl": "https://threatinsight.proofpoint.com"
}
],
"toAddresses": [
"xxxx@xxx.com"
],
"xmailer": null
}
],
"MessagesDelivered": null
}
}
Human Readable Output
Proofpoint Events
clicksBlocked clicksPermitted messagesBlocked messagesDelivered queryEndTime {‘spamScore’: 100, ‘phishScore’: 100, ‘threatsInfoMap’: [{‘threatID’: ‘9a53601a616eb78609e525c0f73356c3d9ff80f00e782105ff08c53ee5a3cfca’, ‘threatStatus’: ‘active’, ‘classification’: ‘phish’, ‘threatUrl’: ‘https://threatinsight.proofpoint.com’, ‘threatTime’: ‘2021-06-07T00:47:12.000Z’, ‘threat’: ‘storage.libertychurch9848737878.io/login/verify’, ‘campaignID’: None, ‘threatType’: ‘url’}, {‘threatID’: ‘b72f9ac2cec86c5f2fb795ea47f2aea23d402fe46c5c64e2565363464b1b0eb2’, ‘threatStatus’: ‘active’, ‘classification’: ‘phish’, ‘threatUrl’: ‘https://threatinsight.proofpoint.com/1c863185-589c-ad2d-49cb-0020fe555aae/threat/email/b72f9ac2cec86c5f2fb795ea47f2aea23d402fe46c5c64e2565363464b1b0eb2’, ‘threatTime’: ‘2021-06-07T00:47:23.000Z’, ‘threat’: ‘libertychurch9848737878.io’, ‘campaignID’: None, ‘threatType’: ‘url’}, {‘threatID’: ‘da0ba8d6a9d5111900f5927eb4554e49fd30e6c5c4ad5b0c975feeb19c3bfc5b’, ‘threatStatus’: ‘active’, ‘classification’: ‘phish’, ‘threatUrl’: ‘https://threatinsight.proofpoint.com/1c863185-589c-ad2d-49cb-0020fe555aae/threat/email/da0ba8d6a9d5111900f5927eb4554e49fd30e6c5c4ad5b0c975feeb19c3bfc5b’, ‘threatTime’: ‘2021-06-07T00:47:22.000Z’, ‘threat’: ‘storage.libertychurch9848737878.io/login/’, ‘campaignID’: None, ‘threatType’: ‘url’}], ‘messageTime’: ‘2021-06-07T01:50:00.000Z’, ‘impostorScore’: 0.0, ‘malwareScore’: 0, ‘cluster’: ‘hosted’, ‘subject’: ‘Your mailbox is full……’, ‘quarantineFolder’: ‘Phish’, ‘quarantineRule’: ‘inbound_spam_phish’, ‘policyRoutes’: [‘default_inbound’], ‘modulesRun’: [‘av’, ‘spf’, ‘dkimv’, ‘spam’, ‘dmarc’, ‘pdr’, ‘urldefense’], ‘messageSize’: 3684, ‘headerFrom’: ‘“xxxx@xxx.com” xxxx@xxx.com’, ‘headerReplyTo’: None, ‘fromAddress’: [‘xxxx@xxx.com’], ‘ccAddresses’: [], ‘replyToAddress’: [], ‘toAddresses’: [‘xxxx@xxx.com’], ‘xmailer’: None, ‘messageParts’: [{‘disposition’: ‘inline’, ‘sha256’: ‘99e2546be00c1c2a763a51861f6b29818710dsfsdf51843dc18542ba1417b0b464c00f’, ‘md5’: ‘af671999d59182d8e66e100d4140b577’, ‘filename’: ‘text.html’, ‘sandboxStatus’: None, ‘oContentType’: ‘text/html’, ‘contentType’: ‘text/html’}], ‘completelyRewritten’: False, ‘id’: ‘867899c4-bbde-9948-f0a2-740c13aafb98’, ‘QID’: ‘3901vhsdvf0q5d-1’, ‘GUID’: ‘9JRzwqisvsdvZEzBenEM48ItsowO9ZJ1jmBbo’, ‘sender’: ‘xxxx@xxx.com’, ‘recipient’: [‘xxxx@xxx.com’], ‘senderIP’: ‘000.000.000.000’, ‘messageID’: ‘xxxx@xxx.com’}
proofpoint-get-forensics
Returns forensics evidence.
Base Command
proofpoint-get-forensics
Input
| Argument Name | Description | Required |
|---|---|---|
| threatId | The ID of the threat (use with either threatId or campaignId). | Optional |
| campaignId | ID of the campaign (use with either threatId or campaignId). | Optional |
| includeCampaignForensics | Whether to include forensic evidence for the whole campaign. Can be used with threatId only. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.Report.ID | String | The ID of the report. |
| Proofpoint.Report.Type | String | The threat type. Can be: “attachment”, “url”, or “hybrid”. |
| Proofpoint.Report.Scope | String | Whether the report scope covers a campaign or an individual threat. |
| Proofpoint.Report.Attachment.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Attachment.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Attachment.Display | String | A friendly display string. |
| Proofpoint.Report.Attachment.SHA256 | String | The SHA256 hash of the attachment’s contents. |
| Proofpoint.Report.Attachment.MD5 | String | The MD5 hash of the attachment’s contents. |
| Proofpoint.Report.Attachment.Blacklisted | Number | Optional. Whether the file was block listed. |
| Proofpoint.Report.Attachment.Offset | Number | Optional. The offset in bytes where the malicious content was found. |
| Proofpoint.Report.Attachment.Size | Number | Optional. The size in bytes of the attachment’s contents. |
| Proofpoint.Report.Attachment.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.Attachment.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Attachment.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Cookie.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Cookie.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Cookie.Display | String | A friendly display string. |
| Proofpoint.Report.Cookie.Action | String | Whether the cookie was set or deleted. |
| Proofpoint.Report.Cookie.Domain | String | The domain that set the cookie. |
| Proofpoint.Report.Cookie.Key | String | The name of the cookie being set or deleted. |
| Proofpoint.Report.Cookie.Value | String | Optional. The content of the cookie being set. |
| Proofpoint.Report.Cookie.Platform.Name | String | Name of the platform. |
| Proofpoint.Report.Cookie.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Cookie.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.DNS.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.DNS.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.DNS.Display | String | A friendly display string. |
| Proofpoint.Report.DNS.Host | String | The hostname being resolved. |
| Proofpoint.Report.DNS.CNames | String | Optional. An array of CNames, which were associated with the hostname. |
| Proofpoint.Report.DNS.IP | String | Optional. An array of IP addresses that were resolved to the hostname. |
| Proofpoint.Report.DNS.NameServers | String | Optional. The nameservers responsible for the hostname’s domain. |
| Proofpoint.Report.DNS.NameServersList | String | Optional. The nameservers responsible for the hostnames. |
| Proofpoint.Report.DNS.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.DNS.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.DNS.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Dropper.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Dropper.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Dropper.Display | String | A friendly display string. |
| Proofpoint.Report.Dropper.Path | String | The location of the dropper file. |
| Proofpoint.Report.Dropper.URL | String | Optional. The name of the static rule inside the sandbox that identified the dropper. |
| Proofpoint.Report.Dropper.Rule | String | Optional. The URL the dropper contacted. |
| Proofpoint.Report.Dropper.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.Dropper.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Dropper.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.File.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.File.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.File.Display | String | A friendly display string. |
| Proofpoint.Report.File.Path | String | Optional. The location of the file operated on. |
| Proofpoint.Report.File.Action | String | Optional. The filesystem call made (create, modify, or delete). |
| Proofpoint.Report.File.Rule | String | Optional. The name of the static rule inside the sandbox that identified the suspicious file. |
| Proofpoint.Report.File.SHA256 | Unknown | Optional. The SH256 hash of the file’s contents. |
| Proofpoint.Report.File.MD5 | String | Optional. The MD5 hash of the file’s contents. |
| Proofpoint.Report.File.Size | Number | Optional. The size in bytes of the file’s contents. |
| Proofpoint.Report.File.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.File.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.File.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.IDS.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.IDS.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.IDS.Display | String | A friendly display string. |
| Proofpoint.Report.IDS.Name | String | The friendly name of the IDS rule that observed the malicious traffic. |
| Proofpoint.Report.IDS.SignatureID | String | The identifier of the IDS rule that observed the malicious traffic. |
| Proofpoint.Report.IDS.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.IDS.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.IDS.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Mutex.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Mutex.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Mutex.Display | String | A friendly display string. |
| Proofpoint.Report.Mutex.Name | String | The name of the mutex. |
| Proofpoint.Report.Mutex.Path | String | Optional. The path to the process which spawned the mutex. |
| Proofpoint.Report.Mutex.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.Mutex.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Mutex.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Network.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Network.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Network.Display | String | A friendly display string. |
| Proofpoint.Report.Network.Action | String | The type of network activity being initiated (connect or listen). |
| Proofpoint.Report.Network.IP | String | The remote IP address being contacted. |
| Proofpoint.Report.Network.Port | String | The remote IP port being contacted. |
| Proofpoint.Report.Network.Type | String | The protocol being used (tcp or udp). |
| Proofpoint.Report.Network.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.Network.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Network.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Process.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Process.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Process.Display | String | A friendly display string. |
| Proofpoint.Report.Process.Action | String | The action performed on the process. Relevant when create is produced. |
| Proofpoint.Report.Process.Path | String | The location of the executable that spawned the process. |
| Proofpoint.Report.Process.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.Process.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Process.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Registry.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Registry.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Registry.Display | String | A friendly display string. |
| Proofpoint.Report.Registry.Name | String | Optional. The name of the registry entry being created or set. |
| Proofpoint.Report.Registry.Action | String | The registry change made (create or set). |
| Proofpoint.Report.Registry.Key | String | The location of the registry key being modified. |
| Proofpoint.Report.Registry.Value | String | Optional. The contents of the key being created or set. |
| Proofpoint.Report.Registry.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.Registry.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Registry.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.URL.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.URL.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.URL.Display | String | A friendly display string. |
| Proofpoint.Report.URL.URL | String | The URL which was observed. |
| Proofpoint.Report.URL.Blacklisted | Boolean | Optional. Whether the URL appeared on a block list. |
| Proofpoint.Report.URL.SHA256 | String | Optional. The SHA256 hash of the file downloaded from the URL. |
| Proofpoint.Report.URL.MD5 | String | Optional. The MD5 hash of the file downloaded from the URL. |
| Proofpoint.Report.URL.Size | Number | Optional. The size in bytes of the file retrieved from the URL. |
| Proofpoint.Report.URL.HTTPStatus | Number | Optional. The HTTP status code that was produced when our sandbox visited the URL. |
| Proofpoint.Report.URL.IP | String | Optional. The IP address that was resolved to the hostname by the sandbox. |
| Proofpoint.Report.URL.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.URL.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.URL.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Behavior.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Behavior.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Behavior.Display | String | A friendly display string. |
| Proofpoint.Report.Behavior.URL | String | The URL that was observed. |
| Proofpoint.Report.Behavior.Path | String | The location of the executable which spawned the behavior. |
| Proofpoint.Report.Behavior.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.Behavior.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Behavior.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Behavior.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Behavior.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Behavior.Display | String | A friendly display string. |
| Proofpoint.Report.Behavior.URL | String | The URL that was observed. |
| Proofpoint.Report.Behavior.Path | String | The location of the executable that spawned the behavior. |
| Proofpoint.Report.Behavior.Platform.Name | String | The name of the platform. |
| Proofpoint.Report.Behavior.Platform.OS | String | The operating system of the platform. |
| Proofpoint.Report.Behavior.Platform.Version | String | The version of the platform. |
| Proofpoint.Report.Screenshot.Time | Date | The relative time at which the evidence was observed during sandboxing. |
| Proofpoint.Report.Screenshot.Malicious | String | Whether the evidence was used to reach a malicious verdict. |
| Proofpoint.Report.Screenshot.Display | String | A friendly display string. |
| Proofpoint.Report.Screenshot.URL | String | The URL hosting the screenshot image. |
Command Example
!proofpoint-get-forensics campaignId="35e291e1-c9da-4ebd-b229-538bf759b546"
Context Example
{
"Proofpoint": {
"Report": {
"Attachment": [
{
"Display": "Malicious attachment with SHA-256: 1c207a1ea4b89cc63c2d8391afcf25",
"Malicious": true,
"Platform": [
{
"Name": "Win10",
"OS": "win",
"Version": "win10"
}
],
"SHA256": "1c207da4b89cc63c2d8391afcf25",
"Time": 0
}
]
}
}
}
Human Readable Output
Forensic results from ProofPoint for ID: 35e291e1-c9da-4ebd-b229-538bf759b546
ID Scope Type 35e291e1-c9da-4ebd-b229-538bf759b546 CAMPAIGN
proofpoint-get-events-clicks-blocked
Gets events for clicks to malicious URLs blocked in the specified time period. Must provide either the interval or time_range arguments.
Base Command
proofpoint-get-events-clicks-blocked
Input
| Argument Name | Description | Required |
|---|---|---|
| threat_status | Click’s threat status to be retrieved. If no value is specified, active and cleared threats will be retrieved. Possible values: ‘active’, ‘cleared’, and ‘falsePositive’. Possible values are: active, cleared, falsePositive. | Optional |
| interval | ISO8601-formatted interval date. The minimum interval is thirty seconds. The maximum interval is one hour. For example: 2021-04-27T09:00:00Z/2021-04-27T10:00:00Z. | Optional |
| time_range | Represents the start of the data retrieval period. For example: 1 week, 2 days, 3 hours, etc. The maximum is 1 week. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.ClicksBlocked.url | String | The malicious URL was clicked. |
| Proofpoint.ClicksBlocked.classification | String | The threat category of the malicious URL (Malware, Phish, or Spam) |
| Proofpoint.ClicksBlocked.clickTime | Date | The time the user clicked the URL. |
| Proofpoint.ClicksBlocked.threatTime | Date | The time that Proofpoint identified the URL as a threat. |
| Proofpoint.ClicksBlocked.userAgent | String | The User-Agent header from the clicker’s HTTP request. |
| Proofpoint.ClicksBlocked.campaignId | String | An identifier for the campaign of which the threat is a member. |
| Proofpoint.ClicksBlocked.id | String | The unique ID of the click. |
| Proofpoint.ClicksBlocked.clickIP | String | The external IP address of the user who clicked the link. |
| Proofpoint.ClicksBlocked.sender | String | The email address of the sender. The user-part is hashed. The domain-part is cleartext. |
| Proofpoint.ClicksBlocked.recipient | String | The email address of the recipient. |
| Proofpoint.ClicksBlocked.senderIP | String | The IP address of the sender. |
| Proofpoint.ClicksBlocked.threatID | String | The unique identifier associated with this threat. |
| Proofpoint.ClicksBlocked.threatURL | String | A link to the entry on the TAP dashboard for the particular threat. |
| Proofpoint.ClicksBlocked.threatStatus | String | The current state of the threat. |
| Proofpoint.ClicksBlocked.messageID | String | The ID of the message that the URL belongs to. |
| Proofpoint.ClicksBlocked.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS. |
Command Example
!proofpoint-get-events-clicks-blocked time_range="1 hour"
Context Example
{
"Proofpoint": {
"ClicksBlocked": {
"campaignId": "46e01b8a-c899-404d-bcd9-189bb393d1a7",
"classification": "MALWARE",
"clickIP": "192.0.2.2",
"clickTime": "2010-01-22T00:00:10.000Z",
"messageID": "4444",
"recipient": "xxxx@xxx.com",
"sender": "xxxx@xxx.com",
"senderIP": "000.000.000.000",
"threatID": "threat_num2",
"threatTime": "2010-01-22T00:00:20.000Z",
"threatURL": "https://threatinsight.proofpoint.com",
"url": "http://badguy.zz/",
"userAgent": "Mozilla/5.0(WindowsNT6.1;WOW64;rv:27.0)Gecko/20100101Firefox/27.0"
}
}
}
Human Readable Output
Blocked Clicks
Id Sender IP Recipient Classification Threat ID Threat URL Threat Status Threat Time Click Time Campaign Id User Agent 000.000.000.000 xxxx@xxx.com MALWARE threat_num2 https://threatinsight.proofpoint.com 2010-01-22T00:00:20.000Z 2010-01-22T00:00:10.000Z 46e01b8a-c899-404d-bcd9-189bb393d1a7 Mozilla/5.0(WindowsNT6.1;WOW64;rv:27.0)Gecko/20100101Firefox/27.0
proofpoint-get-events-clicks-permitted
Get events for clicks to malicious URLs permitted in the specified time period. Must provide either the interval or time_range arguments.
Base Command
proofpoint-get-events-clicks-permitted
Input
| Argument Name | Description | Required |
|---|---|---|
| threat_status | Click’s threat status to be retrieved. If no value is specified, active and cleared threats will be retrieved. Possible values: ‘active’, ‘cleared’, and ‘falsePositive’. Possible values are: active, cleared, falsePositive. | Optional |
| interval | ISO8601-formatted interval date. The minimum interval is thirty seconds. The maximum interval is one hour. For example: 2021-04-27T09:00:00Z/2021-04-27T10:00:00Z. | Optional |
| time_range | Represents the start of the data retrieval period. For example: 1 week, 2 days, 3 hours, etc. The maximum is 1 week. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.ClicksPermitted.url | String | The malicious URL that was clicked. |
| Proofpoint.ClicksPermitted.classification | String | The threat category of the malicious URL (Malware, Phish, or Spam). |
| Proofpoint.ClicksPermitted.clickTime | Date | The time the user clicked the URL. |
| Proofpoint.ClicksPermitted.threatTime | Date | The time that Proofpoint identified the URL as a threat. |
| Proofpoint.ClicksPermitted.userAgent | String | The User-Agent header from the clicker’s HTTP request. |
| Proofpoint.ClicksPermitted.campaignId | String | An identifier for the campaign of which the threat is a member. |
| Proofpoint.ClicksPermitted.id | String | The unique ID of the click. |
| Proofpoint.ClicksPermitted.clickIP | String | The external IP address of the user who clicked the link. |
| Proofpoint.ClicksPermitted.sender | String | The email address of the sender. The user-part is hashed. The domain-part is in cleartext. |
| Proofpoint.ClicksPermitted.recipient | String | The email address of the recipient. |
| Proofpoint.ClicksPermitted.senderIP | String | The IP address of the sender. |
| Proofpoint.ClicksPermitted.threatID | String | The unique identifier associated with this threat. |
| Proofpoint.ClicksPermitted.threatURL | String | A link to the entry on the TAP dashboard for the particular threat. |
| Proofpoint.ClicksPermitted.threatStatus | String | The current state of the threat. |
| Proofpoint.ClicksPermitted.messageID | String | The ID of the message that the URL belongs to. |
| Proofpoint.ClicksPermitted.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS. |
Command Example
!proofpoint-get-events-clicks-permitted time_range="1 hour"
Context Example
{
"Proofpoint": {
"ClicksPermitted": {
"campaignId": "46e01b8a-c899-404d-bcd9-189bb393d1a7",
"classification": "MALWARE",
"clickIP": "192.0.2.2",
"clickTime": "2010-01-22T00:00:10.000Z",
"messageID": "4444",
"recipient": "xxxx@xxx.com",
"sender": "9facbf452def2d7efc5b5c48cdb837fa@badguy.zz",
"senderIP": "000.000.000.000",
"threatID": "threat_num2",
"threatTime": "2010-01-22T00:00:20.000Z",
"threatURL": "https://threatinsight.proofpoint.com",
"url": "http://badguy.zz/",
"userAgent": "Mozilla/5.0(WindowsNT6.1;WOW64;rv:27.0)Gecko/20100101Firefox/27.0"
}
}
}
Human Readable Output
Permitted Clicks
Id Sender IP Recipient Classification Threat ID Threat URL Threat Status Threat Time Click Time Campaign Id User Agent 192.0.2.255 xxxx@xxx.com MALWARE threat_num2 https://threatinsight.proofpoint.com 2010-01-22T00:00:20.000Z 2010-01-22T00:00:10.000Z 46e01b8a-c899-404d-bcd9-189bb393d1a7 Mozilla/5.0(WindowsNT6.1;WOW64;rv:27.0)Gecko/20100101Firefox/27.0
proofpoint-get-events-messages-blocked
Get events for blocked messages in the specified time period. Must provide either the interval or time_range arguments.
Base Command
proofpoint-get-events-messages-blocked
Input
| Argument Name | Description | Required |
|---|---|---|
| threat_type | Message’s threat type to be retrieved. If no value is specified, all threat types will be retrieved. Possible values: ‘url’, ‘attachment’, and ‘message’. Possible values are: url, attachment, message. | Optional |
| threat_status | Message’s threat status to be retrieved. If no value is specified, active and cleared threats will be retrieved. Possible values: ‘active’, ‘cleared’, and ‘falsePositive’. Possible values are: active, cleared, falsePositive. | Optional |
| interval | ISO8601-formatted interval date. The minimum interval is thirty seconds. The maximum interval is one hour. For example: 2021-04-27T09:00:00Z/2021-04-27T10:00:00Z. | Optional |
| time_range | Represents the start of the data retrieval period. For example: 1 week, 2 days, 3 hours, etc. The maximum is 1 week. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.MessagesBlocked.spamScore | Number | The spam score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesBlocked.phishScore | Number | The phish score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesBlocked.threatsInfoMap | List | List that contains details about detected threats within the message. Contains: campaignID, classification, threat, threatID, threatStatus,threatTime, threatType, threatUrl. |
| Proofpoint.MessagesBlocked.messageTime | Date | The time the message was delivered to the user or quarantined by PPS. |
| Proofpoint.MessagesBlocked.impostorScore | Number | The impostor score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesBlocked.malwareScore | Number | The malware score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesBlocked.cluster | String | The name of the PPS cluster that processed the message. |
| Proofpoint.MessagesBlocked.subject | String | The subject line of the message, if available. |
| Proofpoint.MessagesBlocked.quarantineFolder | String | The name of the folder that contains the quarantined message. This appears only for blocked messages. For delivered messages will be ‘None’. |
| Proofpoint.MessagesBlocked.quarantineRule | String | The name of the rule that quarantined the message. This appears only for messagesBlocked events. |
| Proofpoint.MessagesBlocked.policyRoutes | List | The policy routes that the message matched during processing by PPS. |
| Proofpoint.MessagesBlocked.modulesRun | String | The list of PPS modules that processed the message. |
| Proofpoint.MessagesBlocked.messageSize | Number | The size in bytes of the message, including headers and attachments. |
| Proofpoint.MessagesBlocked.Header.headerFrom | String | The full content of the From header, including any friendly name. |
| Proofpoint.MessagesBlocked.Header.headerReplyTo | String | If present, the full content of the Reply-To: header, including any friendly names. |
| Proofpoint.MessagesBlocked.Header.fromAddress | List | The email address contained in the From header, excluding the friendly name. |
| Proofpoint.MessagesBlocked.Header.ccAddresses | List | A list of email addresses contained within the CC: header, excluding friendly names. |
| Proofpoint.MessagesBlocked.Header.replyToAddress | List | The email address contained in the Reply-To: header, excluding friendly name. |
| Proofpoint.MessagesBlocked.Header.toAddresses | List | A list of email addresses contained within the To: header, excluding friendly names. |
| Proofpoint.MessagesBlocked.Header.xmailer | String | The content of the X-Mailer: header, if present. |
| Proofpoint.MessagesBlocked.messageParts | List | An array of structures that contain details about parts of the message, including both message bodies and attachments. |
| Proofpoint.MessagesBlocked.completelyRewritten | String | The rewrite status of the message. If value is true, all instances of URL threats within the message were successfully rewritten. If the value is false, at least one instance of the threat URL was not rewritten. If the value is ‘na’, the message did not contain any URL-based threats. |
| Proofpoint.MessagesBlocked.id | String | The unique ID of the message. |
| Proofpoint.MessagesBlocked.sender | String | The email address of the SMTP (envelope) sender. The user-part is hashed. The domain-part is cleartext. |
| Proofpoint.MessagesBlocked.recipient | List | A list containing the email addresses of the recipients. |
| Proofpoint.MessagesBlocked.senderIP | String | The IP address of the sender. |
| Proofpoint.MessagesBlocked.messageID | String | Message-ID extracted from the headers of the email message. |
| Proofpoint.MessagesBlocked.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS. |
Command Example
!proofpoint-get-events-messages-blocked interval="2021-06-07T02:00:00Z/2021-06-07T03:00:00Z"
Context Example
{
"Proofpoint": {
"MessagesBlocked": [
{
"GUID": "9JRzwqiZEzBenEMsdgsdfg48ItsowO9ZJ1jmBbo",
"Header": {
"ccAddresses": [],
"fromAddress": [
"xxxx@xxx.com"
],
"headerFrom": "\"xxxx@xxx.com\" <xxxx@xxx.com>",
"headerReplyTo": null,
"replyToAddress": [],
"toAddresses": [
"xxxx@xxx.com"
],
"xmailer": null
},
"cluster": "hosted",
"completelyRewritten": false,
"id": "867899c4-bbde-9948-f0a2-740c13aafb98",
"impostorScore": 0,
"malwareScore": 0,
"messageID": "<xxxx@xxx.com>",
"messageParts": [
{
"contentType": "text/html",
"disposition": "inline",
"filename": "text.html",
"md5": "a",
"oContentType": "text/html",
"sandboxStatus": null,
"sha256": "99843dc18542ba1417b0b464c00f"
}
],
"messageSize": 3684,
"messageTime": "2021-06-07T01:50:00.000Z",
"modulesRun": [
"av",
"spf",
"dkimv",
"spam",
"dmarc",
"pdr",
"urldefense"
],
"phishScore": 100,
"policyRoutes": [
"default_inbound"
],
"quarantineFolder": "Phish",
"quarantineRule": "inbound_spam_phish",
"recipient": [
"xxxx@xxx.com"
],
"sender": "xxxx@xxx.com",
"senderIP": "000.000.000.000",
"spamScore": 100,
"subject": "Your mailbox is full......",
"threatsInfoMap": [
{
"campaignID": null,
"classification": "phish",
"threat": "login/verify",
"threatID": "9a",
"threatStatus": "active",
"threatTime": "2021-06-07T00:47:12.000Z",
"threatType": "url",
"threatUrl": "https://threatinsight.proofpoint.com"
},
]
}
]
}
}
Human Readable Output
Blocked Messages
Sender IP Sender Recipient Subject Message Size Message Time Malware Score Phish Score Spam Score 000.000.000.000 xxxx@xxx.com xxxx@xxx.com Your mailbox is full…… 3684 2021-06-07T01:50:00.000Z 0 100 100 Blocked Messages Threats Information
Sender Recipient Subject Classification Threat Threat Status Threat Url Threat ID Threat Time Campaign ID xxxx@xxx.com xxxx@xxx.com Your mailbox is full…… phish login/verify active https://threatinsight.proofpoint.com 9a53601a616eb78609e525c0f3ee5a3cfca 2021-06-07T00:47:12.000Z
proofpoint-get-events-messages-delivered
Get events for delivered messages in the specified time period. Must provide either the interval or time_range arguments.
Base Command
proofpoint-get-events-messages-delivered
Input
| Argument Name | Description | Required |
|---|---|---|
| threat_type | Message’s threat type to be retrieved. If no value is specified, all threat types will be retrieved. Possible values: ‘url’, ‘attachment’, and ‘message’. Possible values are: url, attachment, message. | Optional |
| threat_status | Message’s threat status to be retrieved. If no value is specified, active and cleared threats will be retrieved. Possible values: ‘active’, ‘cleared’, and ‘falsePositive’. Possible values are: active, cleared, falsePositive. | Optional |
| interval | ISO8601-formatted interval date. The minimum interval is thirty seconds. The maximum interval is one hour. For example: 2021-04-27T09:00:00Z/2021-04-27T10:00:00Z. | Optional |
| time_range | Represents the start of the data retrieval period. For example: 1 week, 2 days, 3 hours, etc. The maximum is 1 week. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.MessagesDelivered.spamScore | Number | The spam score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.phishScore | Number | The phish score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.threatsInfoMap | List | List that contains details about detected threats within the message. Contains: campaignID, classification, threat, threatID, threatStatus,threatTime, threatType, threatUrl. |
| Proofpoint.MessagesDelivered.messageTime | Date | The time the message was delivered to the user or quarantined by PPS. |
| Proofpoint.MessagesDelivered.impostorScore | Number | The impostor score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.malwareScore | Number | The malware score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.cluster | String | The name of the PPS cluster that processed the message. |
| Proofpoint.MessagesDelivered.subject | String | The subject line of the message, if available. |
| Proofpoint.MessagesDelivered.quarantineFolder | String | The name of the folder that contains the quarantined message. This appears only for blocked messages. For delivered messages will be ‘None’. |
| Proofpoint.MessagesDelivered.quarantineRule | String | The name of the rule that quarantined the message. This appears only for messagesBlocked events. |
| Proofpoint.MessagesDelivered.policyRoutes | List | The policy routes that the message matched during processing by PPS. |
| Proofpoint.MessagesDelivered.modulesRun | String | The list of PPS modules that processed the message. |
| Proofpoint.MessagesDelivered.messageSize | Number | The size in bytes of the message, including headers and attachments. |
| Proofpoint.MessagesDelivered.Header.headerFrom | String | The full content of the From header, including any friendly name. |
| Proofpoint.MessagesDelivered.Header.headerReplyTo | String | If present, the full content of the Reply-To: header, including any friendly names. |
| Proofpoint.MessagesDelivered.Header.fromAddress | List | The email address contained in the From header, excluding the friendly name. |
| Proofpoint.MessagesDelivered.Header.ccAddresses | List | A list of email addresses contained within the CC: header, excluding friendly names. |
| Proofpoint.MessagesDelivered.Header.replyToAddress | List | The email address contained in the Reply-To: header, excluding friendly name. |
| Proofpoint.MessagesDelivered.Header.toAddresses | List | A list of email addresses contained within the To: header, excluding friendly names. |
| Proofpoint.MessagesDelivered.Header.xmailer | String | The content of the X-Mailer: header, if present. |
| Proofpoint.MessagesDelivered.messageParts | List | An array of structures that contains details about parts of the message, including both message bodies and attachments. |
| Proofpoint.MessagesDelivered.completelyRewritten | String | The rewrite status of the message. If value is true, all instances of URL threats within the message were successfully rewritten. If the value is false, at least one instance of the threat URL was not rewritten. If the value is ‘na’, the message did not contain any URL-based threats. |
| Proofpoint.MessagesDelivered.id | String | The unique ID of the message. |
| Proofpoint.MessagesDelivered.sender | String | The email address of the SMTP (envelope) sender. The user-part is hashed. The domain-part is cleartext. |
| Proofpoint.MessagesDelivered.recipient | List | A list containing the email addresses of the recipients. |
| Proofpoint.MessagesDelivered.senderIP | String | The IP address of the sender. |
| Proofpoint.MessagesDelivered.messageID | String | Message-ID extracted from the headers of the email message. |
| Proofpoint.MessagesDelivered.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS and is guaranteed to be unique. |
Command Example
!proofpoint-get-events-messages-delivered interval="2021-06-03T17:00:00Z/2021-06-03T18:00:00Z"
Context Example
{
"Proofpoint": {
"MessagesDelivered": {
"GUID": "Ggfsdfsdf",
"Header": {
"ccAddresses": [],
"fromAddress": [
"xxxx@xxx.com"
],
"headerFrom": "\"j.\" <xxxx@xxx.com>",
"headerReplyTo": null,
"replyToAddress": [],
"toAddresses": [],
"xmailer": null
},
"cluster": "hosted",
"completelyRewritten": true,
"id": "1828003vsdv05566e842",
"impostorScore": 0,
"malwareScore": 0,
"messageID": "<SI2PR0dfbvd.xxxx@xxx.com.com>",
"messageParts": [
{
"contentType": "text/html",
"disposition": "inline",
"filename": "text.html",
"md5": "fcfa9b21f43fbdf02965263c63e",
"oContentType": "text/html",
"sandboxStatus": null,
"sha256": "72d3dc7a01dfbdbe8e871536864f56bf235ba08ff259105ac"
},
],
"messageSize": 10171,
"messageTime": "2021-06-02T13:41:32.000Z",
"modulesRun": [
"av",
"spf",
"dkimv",
"spam",
"dmarc",
"urldefense"
],
"phishScore": 0,
"policyRoutes": [
"default_inbound",
"allow_relay"
],
"quarantineFolder": null,
"quarantineRule": null,
"recipient": [
"xxxx@xxx.com"
],
"sender": "xxxx@xxx.com",
"senderIP": "400.000.000",
"spamScore": 43,
"subject": "=",
"threatsInfoMap": [
{
"campaignID": null,
"classification": "phish",
"threat": "https://bit.ly",
"threatID": "45fe3b35ghkk2b8916934b6c0a536cc9b2603d03",
"threatStatus": "active",
"threatTime": "2021-06-03T07:17:11.000Z",
"threatType": "url",
"threatUrl": "https://threatinsight.proofpoint.com"
}
]
}
}
}
Human Readable Output
Delivered Messages
Sender IP Sender Recipient Subject Message Size Message Time Malware Score Phish Score Spam Score 00.000.000.0000 xxxx@xxx.com xxxx@xxx.com = 10171 2021-06-02T13:41:32.000Z 0 0 43 Delivered Messages Threats Information
Sender Recipient Subject Classification Threat Threat Status Threat Url Threat ID Threat Time Campaign ID xxxx@xxx.com xxxx@xxx.com = phish https://bit.ly active https://threatinsight.proofpoint.com 45fe3b35b7bd2adfad6dea4d305bea3e7c1a2b8gfhh03d03 2021-06-03T07:17:11.000Z
proofpoint-list-issues
Get events for clicks to malicious URLs permitted and messages delivered containing a known attachment threat within the specified time period. Must provide either the interval or time_range arguments.
Base Command
proofpoint-list-issues
Input
| Argument Name | Description | Required |
|---|---|---|
| threat_type | Event’s threat type to be retrieved. If no value is specified, all threat types will be retrieved. Possible values: ‘url’, ‘attachment’, and ‘message’. Possible values are: url, attachment, message. | Optional |
| threat_status | Event’s threat status to be retrieved.If no value is specified, active and cleared threats will be retrieved. Possible values: ‘url’, ‘attachment’, and ‘message’. Possible values are: active, cleared, falsePositive. | Optional |
| interval | ISO8601-formatted interval date. The minimum interval is thirty seconds. The maximum interval is one hour. For example: 2021-04-27T09:00:00Z/2021-04-27T10:00:00Z. | Optional |
| time_range | Represents the start of the data retrieval period. For example: 1 week, 2 days, 3 hours, etc. The maximum is 1 week. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.ClicksPermitted.url | String | The malicious URL was clicked. |
| Proofpoint.ClicksPermitted.classification | String | The threat category of the malicious URL (Malware, Phish, or Spam). |
| Proofpoint.ClicksPermitted.clickTime | Date | The time the user clicked the URL. |
| Proofpoint.ClicksPermitted.threatTime | Date | The time that Proofpoint identified the URL as a threat. |
| Proofpoint.ClicksPermitted.userAgent | String | The User-Agent header from the clicker’s HTTP request. |
| Proofpoint.ClicksPermitted.campaignId | String | An identifier for the campaign of which the threat is a member. |
| Proofpoint.ClicksPermitted.id | String | The unique ID of the click. |
| Proofpoint.ClicksPermitted.clickIP | String | The external IP address of the user who clicked the link. |
| Proofpoint.ClicksPermitted.sender | String | The email address of the sender. The user-part is hashed. The domain-part is in cleartext. |
| Proofpoint.ClicksPermitted.recipient | String | The email address of the recipient. |
| Proofpoint.ClicksPermitted.senderIP | String | The IP address of the sender. |
| Proofpoint.ClicksPermitted.threatID | String | The unique identifier associated with this threat. |
| Proofpoint.ClicksPermitted.threatURL | String | A link to the entry on the TAP dashboard for the particular threat. |
| Proofpoint.ClicksPermitted.threatStatus | String | The current state of the threat. |
| Proofpoint.ClicksPermitted.messageID | String | The ID of the message that the URL belongs to. |
| Proofpoint.ClicksPermitted.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS and is guaranteed to be unique. |
| Proofpoint.MessagesDelivered.spamScore | Number | The spam score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.phishScore | Number | The phish score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.threatsInfoMap | List | List which contain details about detected threats within the message. Contains: campaignID, classification, threat, threatID, threatStatus,threatTime, threatType, threatUrl. |
| Proofpoint.MessagesDelivered.messageTime | Date | THe time the message was delivered to the user or quarantined by PPS. |
| Proofpoint.MessagesDelivered.impostorScore | Number | The impostor score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.malwareScore | Number | The malware score of the message. Higher scores indicate higher certainty. |
| Proofpoint.MessagesDelivered.cluster | String | The name of the PPS cluster that processed the message. |
| Proofpoint.MessagesDelivered.subject | String | The subject line of the message, if available. |
| Proofpoint.MessagesDelivered.quarantineFolder | String | The name of the folder that contains the quarantined message. This appears only for blocked messages. For delivered messages will be ‘None’. |
| Proofpoint.MessagesDelivered.quarantineRule | String | The name of the rule that quarantined the message. This appears only for messagesBlocked events. |
| Proofpoint.MessagesDelivered.policyRoutes | List | The policy routes that the message matched during processing by PPS. |
| Proofpoint.MessagesDelivered.modulesRun | String | The list of PPS modules that processed the message. |
| Proofpoint.MessagesDelivered.messageSize | Number | The size in bytes of the message, including headers and attachments. |
| Proofpoint.MessagesDelivered.Header.headerFrom | String | The full content of the From header, including any friendly name. |
| Proofpoint.MessagesDelivered.Header.headerReplyTo | String | If present, the full content of the Reply-To: header, including any friendly names. |
| Proofpoint.MessagesDelivered.Header.fromAddress | List | The email address contained in the From header, excluding any friendly name. |
| Proofpoint.MessagesDelivered.Header.ccAddresses | List | A list of email addresses contained within the CC: header, excluding any friendly names. |
| Proofpoint.MessagesDelivered.Header.replyToAddress | List | The email address contained in the Reply-To: header, excluding any friendly name. |
| Proofpoint.MessagesDelivered.Header.toAddresses | List | A list of email addresses contained within the To: header, excluding any friendly names. |
| Proofpoint.MessagesDelivered.Header.xmailer | String | The content of the X-Mailer: header, if present. |
| Proofpoint.MessagesDelivered.messageParts | List | An array of structures that contain details about parts of the message, including both message bodies and attachments. |
| Proofpoint.MessagesDelivered.completelyRewritten | String | The rewrite status of the message. If value is true, all instances of URL threats within the message were successfully rewritten. If the value is false, at least one instance of the threat URL was not rewritten. If the value is ‘na’, the message did not contain any URL-based threats. |
| Proofpoint.MessagesDelivered.id | String | The unique ID of the message. |
| Proofpoint.MessagesDelivered.sender | String | The email address of the SMTP (envelope) sender. The user-part is hashed. The domain-part is cleartext. |
| Proofpoint.MessagesDelivered.recipient | List | A list containing the email addresses of the recipients |
| Proofpoint.MessagesDelivered.senderIP | String | The IP address of the sender. |
| Proofpoint.MessagesDelivered.messageID | String | Message-ID extracted from the headers of the email message. |
| Proofpoint.MessagesDelivered.GUID | String | The ID of the message within PPS. It can be used to identify the message in PPS and is guaranteed to be unique. |
Command Example
!proofpoint-list-issues interval="2021-06-03T17:00:00Z/2021-06-03T18:00:00Z"
Context Example
{
"Proofpoint": {
"MessagesDelivered": {
"GUID": "Ggfsdfsdf",
"Header": {
"ccAddresses": [],
"fromAddress": [
"xxxx@xxx.com"
],
"headerFrom": "\"j.\" <xxxx@xxx.com>",
"headerReplyTo": null,
"replyToAddress": [],
"toAddresses": [],
"xmailer": null
},
"cluster": "hosted",
"completelyRewritten": true,
"id": "1828003vsdv05566e842",
"impostorScore": 0,
"malwareScore": 0,
"messageID": "<SI2PR0dfbvd.xxxx@xxx.com.com>",
"messageParts": [
{
"contentType": "text/html",
"disposition": "inline",
"filename": "text.html",
"md5": "fcfa9b21f43fbdf02965263c63e",
"oContentType": "text/html",
"sandboxStatus": null,
"sha256": "72d3dc7a01dfbdbe8e871536864f56bf235ba08ff259105ac"
},
],
"messageSize": 10171,
"messageTime": "2021-06-02T13:41:32.000Z",
"modulesRun": [
"av",
"spf",
"dkimv",
"spam",
"dmarc",
"urldefense"
],
"phishScore": 0,
"policyRoutes": [
"default_inbound",
"allow_relay"
],
"quarantineFolder": null,
"quarantineRule": null,
"recipient": [
"xxxx@xxx.com"
],
"sender": "xxxx@xxx.com",
"senderIP": "400.000.000",
"spamScore": 43,
"subject": "=",
"threatsInfoMap": [
{
"campaignID": null,
"classification": "phish",
"threat": "https://bit.ly",
"threatID": "45fe3b35ghkk2b8916934b6c0a536cc9b2603d03",
"threatStatus": "active",
"threatTime": "2021-06-03T07:17:11.000Z",
"threatType": "url",
"threatUrl": "https://threatinsight.proofpoint.com"
}
]
}
}
}
Human Readable Output
Delivered Messages
Sender IP Sender Recipient Subject Message Size Message Time Malware Score Phish Score Spam Score 00.000.000.0000 xxxx@xxx.com xxxx@xxx.com = 10171 2021-06-02T13:41:32.000Z 0 0 43 Delivered Messages Threats Information
Sender Recipient Subject Classification Threat Threat Status Threat Url Threat ID Threat Time Campaign ID xxxx@xxx.com xxxx@xxx.com = phish https://bit.ly active https://threatinsight.proofpoint.com 45fe3b35b7bd2adfad6dea4d305bea3e7c1a2b8gfhh03d03 2021-06-03T07:17:11.000Z
Permitted click from list-issues command result
No entries.
proofpoint-list-campaigns
Gets a list of IDs of campaigns active in a specified time period. Must provide either the interval or time_range arguments.
Base Command
proofpoint-list-campaigns
Input
| Argument Name | Description | Required |
|---|---|---|
| interval | ISO8601-formatted interval date. The minimum interval is thirty seconds. The maximum interval is one day. For example: 2021-04-27T09:00:00Z/2021-04-27T10:00:00Z. | Optional |
| limit | The maximum number of campaign IDs to produce in the response. Defaults to 100 and the maximum supported value is 200. Default is 100. | Optional |
| page | The page of results to return, in multiples of the specified size. Default is 1. | Optional |
| time_range | Represents the start of the data retrieval period. For example: 1 week, 2 days, 3 hours, etc. The maximum is 1 week. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.Campaigns.id | String | The campaign ID. |
| Proofpoint.Campaigns.lastUpdatedAt | String | Last updated timestamp of the campaign. |
Command Example
!proofpoint-list-campaigns interval="2021-06-01T11:00:00Z/2021-06-02T11:00:00Z"
Context Example
{
"Proofpoint": {
"Campaign": {
"id": "7c91b71fdgdfgdfg591a1ad38",
"lastUpdatedAt": "2021-06-03T13:01:57.000Z"
}
}
}
Human Readable Output
Campaigns List
Id Last Updated At 7c91b71fdgdfgdfg591a1ad38 2021-06-03T13:01:57.000Z
proofpoint-get-campaign
Gets details for a given campaign.
Base Command
proofpoint-get-campaign
Input
| Argument Name | Description | Required |
|---|---|---|
| campaign_id | ID of the required campaign. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.Campaign.info | List | The campaign information - ID,name, description, startDate, and notable. |
| Proofpoint.Campaign.actors | List | A list of actor objects. |
| Proofpoint.Campaign.families | List | A list of family objects. |
| Proofpoint.Campaign.malware | List | A list of malware objects. |
| Proofpoint.Campaign.techniques | List | A list of technique objects. |
| Proofpoint.Campaign.brands | List | A list of brand objects. |
| Proofpoint.Campaign.campaignMembers | List | A list of campaign member objects. |
Command Example
!proofpoint-get-campaign campaign_id="f3ff0874-85ef-475e-b3fe-d05f97b2ed3f"
Context Example
{
"Proofpoint": {
"Campaign": {
"actors": [],
"brands": [],
"campaignMembers": [],
"families": [
{
"id": "69a63403-f478-40f6-a4cb-3d2ffb85b98e",
"name": "Keylogger"
}
],
"info": {
"description": "Messages purporting to be e.g.\r\n\r\n* from <xxxx@xxx.com;' and subject \"Re: New Order From customer\".\r\n\r\nThese messages contain compressed executables that lead to the installation of AgentTesla with the following example configuration:\r\n\r\n<pre>C2_Email_Address: xxxx@xxx.com\r\nC2_Email_Password: \r\nC2_Email_Server: xxxx@xxx.com</pre>",
"id": "f3ff087dfgdfge-d05f97b2ed3f",
"name": "AgentTesla | Compressed Executables | \"techie\" | 25 March 2021",
"notable": false,
"startDate": "2021-03-25T00:00:00.000Z"
},
"malware": [
{
"id": "4b50dfbdfb-901a-1cb4cf8a21fb",
"name": "AgentTesla"
}
],
"techniques": [
{
"id": "e488ddfbdfb20-a1aa-d1a85494067c",
"name": "Compressed Executable"
}
]
}
}
}
Human Readable Output
Campaign Information
Id Name Description Start Date Notable f3ff08dfbdb5e-b3fe-d05f97b2ed3f AgentTesla | Compressed Executables | “techie” | 25 March 2021 Messages purporting to be e.g.
* from <xxxx@xxx.com>’ and subject “Re: New Order From customer”.
These messages contain compressed executables that lead to the installation of AgentTesla with the following example configuration:
<pre>C2_Email_Address: xxxx@xxx.com
C2_Email_Password:
C2_Email_Server: xxxx@xxx.com</pre>2021-03-25T00:00:00.000Z false Campaign Members
No entries.
Families
Id Name 69a63403-dbfdfb4cb-3d2ffb85b98e Keylogger Techniques
Id Name e48835be-xcvxcvaa-d1a85494067c Compressed Executable Actors
No entries.
Brands
No entries.
Malware
Id Name 4b500558-23d0-sfdsdf1cb4cf8a21fb AgentTesla
proofpoint-list-most-attacked-users
Gets a list of the most attacked users in the organization.
Base Command
proofpoint-list-most-attacked-users
Input
| Argument Name | Description | Required |
|---|---|---|
| window | An integer indicating how many days the data should be retrieved for. Possible values: “14”, “30”, “90”. Possible values are: 14, 30, 90. Default is false. | Required |
| limit | The maximum number of users to produce in the response. Default is 1000. | Optional |
| page | The page of results to return. Default is 1. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.Vap.users | List | List of users in the organization. |
| Proofpoint.Vap.totalVapUsers | Number | The total number of VAP users for the interval. |
| Proofpoint.Vap.interval | String | An ISO8601-formatted interval showing the time the response was calculated for. |
| Proofpoint.Vap.averageAttackIndex | Number | The average attack index value for users during the interval. |
| Proofpoint.Vap.vapAttackIndexThreshold | Number | This interval’s attack index threshold, past which a user is considered a VAP. |
Command Example
!proofpoint-list-most-attacked-users window="14"
Context Example
{
"Proofpoint": {
"Vap": {
"averageAttackIndex": 307.05145,
"interval": "2021-05-23T21:44:53Z/2021-06-06T21:44:53Z",
"totalVapUsers": 1,
"users": [
{
"identity": {
"customerUserId": null,
"department": null,
"emails": [
"xxxx@xxx.com"
],
"guid": "3b5132sdvsd76-c442-919e69175bdd",
"location": null,
"name": null,
"title": null,
"vip": false
},
"threatStatistics": {
"attackIndex": 4576,
"families": [
{
"name": "credential phishing",
"score": 7008
}
]
}
}
],
"vapAttackIndexThreshold": 965.9637
}
}
}
Human Readable Output
Most Attacked Users Information
Total Vap Users Interval Average Attack Index Vap Attack Index Threshold 7 2021-05-23T21:44:53Z/2021-06-06T21:44:53Z 307.05145 965.9637 Threat Families
Mailbox Threat Family Name Threat Score xxxx@xxx.com credential phishing 7008
proofpoint-get-top-clickers
Gets a list of the top clickers in the organization for a specified time period.
Base Command
proofpoint-get-top-clickers
Input
| Argument Name | Description | Required |
|---|---|---|
| window | An integer indicating how many days the data should be retrieved for. Possible values: “14”, “30”, “90”. Possible values are: 14, 30, 90. Default is false. | Required |
| limit | The maximum number of top clickers to produce in the response.The max supported value is 200. Default is 100. | Optional |
| page | The page of results to return. Default is 1. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.Topclickers.users | List | List of users in the organization. |
| Proofpoint.Topclickers.totalTopClickers | int | The total number of top clickers in the time interval. |
| Proofpoint.Topclickers.interval | Date | An ISO8601-formatted interval showing the time the response was calculated for. |
Command Example
!proofpoint-get-top-clickers window="90"
Context Example
{
"Proofpoint": {
"Topclickers": {
"interval": "2021-03-09T07:17:00Z/2021-06-07T07:17:00Z",
"totalTopClickers": 1,
"users": [
{
"clickStatistics": {
"clickCount": 2,
"families": [
{
"clicks": 2,
"name": "Malware"
}
]
},
"identity": {
"customerUserId": null,
"department": null,
"emails": [
"xxxx@xxx.come"
],
"guid": "44fa5svfdgae-f22f-b49b49b1e4e3",
"location": null,
"name": null,
"title": null,
"vip": false
}
}
]
}
}
}
Human Readable Output
Top Clickers Users Information
Total Top Clickers Interval 1 2021-03-09T07:17:00Z/2021-06-07T07:17:00Z Threat Families
Mailbox Threat Family Name Threat Score xxxx@xxx.com Malware
proofpoint-url-decode
Decodes URLs that have been rewritten by TAP to their original, target URL.
Base Command
proofpoint-url-decode
Input
| Argument Name | Description | Required |
|---|---|---|
| urls | A comma-separated list of encoded URLs. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Proofpoint.URL.encodedUrl | String | The original, rewritten URL supplied to the endpoint. |
| Proofpoint.URL.decodedUrl | String | The target URL embedded inside the rewritten link. |
| Proofpoint.URL.success | Boolean | Indicates whether the URL could successfully be decoded. |
Command Example
!proofpoint-url-decode urls="https://urldefense.proofpoint.com/v2/url?u=http-3A__links.mkt3337.com_ctt-3Fkn-3D3-26ms-3DMzQ3OTg3MDQS1-26r-3DMzkxNzk3NDkwMDA0S0-26b-3D0-26j-3DMTMwMjA1ODYzNQS2-26mt-3D1-26rt-3D0&d=DwMFaQ&c=Vxt5e0Osvvt2gflwSlsJ5DmPGcPvTRKLJyp031rXjhg&r=MujLDFBJstxoxZI_GKbsW7wxGM7nnIK__qZvVy6j9Wc&m=QJGhloAyfD0UZ6n8r6y9dF-khNKqvRAIWDRU_K65xPI&s=ew-rOtBFjiX1Hgv71XQJ5BEgl9TPaoWRm_Xp9Nuo8bk&e="
Context Example
{
"Proofpoint": {
"URL": {
"decodedUrl": "http://links.mkt3337.com/ctt?kn=3&ms=MzQ3OTg3MDQS1&r=MzkxNzk3NDkwMDA0S0&b=0&j=MTMwMjA1ODYzNQS2&mt=1&rt=0",
"encodedUrl": "https://urldefense.proofpoint.com/v2/url?u=http-3A__links.mkt3337.com_ctt-3Fkn-3D3-26ms-3DMzQ3OTg3MDQS1-26r-3DMzkxNzk3NDkwMDA0S0-26b-3D0-26j-3DMTMwMjA1ODYzNQS2-26mt-3D1-26rt-3D0&d=DwMFaQ&c=Vxt5e0Osvvt2gflwSlsJ5DmPGcPvTRKLJyp031rXjhg&r=MujLDFBJstxoxZI_GKbsW7wxGM7nnIK__qZvVy6j9Wc&m=QJGhloAyfD0UZ6n8r6y9dF-khNKqvRAIWDRU_K65xPI&s=ew-rOtBFjiX1Hgv71XQJ5BEgl9TPaoWRm_Xp9Nuo8bk&e=",
"success": true
}
}
}
Human Readable Output
URLs decoded information
Encoded Url Decoded Url https://urldefense.proofpoint.com/v2/url?u=http-3A__links.mkt3337.com_ctt-3Fkn-3D3-26ms-3DMzQ3OTg3MDQS1-26r-3DMzkxNzk3NDkwMDA0S0-26b-3D0-26j-3DMTMwMjA1ODYzNQS2-26mt-3D1-26rt-3D0&d=DwMFaQ&c=Vxt5e0Osvvt2gflwSlsJ5DmPGcPvTRKLJyp031rXjhg&r=MujLDFBJstxoxZI_GKbsW7wxGM7nnIK__qZvVy6j9Wc&m=QJGhloAyfD0UZ6n8r6y9dF-khNKqvRAIWDRU_K65xPI&s=ew-rOtBFjiX1Hgv71XQJ5BEgl9TPaoWRm_Xp9Nuo8bk&e= http://links.mkt3337.com/ctt?kn=3&ms=MzQ3OTg3MDQS1&r=MzkxNzk3NDkwMDA0S0&b=0&j=MTMwMjA1ODYzNQS2&mt=1&rt=0
Configuration parameters
url— Server URL (required)credentials— Service Principal (required)api_version— API Versioninsecure— Trust any certificate (not secure)proxy— Use system proxy settingsthreat_type— Threat typethreat_status— Threat statusevents_type— Events to fetchlimit— Maximum number of incident per fetchfetch_time— First fetch time rangeraw_json_encoding— Advanced: Raw message encodinglook_back_minutes— Events Fetch Look-Back (minutes)isFetch— Fetch incidentsincidentType— Incident typeincidentFetchInterval— Incidents Fetch Interval
Commands (12)
-
proofpoint-get-campaignGets details for a given campaign.
-
proofpoint-get-eventsFetches events for all clicks and messages relating to known threats within the specified time period. Details as per clicks/blocked.
-
proofpoint-get-events-clicks-blockedGets events for clicks to malicious URLs blocked in the specified time period. Must provide either the interval or time_range arguments.
-
proofpoint-get-events-clicks-permittedGet events for clicks to malicious URLs permitted in the specified time period. Must provide either the interval or time_range arguments.
-
proofpoint-get-events-messages-blockedGet events for blocked messages in the specified time period. Must provide either the interval or time_range arguments.
-
proofpoint-get-events-messages-deliveredGet events for delivered messages in the specified time period. Must provide either the interval or time_range arguments.
-
proofpoint-get-forensicsReturns forensics evidence.
-
proofpoint-get-top-clickersGets a list of the top clickers in the organization for a specified time period.
-
proofpoint-list-campaignsGets a list of IDs of campaigns active in a specified time period. Must provide either the interval or time_range arguments.
-
proofpoint-list-issuesGet events for clicks to malicious URLs permitted and messages delivered containing a known attachment threat within the specified time period. Must provide either the interval or time_range arguments.
-
proofpoint-list-most-attacked-usersGets a list of the most attacked users in the organization.
-
proofpoint-url-decodeDecodes URLs that have been rewritten by TAP to their original, target URL.
import json from datetime import datetime, timedelta, UTC import dateparser import demistomock as demisto import requests import urllib3 from CommonServerPython import * # Disable insecure warnings urllib3.disable_warnings() ALL_EVENTS = "All" ISSUES_EVENTS = "Issues" BLOCKED_CLICKS = "Blocked Clicks" PERMITTED_CLICKS = "Permitted Clicks" BLOCKED_MESSAGES = "Blocked Messages" DELIVERED_MESSAGES = "Delivered Messages" DEFAULT_LIMIT = 50 DEFAULT_LOOK_BACK_MINUTES = 30 DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ" MAX_SEEN_IDS = 10_000 def get_now(): """A wrapper function for datetime.now(timezone.utc) helps handle tests Returns: datetime: time right now in the UTC timezone (naive, for backward compatibility). """ return datetime.now(UTC).replace(tzinfo=None) def prune_seen_ids(seen_ids: dict[str, str], look_back_minutes: int) -> dict[str, str]: """Remove event IDs outside the lookback window. Apply hard cap if needed. Args: seen_ids: Mapping of event_id → interval_end_str (the end of the fetch interval in which the event was first seen) for deduplication. look_back_minutes: The lookback window in minutes. A 30-minute safety margin is added on top to tolerate clock skew and API indexing delay. Returns: Pruned dict with only IDs whose interval_end is within the lookback window + 30min margin. """ if not seen_ids: return seen_ids cutoff = (get_now() - timedelta(minutes=look_back_minutes + 30)).strftime(DATE_FORMAT) pruned = {event_id: interval_end for event_id, interval_end in seen_ids.items() if interval_end >= cutoff} if len(pruned) > MAX_SEEN_IDS: demisto.info(f"seen_ids exceeded {MAX_SEEN_IDS}, pruning oldest 25%") sorted_ids = sorted(pruned.items(), key=lambda x: x[1]) pruned = dict(sorted_ids[len(sorted_ids) // 4 :]) demisto.debug(f"Pruned seen_ids: {len(seen_ids)=}, {len(pruned)=}") return pruned def get_fetch_times(last_fetch, look_back_minutes: int = 0): """Generate time intervals for fetching events from Proofpoint TAP API. When `look_back_minutes` > 0, the effective fetch window between the start time (derived from `last_fetch`) and `now` is guaranteed to be at least `look_back_minutes` long. Equivalently: ``effective_start = now - max(now - last_fetch, look_back_minutes)``. - If ``now - last_fetch >= look_back_minutes``: leave the start unchanged (do NOT add `look_back_minutes` on top of an already-large gap). - If ``now - last_fetch < look_back_minutes``: shift the start back so that ``now - effective_start == look_back_minutes``, ensuring late-indexed events from the last `look_back_minutes` are re-scanned. Deduplication (handled by the caller) prevents duplicates produced by the overlapping region. Args: last_fetch (datetime or str): Starting time for fetch. May be shifted back so that the window length is at least `look_back_minutes`. look_back_minutes (int): Minimum length (in minutes) of the fetch window, used to re-scan for late-indexed events. Default is 0 (no look-back). Returns: List[tuple[str, str]]: List of (start_time, end_time) tuples in DATE_FORMAT. Each interval is ≤59 minutes and ≥30 seconds. Returns empty list if no valid intervals can be created. """ now = get_now() time_format = DATE_FORMAT if isinstance(last_fetch, str): last_fetch = datetime.strptime(last_fetch, time_format) # Ensure the window [effective_start, now] is at least `look_back_minutes` long. # Equivalent to: effective_start = now - max(now - last_fetch, look_back_minutes). # Only shift back when the existing gap is smaller than `look_back_minutes`; do not # subtract `look_back_minutes` on top of an already-sufficient gap. effective_start = last_fetch if look_back_minutes > 0: look_back_delta = timedelta(minutes=look_back_minutes) if (now - last_fetch) < look_back_delta: effective_start = now - look_back_delta # Guard against invalid intervals if effective_start >= now: demisto.debug(f"Skipping fetch. {effective_start=} >= {now=}") return [] intervals = [] current_start = effective_start # Create 59-minute intervals while now - current_start > timedelta(minutes=59): current_end = current_start + timedelta(minutes=59) intervals.append((current_start.strftime(time_format), current_end.strftime(time_format))) current_start = current_end # Add final interval (minimum 30 seconds) seconds_remaining = (now - current_start).total_seconds() if seconds_remaining >= 30: intervals.append((current_start.strftime(time_format), now.strftime(time_format))) demisto.debug(f"Final interval: {seconds_remaining:.0f} seconds") else: demisto.debug(f"Skipping final interval: only {seconds_remaining:.0f} seconds remaining (< 30s minimum)") demisto.debug( f"Generated {len(intervals)} intervals from {effective_start.strftime(time_format)} to {now.strftime(time_format)}" ) return intervals class Client: def __init__(self, proofpoint_url, api_version, verify, service_principal, secret, proxies): self.base_url = proofpoint_url self.api_version = api_version self.verify = verify self.service_principal = service_principal self.secret = secret self.proxies = proxies def http_request(self, method, url_suffix, params=None, data=None, forensics_api=False): if forensics_api: full_url = urljoin(self.base_url, "/v2/forensics") else: full_url = urljoin(urljoin(self.base_url, self.api_version), url_suffix) res = requests.request( method, full_url, verify=self.verify, params=params, json=data, auth=(self.service_principal, self.secret), proxies=self.proxies, ) if res.status_code not in [200, 204]: raise ValueError(f"Error in API call to Proofpoint TAP {res.status_code}. Reason: {res.text}") try: return res.json() except Exception: raise ValueError(f"Failed to parse http response to JSON format. Original response body: \n{res.text}") def get_events( self, interval=None, since_time=None, since_seconds=None, threat_type=None, threat_status=None, event_type_filter="All" ): if not interval and not since_time and not since_seconds: raise ValueError("Required to pass interval or sinceTime or sinceSeconds.") query_params = {"format": "json"} query_params.update( assign_params( interval=interval, sinceTime=since_time, sinceSeconds=since_seconds, threatStatus=threat_status, threatType=threat_type, ) ) url_route = { "All": "/all", "Issues": "/issues", "Blocked Clicks": "/clicks/blocked", "Permitted Clicks": "/clicks/permitted", "Blocked Messages": "/messages/blocked", "Delivered Messages": "/messages/delivered", }[event_type_filter] events = self.http_request("GET", urljoin("siem", url_route), params=query_params) return events def get_forensics(self, threat_id=None, campaign_id=None, include_campaign_forensics=None): if threat_id and campaign_id: raise DemistoException("threadId and campaignID supplied, supply only one of them") if include_campaign_forensics and campaign_id: raise DemistoException("includeCampaignForensics can be true only with threadId") if campaign_id: params = assign_params(campaignId=campaign_id) else: params = assign_params(threatId=threat_id, includeCampaignForensics=include_campaign_forensics) return self.http_request("GET", None, params=params, forensics_api=True) def get_clicks(self, clicks_type: str, interval: str, threat_status: str = None) -> dict: """ Retrieves clicks on malicious URLs in the specified time period. Clicks can either be blocked or permitted. Args: interval (str): ISO8601-formatted interval date. The minimum interval is 30 seconds. The maximum interval is one hour. threat_status (str): The status of the threat. Can be: active, cleared or falsePositive. clicks_type (str): The type of the click. Can be either "blocked" or "permitted". Returns: dict: API response from ProofpointTAP. """ params = remove_empty_elements({"interval": interval, "threatStatus": threat_status, "format": "json"}) return self.http_request("GET", f"/siem/clicks/{clicks_type}", params=params) def get_messages(self, messages_type: str, interval: str, threat_status: str = None, threat_type: str = None) -> dict: """ Retrieves events for messages in the specified time period. Messages can either be blocked or delivered. Args: interval (str): ISO8601-formatted interval date. The minimum interval is 30 seconds. The maximum interval is one hour. threat_status (str): The status of the threat. Can be: active, cleared or falsePositive. threat_type (str): The type of the threat. Can be: url, attachment or message. messages_type (str): The type of the messages. Can be either "blocked" or "delivered" Returns: dict: API response from ProofpointTAP. """ params = remove_empty_elements( {"interval": interval, "threatStatus": threat_status, "threatType": threat_type, "format": "json"} ) return self.http_request("GET", f"/siem/messages/{messages_type}", params=params) def list_campaigns(self, interval: str, page: str = None, limit: str = None) -> dict: """ Retrieves a list of IDs of campaigns active in a time window. Args: interval (str): ISO8601-formatted interval date. The minimum interval is 30 seconds. The maximum interval is one day. limit (str): The maximum number of campaign IDs to produce in the response. page (str): The page of results to return, in multiples of the specified size. Returns: dict: API response from ProofpointTAP. """ params = remove_empty_elements({"interval": interval, "page": page, "size": limit, "format": "json"}) return self.http_request("GET", "/campaign/ids", params=params) def get_campaign(self, campaign_id: str) -> dict: """ Retrieves information for a given campaign. Args: campaign_id (str): The ID of the required campaign. Returns: dict: API response from ProofpointTAP. """ return self.http_request("GET", f"/campaign/{campaign_id}") def list_most_attacked_users(self, window: str, limit: str = None, page: str = None) -> dict: """ Retrieves a list of the most attacked users in the organization for a given period. Args: window (str): The number of days for which the information will be retrieved. limit (str): The maximum number of VAPs to produce. page (str): The page of results to return, in multiples of the specified size. Returns: dict: API response from ProofpointTAP. """ params = remove_empty_elements({"window": window, "size": limit, "page": page}) return self.http_request("GET", "/people/vap", params=params) def get_top_clickers(self, window: str, limit: str = None, page: str = None) -> dict: """ Retrieves a list of the top clickers in the organization for a given period. Args: window (str): The number of days for which the information will be retrieved. limit (str): The maximum number of top clickers to produce. page (str): The page of results to return, in multiples of the specified size. Returns: dict: API response from ProofpointTAP. """ params = remove_empty_elements({"window": window, "size": limit, "page": page}) return self.http_request("GET", "/people/top-clickers", params=params) def url_decode(self, url_list: list) -> dict: """ Decode URLs that have been rewritten by TAP to their original, target URL. Args: url_list (list): List of encoded URLs. Returns: dict: API response from ProofpointTAP. """ data = {"urls": url_list} return self.http_request("POST", "/url/decode", data=data) def list_issues(self, interval: str, threat_status: str = None, threat_type: str = None) -> dict: """ Retrieves events for permitted clicks on malicious URLs and delivered messages in the specified time period. Args: interval (str): ISO8601-formatted interval date. The minimum interval is 30 seconds. The maximum interval is one hour. threat_status (str): The status of the threat. Can be: active, cleared or falsePositive. threat_type (str): The type of the threat. Can be: url, attachment or messageText. Returns: dict: API response from ProofpointTAP. """ params = remove_empty_elements( {"interval": interval, "threatStatus": threat_status, "threatType": threat_type, "format": "json"} ) return self.http_request("GET", "/siem/issues", params=params) def get_all_siem(self, format: str, since: int): return self.http_request("GET", "/siem/all", params={"format": format, "sinceSeconds": since}) def test_module(client: Client) -> str: """ Tests API connectivity and authentication. Args: client (Client): ProofpointTAP API client. Returns: str : 'ok' if test passed, anything else will fail the test. """ try: client.get_all_siem(format="JSON", since=60) except Exception as exception: if "Unauthorized" in str(exception) or "authentication" in str(exception): return "Authorization Error: make sure API Credentials are correctly set" if "connection" in str(exception): return "Connection Error: make sure Server URL is correctly set" raise exception return "ok" def build_context_attachment(what: dict) -> dict: return assign_params( SHA256=what.get("sha256"), MD5=what.get("md5"), Blacklisted=what.get("blacklisted"), Offset=what.get("offset"), Size=what.get("size"), ) def build_context_cookie(what: dict) -> dict: return assign_params( Action=what.get("action"), Domain=what.get("domain"), Key=what.get("key"), Value=what.get("value"), ) def build_context_dns(what: dict) -> dict: return assign_params( Host=what.get("host"), CNames=what.get("cnames"), IP=what.get("ips"), NameServers=what.get("nameservers"), NameServersList=what.get("nameserversList"), ) def build_context_mutex(what: dict) -> dict: return assign_params(Name=what.get("name"), Path=what.get("path")) def build_context_ids(what: dict) -> dict: return assign_params(Name=what.get("name"), SignatureID=what.get("signatureId")) def build_context_network(what: dict) -> dict: return assign_params(Action=what.get("action"), IP=what.get("ip"), Port=what.get("port"), Protocol=what.get("type")) def build_context_process(what: dict) -> dict: return assign_params( Action=what.get("action"), Path=what.get("path"), ) def build_context_dropper(what: dict) -> dict: return assign_params( Path=what.get("path"), URL=what.get("url"), Rule=what.get("rule"), ) def build_context_registry(what: dict) -> dict: return assign_params( Name=what.get("name"), Action=what.get("action"), Key=what.get("key"), Value=what.get("value"), ) def build_context_file(what: dict) -> dict: return assign_params( Path=what.get("path"), Action=what.get("action"), SHA256=what.get("sha256"), MD5=what.get("md5"), Size=what.get("size"), ) def build_context_url(what: dict) -> dict: return assign_params( URL=what.get("url"), Blacklisted=what.get("blacklisted"), SHA256=what.get("sha256"), MD5=what.get("md5"), Size=what.get("size"), HTTPStatus=what.get("httpStatus"), IP=what.get("ip"), ) def build_context_behavior(forensics_data: dict) -> dict: """ Build forensics behavior evidence type objects in order to update the command report context. Args: forensics_data (dict): Forensics data. A map of values associated with the specific evidence type. Returns: dict: Dictionary from given kwargs without empty values. """ return assign_params( Path=forensics_data.get("path"), URL=forensics_data.get("url"), ) def build_context_screenshot(forensics_data: dict) -> dict: """ Build forensics screenshot evidence type objects in order to update the command report context. Args: forensics_data (dict): Forensics data. A map of values associated with the specific evidence type. Returns: dict: Dictionary from given kwargs without empty values. """ return assign_params( URL=forensics_data.get("url"), ) def get_forensic_command(client: Client, args: dict) -> tuple[str, dict, dict]: """ Args: client: args: demisto.args() Returns: Outputs """ forensic_types = { "attachment": "Attachment", "cookie": "Cookie", "dns": "DNS", "dropper": "Dropper", "file": "File", "ids": "IDS", "mutex": "Mutex", "network": "Network", "process": "Process", "registry": "Registry", "url": "URL", "behavior": "Behavior", "screenshot": "Screenshot", } threat_id = args.get("threatId") campaign_id = args.get("campaignId") include_campaign_forensics = args.get("includeCampaignForensics") == "true" limit = args.get("limit", DEFAULT_LIMIT) raw_response = client.get_forensics( threat_id=threat_id, campaign_id=campaign_id, include_campaign_forensics=include_campaign_forensics ) reports = raw_response.get("reports", []) if len(reports) > limit: reports = reports[:limit] reports_context = [] for report in reports: report_context = assign_params(Scope=report.get("scope"), Type=report.get("type"), ID=report.get("id")) for evidence in report.get("forensics", []): evidence_type = evidence.get("type") evidence_type = forensic_types.get(evidence_type) if evidence_type: # Create list in report if evidence_type not in report_context: report_context[evidence_type] = [] what = evidence.get("what", {}) basic_report = assign_params( Time=evidence.get("time"), Display=evidence.get("display"), Malicious=evidence.get("malicious"), ) basic_report["Platform"] = [ {"Name": platform.get("name"), "OS": platform.get("os"), "Version": platform.get("version")} for platform in evidence.get("platforms", []) ] if evidence_type == "Attachment": basic_report.update(build_context_attachment(what)) report_context[evidence_type].append(basic_report) elif evidence_type == "Cookie": basic_report.update(build_context_cookie(what)) report_context[evidence_type].append(basic_report) elif evidence_type == "DNS": basic_report.update(build_context_dns(what)) report_context["DNS"].append(basic_report) elif evidence_type == "Dropper": basic_report.update(build_context_dropper(what)) report_context["Dropper"].append(basic_report) elif evidence_type == "File": basic_report.update(build_context_file(what)) report_context["File"].append(basic_report) elif evidence_type == "IDS": basic_report.update(build_context_ids(what)) report_context["IDS"].append(basic_report) elif evidence_type == "Mutex": basic_report.update(build_context_mutex(what)) report_context["Mutex"].append(basic_report) elif evidence_type == "Network": basic_report.update(build_context_network(what)) report_context["Network"].append(basic_report) elif evidence_type == "Process": basic_report.update(build_context_process(what)) report_context["Process"].append(basic_report) elif evidence_type == "Registry": basic_report.update(build_context_registry(what)) report_context["Registry"].append(basic_report) elif evidence_type == "URL": basic_report.update(build_context_url(what)) report_context["URL"].append(basic_report) elif evidence_type == "Behavior": basic_report.update(build_context_behavior(what)) report_context["Behavior"].append(basic_report) elif evidence_type == "Screenshot": basic_report.update(build_context_screenshot(what)) report_context["Screenshot"].append(basic_report) reports_context.append(report_context) outputs = {"Proofpoint.Report(var.ID === obj.ID)": reports_context} readable_outputs = tableToMarkdown( f"Forensic results from ProofPoint for ID: {threat_id or campaign_id}", reports_context, headers=["ID", "Scope", "Type"] ) return readable_outputs, outputs, raw_response @logger def get_events_command(client, args): interval = args.get("interval") threat_type = argToList(args.get("threatType")) threat_status = args.get("threatStatus") since_time = args.get("sinceTime") since_seconds = int(args.get("sinceSeconds")) if args.get("sinceSeconds") else None event_type_filter = args.get("eventTypes") raw_events = client.get_events(interval, since_time, since_seconds, threat_type, threat_status, event_type_filter) return ( tableToMarkdown("Proofpoint Events", raw_events), { "Proofpoint.MessagesDelivered(val.GUID == obj.GUID)": raw_events.get("messagesDelivered"), "Proofpoint.MessagesBlocked(val.GUID == obj.GUID)": raw_events.get("messagesBlocked"), "Proofpoint.ClicksBlocked(val.GUID == obj.GUID)": raw_events.get("clicksBlocked"), "Proofpoint.ClicksPermitted(val.GUID == obj.GUID)": raw_events.get("clicksPermitted"), }, raw_events, ) def _build_incident(raw_event: dict, event_type: str, occurred: str, raw_json_encoding: str | None = None) -> dict: """Build an incident dict from a raw event. Args: raw_event: The raw event data from Proofpoint API. event_type: Human-readable event type (e.g., "messages delivered"). occurred: The event timestamp string. raw_json_encoding: Optional encoding for the raw JSON. Returns: dict: Incident dict with name, rawJSON, and occurred fields. """ raw_event["type"] = event_type event_id = raw_event.get("id") or raw_event.get("GUID", "") if raw_json_encoding: raw_json = json.dumps(raw_event, ensure_ascii=False).encode(raw_json_encoding).decode() else: raw_json = json.dumps(raw_event) type_label = event_type.replace("_", " ").title() return { "name": f"Proofpoint - {type_label} - {event_id}", "rawJSON": raw_json, "occurred": occurred, } # Event type configuration: (response_key, event_type_label, dedup_field, time_field_or_None) # When time_field is None, use max(threatTime, clickTime) EVENT_TYPE_CONFIGS = [ ("messagesDelivered", "messages delivered", "GUID", "messageTime"), ("messagesBlocked", "messages blocked", "GUID", "messageTime"), ("clicksPermitted", "clicks permitted", "id", None), ("clicksBlocked", "clicks blocked", "id", None), ] def validate_first_fetch_time(first_fetch_time: str): """ validate that the start time is less than 7 days ago Args: first_fetch_time(str) - the start date time that needs to be validated. Returns: A valid datetime for the start_query_time """ dt_start_query_time = arg_to_datetime(first_fetch_time) or get_now() - timedelta(hours=1) seven_days_ago = get_now() - timedelta(days=7) if dt_start_query_time <= seven_days_ago: raise DemistoException( "The First fetch time range is more than 7 days ago. Please update this parameter since " "Proofpoint supports a maximum 1 week fetch back." ) else: demisto.debug(f"The {first_fetch_time=} is less than 7 days ago.") def fetch_incidents( client: Client, last_run, first_fetch_time, event_type_filter, threat_type, threat_status, limit=DEFAULT_LIMIT, integration_context=None, raw_json_encoding: str | None = None, look_back_minutes: int = 0, ) -> tuple[dict, list, list]: incidents = [] end_query_time = "" # Check if there are incidents saved in context (overflow from previous fetch) if integration_context: remained_incidents = integration_context.get("incidents") demisto.debug(f"remained_incidents: {len(remained_incidents) if remained_incidents else 0}") if remained_incidents: return last_run, remained_incidents[:limit], remained_incidents[limit:] # Load dedup state seen_ids: dict[str, str] = last_run.get("seen_ids", {}) demisto.debug(f"Loaded {len(seen_ids)} seen_ids from last_run") # Get the last fetch time, if exists start_query_time = last_run.get("last_fetch") is_first_fetch = not start_query_time # Handle first time fetch, fetch incidents retroactively if is_first_fetch: start_query_time, _ = parse_date_range(first_fetch_time, date_format=DATE_FORMAT, utc=True) # Look-back ramp-up for legacy / freshly-upgraded instances. # Relevant for v1.3.0 and above (introduced with the look-back feature in v1.3.0). # Purpose: gradually ramp up the look-back window for legacy / freshly-upgraded # instances so events are not re-fetched as duplicates. # NOTE: This block can (and should) be removed in the future once all existing # instances have completed the gradual ramp-up and it is no longer relevant. # ------------------------------------------------------------------ # Applying the full `look_back_minutes` immediately on an instance that has # no (or recently-initialized) `seen_ids` state would cause events from the # look-back window to be re-fetched as duplicates, because there is nothing # in `seen_ids` to dedupe against. # # First-time fetches do not need ramp-up (no prior state to duplicate). now = get_now() look_back_enabled_from_str = last_run.get("look_back_enabled_from") effective_look_back_minutes = look_back_minutes carry_enabled_from: str | None = None if look_back_minutes > 0 and not is_first_fetch: if "seen_ids" not in last_run and look_back_enabled_from_str is None: # Legacy instance: first fetch under the look-back feature. carry_enabled_from = now.strftime(DATE_FORMAT) effective_look_back_minutes = 0 demisto.debug( f"Legacy instance detected (last_fetch present but no seen_ids in last_run); " f"initializing look_back ramp-up from {carry_enabled_from} and skipping look_back " f"of {look_back_minutes} minutes for this fetch to avoid duplicates." ) elif look_back_enabled_from_str is not None: # Ramp-up in progress: grow effective look-back with elapsed wall-clock time. enabled_from_dt = datetime.strptime(look_back_enabled_from_str, DATE_FORMAT) elapsed_minutes = int((now - enabled_from_dt).total_seconds() // 60) ramp_minutes = max(0, min(look_back_minutes, elapsed_minutes)) effective_look_back_minutes = ramp_minutes if ramp_minutes < look_back_minutes: # Still ramping up — carry the stamp forward. carry_enabled_from = look_back_enabled_from_str demisto.debug( f"Look-back ramp-up active: enabled_from={look_back_enabled_from_str}, " f"elapsed={elapsed_minutes} min, effective look_back={ramp_minutes} " f"(target {look_back_minutes})." ) else: # Ramp-up complete — drop the stamp; steady-state full look-back from now on. demisto.debug( f"Look-back ramp-up complete (elapsed={elapsed_minutes} min " f">= {look_back_minutes} min target); using full look_back and clearing stamp." ) fetch_intervals = get_fetch_times(start_query_time, effective_look_back_minutes) # If no valid intervals, skip this fetch cycle if not fetch_intervals: demisto.debug("No fetch intervals generated - skipping this fetch cycle") return last_run, [], [] dedup_count = 0 for interval_start, interval_end in fetch_intervals: demisto.debug(f"Fetching interval: {interval_start} / {interval_end}") raw_events = client.get_events( interval=interval_start + "/" + interval_end, event_type_filter=event_type_filter, threat_status=threat_status, threat_type=threat_type, ) for response_key, event_type_label, dedup_field, time_field in EVENT_TYPE_CONFIGS: events = raw_events.get(response_key, []) if events: demisto.debug(f"Fetched {len(events)} {response_key} events") for raw_event in events: # Get the dedup key dedup_key = raw_event.get(dedup_field, "") # Skip if already seen (dedup) if dedup_key and dedup_key in seen_ids: demisto.debug( f"Dedup: skipping event {dedup_key} ({response_key}) — " f"already seen in interval ended by {seen_ids[dedup_key]}" ) dedup_count += 1 continue # Determine occurred time if time_field: occurred = raw_event.get(time_field, "") else: # Safely pick the latest of threatTime / clickTime, ignoring missing values candidate_times = [t for t in (raw_event.get("threatTime"), raw_event.get("clickTime")) if t] occurred = max(candidate_times) if candidate_times else "" if not occurred: demisto.debug(f"Event {dedup_key} ({response_key}) is missing an occurred time; using empty value") # Build incident incident = _build_incident(raw_event, event_type_label, occurred, raw_json_encoding) incidents.append(incident) # Track this event for dedup — store the end of the fetch interval if dedup_key: seen_ids[dedup_key] = interval_end if dedup_count > 0: demisto.debug(f"Deduplicated {dedup_count} events") # Prune old IDs outside the lookback window (always, to avoid unbounded growth of last_run) seen_ids = prune_seen_ids(seen_ids, look_back_minutes) # Advance last_fetch to end of last interval (real now, not shifted) end_query_time = fetch_intervals[-1][1] next_run: dict = { "last_fetch": end_query_time, "seen_ids": seen_ids, } # Carry the look-back ramp-up stamp forward while ramp-up is still in progress. if carry_enabled_from is not None: next_run["look_back_enabled_from"] = carry_enabled_from demisto.debug( f"Fetch summary: {len(fetch_intervals)} intervals, " f"{len(incidents)} total incidents, " f"returning {min(len(incidents), limit)}, " f"remaining {max(0, len(incidents) - limit)}, " f"seen_ids={len(seen_ids)}, " f"next last_fetch={end_query_time}" ) return next_run, incidents[:limit], incidents[limit:] def handle_interval(time_range: datetime, is_hours_interval: bool = True, is_days_interval: bool = False): """ Create a list of interval objects from the current time over time range. Most of ProofpointTAP requests required interval string in order to retrieve information from the API requests. interval objects will be in the following format: '2021-04-27T09:00:00Z/2021-04-27T10:00:00Z' Args: time_range (datetime): Last interval time. is_days_interval (bool): If True, create hours interval objects. is_hours_interval (bool): If True, create days interval objects. Returns: list: List of hour interval items. """ current_time = datetime.utcnow() intervals = [] if current_time - time_range > timedelta( days=7 ): # The maximum time range of Proofpoint TAP API requests is 7 days minus one minute. time_range += timedelta(minutes=1) if is_days_interval: while current_time - time_range > timedelta(days=1): start = time_range.strftime(DATE_FORMAT) time_range += timedelta(days=1) intervals.append(f"{start}/{time_range.strftime(DATE_FORMAT)}") if is_hours_interval: while current_time - time_range > timedelta(hours=1): start = time_range.strftime(DATE_FORMAT) time_range += timedelta(hours=1) intervals.append(f"{start}/{time_range.strftime(DATE_FORMAT)}") return intervals def get_clicks_command( client: Client, is_blocked: bool, interval: str = None, threat_status: str = None, time_range: str = None ) -> CommandResults: """ Retrieves clicks on malicious URLs in the specified time period. Clicks can either be blocked or permitted. Args: client (Client): ProofpointTAP API client. is_blocked (bool): Indicates the clicks type. interval (str): ISO8601-formatted interval date. The minimum interval is thirty seconds. The maximum interval is one hour. threat_status (str): The status of the threat. Can be: active, cleared or falsePositive. time_range (str): Time range, for example: 1 week, 2 days, 3 hours etc. Returns: CommandResults: raw response, outputs, and readable outputs. """ clicks_type = "blocked" if is_blocked else "permitted" if not (interval or time_range): raise Exception("Must provide interval or time_range.") if interval and time_range: raise Exception("Must provide only one of the arguments interval or time_range.") if time_range and dateparser.parse("7 days") > dateparser.parse(time_range): # type: ignore raise Exception("The maximum time range is 7 days") if time_range and dateparser.parse("30 seconds") < dateparser.parse(time_range): # type: ignore raise Exception("The minimum time range is thirty seconds.") if time_range and dateparser.parse("1 hour") < dateparser.parse(time_range): # type: ignore end = datetime.utcnow().strftime(DATE_FORMAT) start = dateparser.parse(time_range).strftime(DATE_FORMAT) # type: ignore intervals = [f"{start}/{end}"] else: intervals = handle_interval(dateparser.parse(time_range)) if time_range else [interval] # type: ignore outputs = [] raw_responses = [] for interval_string in intervals: raw_response = client.get_clicks(clicks_type, interval_string, threat_status) clicks_path = ["clicksBlocked"] if clicks_type == "blocked" else ["clicksPermitted"] if dict_safe_get(raw_response, clicks_path): outputs.extend(dict_safe_get(raw_response, clicks_path)) raw_responses.append(raw_response) readable_output = tableToMarkdown( f"{clicks_type.title()} Clicks", outputs, headers=[ "id", "senderIP", "recipient", "classification", "threatID", "threatURL", "threatStatus", "threatTime", "clickTime", "campaignId", "userAgent", ], headerTransform=pascalToSpace, ) return CommandResults( readable_output=readable_output, outputs_prefix=f"Proofpoint.Clicks{clicks_type.capitalize()}", outputs=outputs, outputs_key_field=["GUID", "id"], raw_response=raw_responses, ) def create_messages_output(messages_list: list) -> list: """ Creates and filters the required fields of messages output. Args: messages_list (list): List of retrieved messages. Returns: list: List of messages with the required fields. """ outputs = [] message_keys = [ "spamScore", "phishScore", "threatsInfoMap", "messageTime", "impostorScore", "malwareScore", "cluster", "subject", "quarantineFolder", "quarantineRule", "policyRoutes", "modulesRun", "messageSize", "messageParts", "completelyRewritten", "id", "sender", "recipient", "senderIP", "messageID", "GUID", ] header_fields = [ "headerFrom", "headerReplyTo", "fromAddress", "fromAddress", "ccAddresses", "replyToAddress", "toAddresses", "xmailer", ] for message in messages_list: message_header = {} for field in header_fields: message_header[field] = message[field] message_output = {key: value for key, value in message.items() if key in message_keys} message_output["Header"] = message_header outputs.append(message_output) return outputs def create_threats_objects(messages: list) -> list: """ Creates list of threats items of messages. Args: messages (list): List of messages items. Returns: list: List of threats items. """ threats_info_map = [] message_keys = ["sender", "recipient", "subject"] for message in messages: for threat in message.get("threatsInfoMap"): threat_object = {key: value for key, value in message.items() if key in message_keys} threat_object.update(threat) threats_info_map.append(threat_object) return threats_info_map def get_messages_command( client: Client, is_blocked: bool, interval: str = None, threat_status: str = None, threat_type: str = None, time_range: str = None, ) -> CommandResults: """ Retrieves events for messages in the specified time period. Messages can either be blocked or delivered. Args: client (Client): ProofpointTAP API client. is_blocked (bool): Indicates the messages type. interval (str): ISO8601-formatted interval date. The minimum interval is thirty seconds. The maximum interval is one hour. threat_status (str): The status of the threat. Can be: active, cleared or falsePositive. threat_type (str): The type of the threat. Can be: url, attachment or message. time_range (str): Time range, for example: 1 week, 2 days, 3 hours etc. Returns: CommandResults: raw response, outputs, and readable outputs. """ messages_type = "blocked" if is_blocked else "delivered" if not (interval or time_range): raise Exception("Must provide interval or time_range.") if interval and time_range: raise Exception("Must provide only one of the arguments interval or time_range.") if time_range and dateparser.parse("7 days") > dateparser.parse(time_range): # type: ignore raise Exception("The maximum time range is 7 days") if time_range and dateparser.parse("30 seconds") < dateparser.parse(time_range): # type: ignore raise Exception("The minimum time range is thirty seconds.") if time_range and dateparser.parse("1 hour") < dateparser.parse(time_range): # type: ignore end = datetime.utcnow().strftime(DATE_FORMAT) start = dateparser.parse(time_range).strftime(DATE_FORMAT) # type: ignore intervals = [f"{start}/{end}"] else: intervals = handle_interval(dateparser.parse(time_range)) if time_range else [interval] # type: ignore outputs = [] raw_responses = [] for interval_string in intervals: raw_response = client.get_messages(messages_type, interval_string, threat_status, threat_type) messages_path = ["messagesBlocked"] if messages_type == "blocked" else ["messagesDelivered"] if dict_safe_get(raw_response, messages_path): outputs.extend(create_messages_output(dict_safe_get(raw_response, messages_path))) raw_responses.append(raw_response) threats_info_map = create_threats_objects(outputs) messages_readable_output = tableToMarkdown( f"{messages_type.title()} Messages", outputs, headers=[ "senderIP", "sender", "recipient", "subject", "messageSize", "messageTime", "malwareScore", "phishScore", "spamScore", ], headerTransform=pascalToSpace, ) threats_info_readable_output = tableToMarkdown( f"{messages_type.title()} Messages Threats Information", threats_info_map, headers=[ "sender", "recipient", "subject", "classification", "threat", "threatStatus", "threatUrl", "threatID", "threatTime", "campaignID", ], headerTransform=pascalToSpace, ) readable_output = messages_readable_output + "\n" + threats_info_readable_output return CommandResults( readable_output=readable_output, outputs_prefix=f"Proofpoint.Messages{messages_type.capitalize()}", outputs=outputs, outputs_key_field=["GUID", "id"], raw_response=raw_responses, ) def list_campaigns_command( client: Client, interval: str = None, limit: str = None, page: str = None, time_range: str = None ) -> CommandResults: """ Retrieves a list of IDs of campaigns active in a time window. Args: client (Client): ProofpointTAP API client. interval (str): ISO8601-formatted interval date. The minimum interval is thirty seconds. The maximum interval is one day. limit (str): The maximum number of campaign IDs to produce in the response. page (str): The page of results to return, in multiples of the specified size. time_range (str): Time range, for example: 1 week, 2 days, 3 hours etc. Returns: CommandResults: raw response, outputs, and readable outputs. """ if not (interval or time_range): raise Exception("Must provide interval or time_range.") if interval and time_range: raise Exception("Must provide only one of the arguments interval or time_range.") if time_range and dateparser.parse("7 days") > dateparser.parse(time_range): # type: ignore raise Exception("The maximum time range is 7 days") if time_range and dateparser.parse("30 seconds") < dateparser.parse(time_range): # type: ignore raise Exception("The minimum time range is thirty seconds.") if time_range and dateparser.parse("1 hour") < dateparser.parse(time_range): # type: ignore end = datetime.utcnow().strftime(DATE_FORMAT) start = dateparser.parse(time_range).strftime(DATE_FORMAT) # type: ignore intervals = [f"{start}/{end}"] else: intervals = ( handle_interval( dateparser.parse(time_range), # type: ignore is_days_interval=True, ) if time_range else [ # type: ignore interval # type: ignore ] ) outputs = [] raw_responses = [] request_error = [] for interval_string in intervals: try: raw_response = client.list_campaigns(interval_string, page, limit) except ValueError: # In case there are no campaigns for the interval, the request returns status code 404 # which causes an error in http_request function request_error.append({"interval": interval_string, "message": f"Not found campaigns data from {interval_string}"}) continue if dict_safe_get(raw_response, ["campaigns"]): outputs.extend(dict_safe_get(raw_response, ["campaigns"])) raw_responses.append(raw_response) readable_output = tableToMarkdown("Campaigns List", outputs, headers=["id", "lastUpdatedAt"], headerTransform=pascalToSpace) if request_error: readable_output += "\n" + tableToMarkdown( "Errors", request_error, headers=["interval", "message"], headerTransform=pascalToSpace ) return CommandResults( readable_output=readable_output, outputs_prefix="Proofpoint.Campaign", outputs=outputs, outputs_key_field="id", raw_response=raw_responses, ) def get_campaign_command(client: Client, campaign_id: str) -> CommandResults | str: """ Retrieves information for a given campaign. Args: client (Client): ProofpointTAP API client. campaign_id (str): The ID of the required campaign. Returns: CommandResults: raw response, outputs, and readable outputs. """ try: raw_response = client.get_campaign(campaign_id) except ValueError: return "Campaign Id not found" campaign_general_fields = ["id", "name", "description", "startDate", "notable"] campaign_fields = ["families", "techniques", "actors", "brands", "malware"] outputs = {} outputs["campaignMembers"] = dict_safe_get(raw_response, ["campaignMembers"]) outputs["info"] = {key: value for key, value in raw_response.items() if key in campaign_general_fields} outputs.update({key: value for key, value in raw_response.items() if key in campaign_fields}) fields_readable_output = "" for field in campaign_fields: fields_readable_output += "\n" + tableToMarkdown( field.capitalize(), dict_safe_get(outputs, [field]), headers=["id", "name"], headerTransform=pascalToSpace ) campaign_info_output = tableToMarkdown( "Campaign Information", outputs["info"], headers=["id", "name", "description", "startDate", "notable"], headerTransform=pascalToSpace, ) campaign_members_output = tableToMarkdown( "Campaign Members", outputs["campaignMembers"], headers=["id", "threat", "type"], headerTransform=pascalToSpace ) readable_output = campaign_info_output + "\n" + campaign_members_output + fields_readable_output return CommandResults( readable_output=readable_output, outputs_prefix="Proofpoint.Campaign", outputs=outputs, outputs_key_field="id", raw_response=raw_response, ) def create_families_objects(users: list, statistics_key: str) -> list: """ Creates list of threat families items of users. Args: statistics_key (str): Dictionary key of users statistics. users (list): List of users items. Returns: list: List of threats items """ threat_families = [] for user in users: emails = dict_safe_get(user, ["identity", "emails"]) for family in dict_safe_get(user, [statistics_key, "families"]): families_object = {"Mailbox": emails, "Threat Family Name": family.get("name"), "Threat Score": family.get("score")} threat_families.append(families_object) return sorted(threat_families, key=lambda x: (x.get("Threat Score", 0), x.get("Mailbox")), reverse=True) def list_most_attacked_users_command(client: Client, window: str, limit: str = None, page: str = None) -> CommandResults: """ Retrieves a list of the most attacked users in the organization for a given period. Args: client (Client): ProofpointTAP API client. window (str): The number of days for which the information will be retrieved. limit (str): The maximum number of VAPs to produce. page (str): The page of results to return, in multiples of the specified size. Returns: CommandResults: raw response, outputs, and readable outputs. """ raw_response = client.list_most_attacked_users(window, limit, page) outputs = raw_response threat_families = create_families_objects(dict_safe_get(outputs, ["users"]), "threatStatistics") most_attacked_users_output = tableToMarkdown( "Most Attacked Users Information", outputs, headers=["totalVapUsers", "interval", "averageAttackIndex", "vapAttackIndexThreshold"], headerTransform=pascalToSpace, ) threat_families_output = tableToMarkdown( "Threat Families", threat_families, headers=["Mailbox", "Threat Family Name", "Threat Score"], headerTransform=pascalToSpace, ) readable_output = most_attacked_users_output + "\n" + threat_families_output return CommandResults( readable_output=readable_output, outputs_prefix="Proofpoint.Vap", outputs=outputs, raw_response=raw_response, outputs_key_field="interval", ) def get_top_clickers_command(client: Client, window: str, limit: str = None, page: str = None) -> CommandResults: """ Retrieves a list of the top clickers in the organization for a given period. Args: client (Client): ProofpointTAP API client. window (str): The number of days for which the information will be retrieved. limit (str): The maximum number of top clickers to produce. page (str): The page of results to return, in multiples of the specified size. Returns: CommandResults: raw response, outputs, and readable outputs. """ raw_response = client.get_top_clickers(window, limit, page) outputs = raw_response threat_families = create_families_objects(dict_safe_get(outputs, ["users"]), "clickStatistics") top_clickers_output = tableToMarkdown( "Top Clickers Users Information", outputs, headers=["totalTopClickers", "interval"], headerTransform=pascalToSpace ) threat_families_output = tableToMarkdown( "Threat Families", threat_families, headers=["Mailbox", "Threat Family Name", "Threat Score"], headerTransform=pascalToSpace, ) readable_output = top_clickers_output + threat_families_output return CommandResults( readable_output=readable_output, outputs_prefix="Proofpoint.Topclickers", outputs=outputs, raw_response=raw_response, outputs_key_field="interval", ) def url_decode_command(client: Client, urls: str) -> CommandResults: """ Decode URLs that have been rewritten by TAP to their original, target URL. Args: client (Client): ProofpointTAP API client. urls (str): Encoded URLs. Returns: CommandResults: raw response, outputs, and readable outputs. """ raw_response = client.url_decode(argToList(urls)) outputs = dict_safe_get(raw_response, ["urls"]) readable_output = tableToMarkdown( "URLs decoded information", outputs, headers=["encodedUrl", "decodedUrl"], headerTransform=pascalToSpace ) return CommandResults( readable_output=readable_output, outputs_prefix="Proofpoint.URL", outputs_key_field="encodedUrl", outputs=outputs, raw_response=raw_response, ) def list_issues_command( client: Client, interval: str = None, threat_status: str = None, threat_type: str = None, time_range: str = None ) -> list: """ Retrieves events for permitted clicks on malicious URLs and delivered messages in the specified time period. Args: client (Client): ProofpointTAP API client. interval (str): ISO8601-formatted interval date. The minimum interval is thirty seconds. The maximum interval is one hour. threat_status (str): The status of the threat. Can be: active, cleared or falsePositive. threat_type (str): The type of the threat. Can be: url, attachment or messageText. time_range (str): Time range, for example: 1 week, 2 days, 3 hours etc. Returns: list: List of CommandResults objects. """ if not (interval or time_range): raise Exception("Must provide interval or time_range.") if interval and time_range: raise Exception("Must provide only one of the arguments interval or time_range.") if time_range and dateparser.parse("7 days") > dateparser.parse(time_range): # type: ignore raise Exception("The maximum time range is 7 days") if time_range and dateparser.parse("30 seconds") < dateparser.parse(time_range): # type: ignore raise Exception("The minimum time range is thirty seconds.") if time_range and dateparser.parse("1 hour") < dateparser.parse(time_range): # type: ignore end = datetime.utcnow().strftime(DATE_FORMAT) start = dateparser.parse(time_range).strftime(DATE_FORMAT) # type: ignore intervals = [f"{start}/{end}"] else: intervals = handle_interval(dateparser.parse(time_range)) if time_range else [interval] # type: ignore messages_outputs = [] messages_raw_responses = [] clicks_outputs = [] clicks_raw_responses = [] command_results_list = [] for interval_string in intervals: raw_response = client.list_issues(interval_string, threat_status, threat_type) messages = dict_safe_get(raw_response, ["messagesDelivered"]) if messages: messages_outputs.extend(create_messages_output(messages)) messages_raw_responses.append(raw_response) clicks = dict_safe_get(raw_response, ["clicksPermitted"]) if clicks: clicks_outputs.extend(clicks) clicks_raw_responses.append(raw_response) threats_info_map = create_threats_objects(messages_outputs) delivered_messages_output = tableToMarkdown( "Delivered Messages", messages_outputs, headers=[ "senderIP", "sender", "recipient", "subject", "messageSize", "messageTime", "malwareScore", "phishScore", "spamScore", ], headerTransform=pascalToSpace, ) threats_info_output = tableToMarkdown( "Delivered Messages Threats Info Map:", threats_info_map, headers=[ "sender", "recipient", "subject", "classification", "threat", "threatStatus", "threatUrl", "threatID", "threatTime", "campaignID", ], headerTransform=pascalToSpace, ) messages_readable_output = delivered_messages_output + "\n" + threats_info_output command_results_list.append( CommandResults( readable_output=messages_readable_output, outputs_prefix="Proofpoint.MessagesDelivered", outputs=messages_outputs, outputs_key_field=["GUID", "id"], raw_response=messages_raw_responses, ) ) clicks_readable_output = tableToMarkdown( "Permitted click from list-issues command result:", clicks_outputs, headers=[ "id", "senderIP", "recipient", "classification", "threatID", "threatURL", "threatStatus", "threatTime", "clickTime", "campaignId", "userAgent", ], headerTransform=pascalToSpace, ) command_results_list.append( CommandResults( readable_output=clicks_readable_output, outputs_prefix="Proofpoint.ClicksPermitted", outputs=clicks_outputs, outputs_key_field=["GUID", "id"], raw_response=clicks_raw_responses, ) ) return command_results_list def main(): """ PARSE AND VALIDATE INTEGRATION PARAMS """ params = demisto.params() service_principal = params.get("credentials", {}).get("identifier") secret = params.get("credentials", {}).get("password") # Remove trailing slash to prevent wrong URL path to service server_url = params["url"][:-1] if (params["url"] and params["url"].endswith("/")) else params["url"] api_version = params.get("api_version") verify_certificate = not params.get("insecure", False) # How many time before the first fetch to retrieve incidents fetch_time = params.get("fetch_time", "60 minutes") threat_status = argToList(params.get("threat_status")) threat_type = argToList(params.get("threat_type")) event_type_filter = params.get("events_type") raw_json_encoding = params.get("raw_json_encoding") fetch_limit = min(int(params.get("limit", DEFAULT_LIMIT)), DEFAULT_LIMIT) # Get look-back buffer parameter (default 0 for backward compatibility) look_back_minutes = arg_to_number(params.get("look_back_minutes", DEFAULT_LOOK_BACK_MINUTES)) or DEFAULT_LOOK_BACK_MINUTES # Remove proxy if not set to true in params proxies = handle_proxy() command = demisto.command() args = demisto.args() demisto.info(f"Command being called is {command}") demisto.debug(f"{fetch_time=}, {look_back_minutes=}") try: client = Client(server_url, api_version, verify_certificate, service_principal, secret, proxies) commands = {"proofpoint-get-events": get_events_command, "proofpoint-get-forensics": get_forensic_command} if command == "test-module": validate_first_fetch_time(fetch_time) return_outputs(test_module(client)) elif demisto.command() == "fetch-incidents": integration_context = demisto.getIntegrationContext() next_run, incidents, remained_incidents = fetch_incidents( client=client, last_run=demisto.getLastRun(), first_fetch_time=fetch_time, event_type_filter=event_type_filter, threat_status=threat_status, threat_type=threat_type, limit=fetch_limit, integration_context=integration_context, raw_json_encoding=raw_json_encoding, look_back_minutes=look_back_minutes, ) # Save last_run, incidents, remained incidents into integration demisto.setLastRun(next_run) demisto.incidents(incidents) # preserve context dict demisto.setIntegrationContext({"incidents": remained_incidents}) elif command in commands: return_outputs(*commands[command](client, args)) elif command == "proofpoint-get-events-clicks-blocked": return_results(get_clicks_command(client, is_blocked=True, **args)) elif command == "proofpoint-get-events-clicks-permitted": return_results(get_clicks_command(client, is_blocked=False, **args)) elif command == "proofpoint-get-events-messages-blocked": return_results(get_messages_command(client, is_blocked=True, **args)) elif command == "proofpoint-get-events-messages-delivered": return_results(get_messages_command(client, is_blocked=False, **args)) elif command == "proofpoint-list-campaigns": return_results(list_campaigns_command(client, **args)) elif command == "proofpoint-get-campaign": return_results(get_campaign_command(client, **args)) elif command == "proofpoint-list-most-attacked-users": return_results(list_most_attacked_users_command(client, **args)) elif command == "proofpoint-get-top-clickers": return_results(get_top_clickers_command(client, **args)) elif command == "proofpoint-url-decode": return_results(url_decode_command(client, **args)) elif command == "proofpoint-list-issues": return_results(list_issues_command(client, **args)) except Exception as exception: if command == "test-module": return_error(str(exception)) return_error(f"Failed to execute {command} command. Error: {exception!s}") if __name__ in ["__main__", "builtin", "builtins"]: main()