Cofense Triage v2
Use the Cofense Triage integration to ingest reported phishing indicators.
Data Enrichment & Threat Intelligence · Cofense Triage
Details
| ID | Cofense Triage v2 |
|---|---|
| Provider | Cofense |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 5.0.0 |
| Docker Image | demisto/chromium:149.0.7827.10133006 |
| Supported Modules | Agentix XSIAM |
README
Use the Cofense Triage integration to ingest reported phishing indicators.
This integration was integrated and tested with version 1.20 of Cofense Triage v2
Configure Cofense Triage v2 in Cortex
| Parameter | Description | Required |
|---|---|---|
| host | Server URL (e.g., https://192.168.0.1) | True |
| user | User | True |
| token | API Token | True |
| isFetch | Fetch incidents | False |
| incidentType | Incident type | False |
| date_range | First fetch time (<number> <time unit>, e.g., 12 hours, 7 days, 3 months, 1 year) | False |
| category_id | Category ID to fetch | False |
| match_priority | Match Priority - the highest match priority based on rule hits for the report | False |
| tags | Tags - CSV list of tags of processed reports by which to filter | False |
| max_fetch | Maximum number of incidents to fetch each time | False |
| insecure | Trust any certificate (not secure) | False |
| proxy | Use system proxy settings | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
cofense-search-reports
Runs a query for reports.
Base Command
cofense-search-reports
Input
| Argument Name | Description | Required |
|---|---|---|
| file_hash | File hash, MD5 or SHA256. | Optional |
| url | The reported URLs. | Optional |
| subject | Report’s subject | Optional |
| reported_at | Retrieve reports that were reported after this time, for example: “2 hours, 4 minutes, 6 month, 1 day”. | Optional |
| created_at | Retrieve reports that were created after this time, for example: “2 hours, 4 minutes, 6 month, 1 day”. | Optional |
| reporter | Address or ID of the reporter. | Optional |
| max_matches | Maximum number of matches to fetch. Default is 30. | Optional |
| verbose | Returns all fields of a report. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.Report.ID | unknown | ID number of the report. |
| Cofense.Report.EmailAttachments | unknown | Email attachments. |
| Cofense.Report.EmailAttachments.id | unknown | Email attachment ID. |
| Cofense.Report.Tags | string | Report tags. |
| Cofense.Report.ClusterId | number | Cluster ID number. |
| Cofense.Report.CategoryId | number | Report category. |
| Cofense.Report.CreatedAt | date | Report creation date. |
| Cofense.Report.ReportedAt | string | Reporting time. |
| Cofense.Report.MatchPriority | number | The highest match priority based on rule hits for the report. |
| Cofense.Report.ReporterId | number | Reporter ID. |
| Cofense.Report.Location | string | Location of the report. |
| Cofense.Report.Reporter | string | Reporter email address. |
| Cofense.Report.SuspectFromAddress | string | Suspect from address. |
| Cofense.Report.ReportSubject | string | Report subject. |
| Cofense.Report.ReportBody | string | Report body. |
| Cofense.Report.Md5 | number | MD5 hash of the file. |
| Cofense.Report.Sha256 | unknown | SHA256 hash of the file. |
Command Example
!cofense-search-reports reported_at="7 days" created_at="7 days" max_matches="1"
Context Example
{
"Cofense": {
"Report": {
"CategoryId": 4,
"ClusterId": null,
"CreatedAt": "2020-06-04T13:42:26.173Z",
"EmailAttachments": [
{
"content_type": "image/png; name=image001.png",
"decoded_filename": "image001.png",
"email_attachment_payload": {
"id": 7095,
"md5": "5008fb6e6652f56cac5bdc5bf1cbe9c2",
"mime_type": "image/png; charset=binary",
"sha256": "554aeaaace31c7038a09dd408945583e1035ec124a46b04e5c6c5b148dc96f68"
},
"id": 18087,
"report_id": 13429,
"size_in_bytes": 1397
},
{
"content_type": "image/png; name=image003.png",
"decoded_filename": "image003.png",
"email_attachment_payload": {
"id": 7097,
"md5": "731ffb7846c22e41e9de8de307c93ece",
"mime_type": "image/png; charset=binary",
"sha256": "c911d07d1f7be624e00e44821148629d98cf6d0f2bfac112362c7c564522ea51"
},
"id": 18089,
"report_id": 13429,
"size_in_bytes": 1701
},
{
"content_type": "image/png; name=image006.png",
"decoded_filename": "image006.png",
"email_attachment_payload": {
"id": 7100,
"md5": "124bd437f87181fdfe3154b31fd2cf6b",
"mime_type": "image/png; charset=binary",
"sha256": "3d804c705545bf2a1e5ac6b0ea9b93a41ceb16d7453adebc58fba5df75335b20"
},
"id": 18092,
"report_id": 13429,
"size_in_bytes": 1994
},
{
"content_type": "image/png; name=image002.png",
"decoded_filename": "image002.png",
"email_attachment_payload": {
"id": 7096,
"md5": "cc07463ceeaaed79783a7f2a607797f9",
"mime_type": "image/png; charset=binary",
"sha256": "c6c2c95238f52648faaef4520fa9bba49c10ca0f1df9bfd1912be544f319b80b"
},
"id": 18088,
"report_id": 13429,
"size_in_bytes": 1430
},
{
"content_type": "image/png; name=image004.png",
"decoded_filename": "image004.png",
"email_attachment_payload": {
"id": 7098,
"md5": "95878e37974ed3cad67154d36dd58a9a",
"mime_type": "image/png; charset=binary",
"sha256": "e0d478f6ce56721867a0584ddea0016d713b9b2ab758fd0c9be3f1409d6e2634"
},
"id": 18090,
"report_id": 13429,
"size_in_bytes": 1557
},
{
"content_type": "image/png; name=image005.png",
"decoded_filename": "image005.png",
"email_attachment_payload": {
"id": 7099,
"md5": "0e911498bf4dc5eddb544ab5ece4b06a",
"mime_type": "image/png; charset=binary",
"sha256": "5f2046b3c55a874aadde052f9da4af3c17e2b5bf5baf704f58b1dd1eadf08544"
},
"id": 18091,
"report_id": 13429,
"size_in_bytes": 1609
},
{
"content_type": "application/pdf; name=\"XSOAR Attachment Test -Inquiry - Agent Tesla Keylogger.pdf\"",
"decoded_filename": "XSOAR Attachment Test -Inquiry - Agent Tesla Keylogger.pdf",
"email_attachment_payload": {
"id": 7110,
"md5": "fb7f083f4fb93a88ab8110d857312978",
"mime_type": "application/pdf; charset=binary",
"sha256": "15ab1b20ada04dfc6285caff5e4da4eab09a9157c2cbe32cd96113da6304a5ee"
},
"id": 18093,
"report_id": 13429,
"size_in_bytes": 49597
}
],
"ID": 13429,
"Location": "Processed",
"MatchPriority": 1,
"Md5": "d312e79695d5de744436006aab6b4ec1",
"ReportBody": "Testing PDF attachment\r\n\r\n\r\nTest User | Director\r\nTEST\r\nm. 123-456-7890\r\ne. test@test.com<mailto:test@test.com>\r\n\r\nConnect with Cofense:\r\n\r\n[signature_527626984]<https://cofense.com/>[signature_379086648]<https://facebook.com/cofense>[signature_426568440]<https://twitter.com/cofense>[signature_1467413640]<https://linkedin.com/company/cofense>[signature_749445379]<https://www.instagram.com/cofense/>[signature_1384270593]<https://www.themuse.com/profiles/cofense>\r\n\r\nUniting Humanity Against Phishing. Watch Our Video<https://cofense.com/project/uhap-video/>\r\n\r\n",
"ReportSubject": "2020-06-04 XSOAR attachment test",
"ReportedAt": "2020-06-04T13:40:29.000Z",
"ReporterId": 5331,
"Sha256": "ba77b5d984f7da97b6f96daa442535c79f47e4b6ea0055e3472b855ee8c244e4",
"Tags": []
}
}
}
Human Readable Output
Reports
Category Id Created At Email Attachments Id Location Match Priority Md5 Report Body Report Subject Reported At Reporter Id Sha256 4 2020-06-04T13:42:26.173Z {‘id’: 18087, ‘report_id’: 13429, ‘decoded_filename’: ‘image001.png’, ‘content_type’: ‘image/png; name=image001.png’, ‘size_in_bytes’: 1397, ‘email_attachment_payload’: {‘id’: 7095, ‘md5’: ‘5008fb6e6652f56cac5bdc5bf1cbe9c2’, ‘sha256’: ‘554aeaaace31c7038a09dd408945583e1035ec124a46b04e5c6c5b148dc96f68’, ‘mime_type’: ‘image/png; charset=binary’}},
{‘id’: 18089, ‘report_id’: 13429, ‘decoded_filename’: ‘image003.png’, ‘content_type’: ‘image/png; name=image003.png’, ‘size_in_bytes’: 1701, ‘email_attachment_payload’: {‘id’: 7097, ‘md5’: ‘731ffb7846c22e41e9de8de307c93ece’, ‘sha256’: ‘c911d07d1f7be624e00e44821148629d98cf6d0f2bfac112362c7c564522ea51’, ‘mime_type’: ‘image/png; charset=binary’}},
{‘id’: 18092, ‘report_id’: 13429, ‘decoded_filename’: ‘image006.png’, ‘content_type’: ‘image/png; name=image006.png’, ‘size_in_bytes’: 1994, ‘email_attachment_payload’: {‘id’: 7100, ‘md5’: ‘124bd437f87181fdfe3154b31fd2cf6b’, ‘sha256’: ‘3d804c705545bf2a1e5ac6b0ea9b93a41ceb16d7453adebc58fba5df75335b20’, ‘mime_type’: ‘image/png; charset=binary’}},
{‘id’: 18088, ‘report_id’: 13429, ‘decoded_filename’: ‘image002.png’, ‘content_type’: ‘image/png; name=image002.png’, ‘size_in_bytes’: 1430, ‘email_attachment_payload’: {‘id’: 7096, ‘md5’: ‘cc07463ceeaaed79783a7f2a607797f9’, ‘sha256’: ‘c6c2c95238f52648faaef4520fa9bba49c10ca0f1df9bfd1912be544f319b80b’, ‘mime_type’: ‘image/png; charset=binary’}},
{‘id’: 18090, ‘report_id’: 13429, ‘decoded_filename’: ‘image004.png’, ‘content_type’: ‘image/png; name=image004.png’, ‘size_in_bytes’: 1557, ‘email_attachment_payload’: {‘id’: 7098, ‘md5’: ‘95878e37974ed3cad67154d36dd58a9a’, ‘sha256’: ‘e0d478f6ce56721867a0584ddea0016d713b9b2ab758fd0c9be3f1409d6e2634’, ‘mime_type’: ‘image/png; charset=binary’}},
{‘id’: 18091, ‘report_id’: 13429, ‘decoded_filename’: ‘image005.png’, ‘content_type’: ‘image/png; name=image005.png’, ‘size_in_bytes’: 1609, ‘email_attachment_payload’: {‘id’: 7099, ‘md5’: ‘0e911498bf4dc5eddb544ab5ece4b06a’, ‘sha256’: ‘5f2046b3c55a874aadde052f9da4af3c17e2b5bf5baf704f58b1dd1eadf08544’, ‘mime_type’: ‘image/png; charset=binary’}},
{‘id’: 18093, ‘report_id’: 13429, ‘decoded_filename’: ‘XSOAR Attachment Test -Inquiry - Agent Tesla Keylogger.pdf’, ‘content_type’: ‘application/pdf; name=”XSOAR Attachment Test -Inquiry - Agent Tesla Keylogger.pdf”’, ‘size_in_bytes’: 49597, ‘email_attachment_payload’: {‘id’: 7110, ‘md5’: ‘fb7f083f4fb93a88ab8110d857312978’, ‘sha256’: ‘15ab1b20ada04dfc6285caff5e4da4eab09a9157c2cbe32cd96113da6304a5ee’, ‘mime_type’: ‘application/pdf; charset=binary’}}13429 Processed 1 d312e79695d5de744436006aab6b4ec1 Testing PDF attachment
Test User | Director
COFENSE
m. 123-456-7890
e. test@test.comtest@test.com
Connect with Cofense:
[signature_527626984]https://cofense.com/[signature_379086648]https://facebook.com/cofense[signature_426568440]https://twitter.com/cofense[signature_1467413640]https://linkedin.com/company/cofense[signature_749445379]https://www.instagram.com/cofense/[signature_1384270593]https://www.themuse.com/profiles/cofense
Uniting Humanity Against Phishing. Watch Our Videohttps://cofense.com/project/uhap-video/2020-06-04 XSOAR attachment test 2020-06-04T13:40:29.000Z 5331 ba77b5d984f7da97b6f96daa442535c79f47e4b6ea0055e3472b855ee8c244e4
cofense-search-inbox-reports
Runs a query for reports from the inbox mailbox.
Base Command
cofense-search-reports
Input
| Argument Name | Description | Required |
|---|---|---|
| file_hash | File hash, MD5 or SHA256. | Optional |
| url | The reported URLs. | Optional |
| subject | Report’s subject | Optional |
| reported_at | Retrieve reports that were reported after this time, for example: “2 hours, 4 minutes, 6 month, 1 day”. | Optional |
| created_at | Retrieve reports that were created after this time, for example: “2 hours, 4 minutes, 6 month, 1 day”. | Optional |
| reporter | Address or ID of the reporter. | Optional |
| max_matches | Maximum number of matches to fetch. Default is 30. | Optional |
| verbose | Returns all fields of a report. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.Report.ID | unknown | ID number of the report. |
| Cofense.Report.EmailAttachments | unknown | Email attachments. |
| Cofense.Report.EmailAttachments.id | unknown | Email attachment ID. |
| Cofense.Report.Tags | string | Report tags. |
| Cofense.Report.ClusterId | number | Cluster ID number. |
| Cofense.Report.CategoryId | number | Report category. |
| Cofense.Report.CreatedAt | date | Report creation date. |
| Cofense.Report.ReportedAt | string | Reporting time. |
| Cofense.Report.MatchPriority | number | The highest match priority based on rule hits for the report. |
| Cofense.Report.ReporterId | number | Reporter ID. |
| Cofense.Report.Location | string | Location of the report. |
| Cofense.Report.Reporter | string | Reporter email address. |
| Cofense.Report.SuspectFromAddress | string | Suspect from address. |
| Cofense.Report.ReportSubject | string | Report subject. |
| Cofense.Report.ReportBody | string | Report body. |
| Cofense.Report.Md5 | number | MD5 hash of the file. |
| Cofense.Report.Sha256 | unknown | SHA256 hash of the file. |
Command Example
!cofense-search-inbox-reports reported_at="7 days" created_at="7 days" max_matches="1"
Context Example
{
"Cofense": {
"Report": {
"CategoryId": 4,
"ClusterId": null,
"CreatedAt": "2020-06-04T13:42:26.173Z",
"EmailAttachments": [
{
"content_type": "image/png; name=image001.png",
"decoded_filename": "image001.png",
"email_attachment_payload": {
"id": 7095,
"md5": "5008fb6e6652f56cac5bdc5bf1cbe9c2",
"mime_type": "image/png; charset=binary",
"sha256": "554aeaaace31c7038a09dd408945583e1035ec124a46b04e5c6c5b148dc96f68"
},
"id": 18087,
"report_id": 13429,
"size_in_bytes": 1397
},
{
"content_type": "image/png; name=image003.png",
"decoded_filename": "image003.png",
"email_attachment_payload": {
"id": 7097,
"md5": "731ffb7846c22e41e9de8de307c93ece",
"mime_type": "image/png; charset=binary",
"sha256": "c911d07d1f7be624e00e44821148629d98cf6d0f2bfac112362c7c564522ea51"
},
"id": 18089,
"report_id": 13429,
"size_in_bytes": 1701
},
{
"content_type": "image/png; name=image006.png",
"decoded_filename": "image006.png",
"email_attachment_payload": {
"id": 7100,
"md5": "124bd437f87181fdfe3154b31fd2cf6b",
"mime_type": "image/png; charset=binary",
"sha256": "3d804c705545bf2a1e5ac6b0ea9b93a41ceb16d7453adebc58fba5df75335b20"
},
"id": 18092,
"report_id": 13429,
"size_in_bytes": 1994
},
{
"content_type": "image/png; name=image002.png",
"decoded_filename": "image002.png",
"email_attachment_payload": {
"id": 7096,
"md5": "cc07463ceeaaed79783a7f2a607797f9",
"mime_type": "image/png; charset=binary",
"sha256": "c6c2c95238f52648faaef4520fa9bba49c10ca0f1df9bfd1912be544f319b80b"
},
"id": 18088,
"report_id": 13429,
"size_in_bytes": 1430
},
{
"content_type": "image/png; name=image004.png",
"decoded_filename": "image004.png",
"email_attachment_payload": {
"id": 7098,
"md5": "95878e37974ed3cad67154d36dd58a9a",
"mime_type": "image/png; charset=binary",
"sha256": "e0d478f6ce56721867a0584ddea0016d713b9b2ab758fd0c9be3f1409d6e2634"
},
"id": 18090,
"report_id": 13429,
"size_in_bytes": 1557
},
{
"content_type": "image/png; name=image005.png",
"decoded_filename": "image005.png",
"email_attachment_payload": {
"id": 7099,
"md5": "0e911498bf4dc5eddb544ab5ece4b06a",
"mime_type": "image/png; charset=binary",
"sha256": "5f2046b3c55a874aadde052f9da4af3c17e2b5bf5baf704f58b1dd1eadf08544"
},
"id": 18091,
"report_id": 13429,
"size_in_bytes": 1609
},
{
"content_type": "application/pdf; name=\"XSOAR Attachment Test -Inquiry - Agent Tesla Keylogger.pdf\"",
"decoded_filename": "XSOAR Attachment Test -Inquiry - Agent Tesla Keylogger.pdf",
"email_attachment_payload": {
"id": 7110,
"md5": "fb7f083f4fb93a88ab8110d857312978",
"mime_type": "application/pdf; charset=binary",
"sha256": "15ab1b20ada04dfc6285caff5e4da4eab09a9157c2cbe32cd96113da6304a5ee"
},
"id": 18093,
"report_id": 13429,
"size_in_bytes": 49597
}
],
"ID": 13429,
"Location": "Inbox",
"MatchPriority": 1,
"Md5": "d312e79695d5de744436006aab6b4ec1",
"ReportBody": "Testing PDF attachment\r\n\r\n\r\nTest User | Director\r\nTEST\r\nm. 123-456-7890\r\ne. test@test.com<mailto:test@test.com>\r\n\r\nConnect with Cofense:\r\n\r\n[signature_527626984]<https://cofense.com/>[signature_379086648]<https://facebook.com/cofense>[signature_426568440]<https://twitter.com/cofense>[signature_1467413640]<https://linkedin.com/company/cofense>[signature_749445379]<https://www.instagram.com/cofense/>[signature_1384270593]<https://www.themuse.com/profiles/cofense>\r\n\r\nUniting Humanity Against Phishing. Watch Our Video<https://cofense.com/project/uhap-video/>\r\n\r\n",
"ReportSubject": "2020-06-04 XSOAR attachment test",
"ReportedAt": "2020-06-04T13:40:29.000Z",
"ReporterId": 5331,
"Sha256": "ba77b5d984f7da97b6f96daa442535c79f47e4b6ea0055e3472b855ee8c244e4",
"Tags": []
}
}
}
Human Readable Output
Reports
Category Id Created At Email Attachments Id Location Match Priority Md5 Report Body Report Subject Reported At Reporter Id Sha256 4 2020-06-04T13:42:26.173Z {‘id’: 18087, ‘report_id’: 13429, ‘decoded_filename’: ‘image001.png’, ‘content_type’: ‘image/png; name=image001.png’, ‘size_in_bytes’: 1397, ‘email_attachment_payload’: {‘id’: 7095, ‘md5’: ‘5008fb6e6652f56cac5bdc5bf1cbe9c2’, ‘sha256’: ‘554aeaaace31c7038a09dd408945583e1035ec124a46b04e5c6c5b148dc96f68’, ‘mime_type’: ‘image/png; charset=binary’}},
{‘id’: 18089, ‘report_id’: 13429, ‘decoded_filename’: ‘image003.png’, ‘content_type’: ‘image/png; name=image003.png’, ‘size_in_bytes’: 1701, ‘email_attachment_payload’: {‘id’: 7097, ‘md5’: ‘731ffb7846c22e41e9de8de307c93ece’, ‘sha256’: ‘c911d07d1f7be624e00e44821148629d98cf6d0f2bfac112362c7c564522ea51’, ‘mime_type’: ‘image/png; charset=binary’}},
{‘id’: 18092, ‘report_id’: 13429, ‘decoded_filename’: ‘image006.png’, ‘content_type’: ‘image/png; name=image006.png’, ‘size_in_bytes’: 1994, ‘email_attachment_payload’: {‘id’: 7100, ‘md5’: ‘124bd437f87181fdfe3154b31fd2cf6b’, ‘sha256’: ‘3d804c705545bf2a1e5ac6b0ea9b93a41ceb16d7453adebc58fba5df75335b20’, ‘mime_type’: ‘image/png; charset=binary’}},
{‘id’: 18088, ‘report_id’: 13429, ‘decoded_filename’: ‘image002.png’, ‘content_type’: ‘image/png; name=image002.png’, ‘size_in_bytes’: 1430, ‘email_attachment_payload’: {‘id’: 7096, ‘md5’: ‘cc07463ceeaaed79783a7f2a607797f9’, ‘sha256’: ‘c6c2c95238f52648faaef4520fa9bba49c10ca0f1df9bfd1912be544f319b80b’, ‘mime_type’: ‘image/png; charset=binary’}},
{‘id’: 18090, ‘report_id’: 13429, ‘decoded_filename’: ‘image004.png’, ‘content_type’: ‘image/png; name=image004.png’, ‘size_in_bytes’: 1557, ‘email_attachment_payload’: {‘id’: 7098, ‘md5’: ‘95878e37974ed3cad67154d36dd58a9a’, ‘sha256’: ‘e0d478f6ce56721867a0584ddea0016d713b9b2ab758fd0c9be3f1409d6e2634’, ‘mime_type’: ‘image/png; charset=binary’}},
{‘id’: 18091, ‘report_id’: 13429, ‘decoded_filename’: ‘image005.png’, ‘content_type’: ‘image/png; name=image005.png’, ‘size_in_bytes’: 1609, ‘email_attachment_payload’: {‘id’: 7099, ‘md5’: ‘0e911498bf4dc5eddb544ab5ece4b06a’, ‘sha256’: ‘5f2046b3c55a874aadde052f9da4af3c17e2b5bf5baf704f58b1dd1eadf08544’, ‘mime_type’: ‘image/png; charset=binary’}},
{‘id’: 18093, ‘report_id’: 13429, ‘decoded_filename’: ‘XSOAR Attachment Test -Inquiry - Agent Tesla Keylogger.pdf’, ‘content_type’: ‘application/pdf; name=”XSOAR Attachment Test -Inquiry - Agent Tesla Keylogger.pdf”’, ‘size_in_bytes’: 49597, ‘email_attachment_payload’: {‘id’: 7110, ‘md5’: ‘fb7f083f4fb93a88ab8110d857312978’, ‘sha256’: ‘15ab1b20ada04dfc6285caff5e4da4eab09a9157c2cbe32cd96113da6304a5ee’, ‘mime_type’: ‘application/pdf; charset=binary’}}13429 Processed 1 d312e79695d5de744436006aab6b4ec1 Testing PDF attachment
Test User | Director
TEST
m. 123-456-7890
e. test@test.comtest@test.com
Connect with Cofense:
[signature_527626984]https://cofense.com/[signature_379086648]https://facebook.com/cofense[signature_426568440]https://twitter.com/cofense[signature_1467413640]https://linkedin.com/company/cofense[signature_749445379]https://www.instagram.com/cofense/[signature_1384270593]https://www.themuse.com/profiles/cofense
Uniting Humanity Against Phishing. Watch Our Videohttps://cofense.com/project/uhap-video/2020-06-04 XSOAR attachment test 2020-06-04T13:40:29.000Z 5331 ba77b5d984f7da97b6f96daa442535c79f47e4b6ea0055e3472b855ee8c244e4
cofense-get-attachment
Retrieves an attachment by the attachment ID number.
Base Command
cofense-get-attachment
Input
| Argument Name | Description | Required |
|---|---|---|
| attachment_id | ID of the attachment. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| File.Size | number | File size. |
| File.Type | string | File type, for example: “PE”, “txt” |
| File.EntryID | string | The file entry ID. |
| File.Name | string | File name. |
| File.SHA1 | string | File SHA1 hash. |
| File.SHA256 | string | File SHA256 hash. |
| File.MD5 | string | File MD5 hash. |
Command Example
!cofense-get-attachment attachment_id="13311"
Context Example
{
"File": {
"EntryID": "603@cc18bdc4-7c64-494c-879c-23c3aee60818",
"Info": "text/plain",
"MD5": "97ee1d575640245abadbba15c0672eec",
"Name": "13311",
"SHA1": "13395876300d0a575812878446e15b9bbddda0b2",
"SHA256": "19d9c63bf4067a897950cfb72c14e8d05d8dcab0655979c6b60b925fb91e329f",
"SHA512": "31df48f235cc82247c6edc05850f910d6a057717d5d5f6ce84a4bc6c6fc3cc1f6ebae706ac592ace106b0559753928a838a1aee7018bec5b4316b90d95f55bcf",
"SSDeep": "24:nDBTBpJG4hbUWBFcXekJPkJ1WkJM8PWkJKckJvV/WskJvV28BesR1zvX0:nDNrHb1BWXekJPkJ1WkJfPWkJDkJvV/n",
"Size": 988,
"Type": "ASCII text, with CRLF line terminators"
}
}
Human Readable Output
cofense-get-reporter
Retrieves Email address of the reporter by ID
Base Command
cofense-get-reporter
Input
| Argument Name | Description | Required |
|---|---|---|
| reporter_id | ID of the reporter. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.Reporter.ID | number | ID of the reporter. |
| Cofense.Reporter.Email | string | Reporter email address. |
| Cofense.Reporter.CreatedAt | string | Reporter creation date. |
| Cofense.Reporter.UpdatedAt | string | Reporter last-updated date. |
| Cofense.Reporter.CredibilityScore | number | Reporter credibility score. |
| Cofense.Reporter.ReportsCount | number | Number of reports. |
| Cofense.Reporter.LastReportedAt | string | Date of most recent report. |
| Cofense.Reporter.VIP | bool | Whether Reporter is a VIP. |
Command Example
!cofense-get-reporter reporter_id="1"
Context Example
{
"Cofense": {
"Reporter": {
"CreatedAt": "2019-04-12T02:58:17.401Z",
"CredibilityScore": 0,
"Email": "ha.oullette@example.com",
"ID": 1,
"LastReportedAt": "2016-02-18T00:24:45.000Z",
"ReportsCount": 3,
"UpdatedAt": "2019-04-12T02:59:22.287Z",
"Vip": false
}
}
}
Human Readable Output
Integration log: cmel case attrs: {‘ID’: 1, ‘Email’: ‘ha.oullette@example.com’, ‘CreatedAt’: ‘2019-04-12T02:58:17.401Z’, ‘UpdatedAt’: ‘2019-04-12T02:59:22.287Z’, ‘CredibilityScore’: 0, ‘ReportsCount’: 3, ‘LastReportedAt’: ‘2016-02-18T00:24:45.000Z’, ‘Vip’: False}### Reporter Results:
Created At Credibility Score Id Last Reported At Reports Count Updated At Vip 2019-04-12T02:58:17.401Z 0 ha.oullette@example.com 1 2016-02-18T00:24:45.000Z 3 2019-04-12T02:59:22.287Z false
cofense-get-report-by-id
Retrieves a report by the report ID number.
Base Command
cofense-get-report-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| report_id | ID of the report | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.Report.ID | number | ID number of the report. |
| Cofense.Report.EmailAttachments | string | Email attachments. |
| Cofense.Report.EmailAttachments.id | string | Email attachment ID. |
| Cofense.Report.Tags | string | Report tags. |
| Cofense.Report.ClusterId | number | Cluster ID number. |
| Cofense.Report.CategoryId | number | Report category. |
| Cofense.Report.CreatedAt | string | Report creation date. |
| Cofense.Report.ReportedAt | string | Reporting time. |
| Cofense.Report.MatchPriority | number | The highest match priority based on rule hits for the report. |
| Cofense.Report.ReporterId | number | Reporter ID. |
| Cofense.Report.Location | string | Location of the report. |
| Cofense.Report.Reporter | string | Reporter email address. |
| Cofense.Report.SuspectFromAddress | string | Suspect from address. |
| Cofense.Report.ReportSubject | string | Report subject. |
| Cofense.Report.ReportBody | string | Report body. |
| Cofense.Report.Md5 | number | MD5 hash of the file. |
| Cofense.Report.Sha256 | unknown | SHA256 hash of the file. |
Command Example
!cofense-get-report-by-id report_id="5760"
Context Example
{
"Cofense": {
"Report": {
"CategoryId": 4,
"ClusterId": null,
"CreatedAt": "2019-04-17T20:53:02.090Z",
"EmailAttachments": [],
"ID": 5760,
"Location": "Processed",
"MatchPriority": 0,
"Md5": "f13bbc172fe7d394828ccabb25c3c99e",
"ReportSubject": "test@test.net Reset password instruction",
"ReportedAt": "2019-04-17T16:54:57.000Z",
"ReporterId": 3280,
"Sha256": "4f6bc0d9c1217a2a6f327423e16b7a6e9294c68cfb33864541bd805fe4ab2d72",
"Tags": []
}
}
}
Human Readable Output
{“HumanReadable”:”### Cofense HTML Report:\nHTML report download request has been completed”,”name”:”5760-report.html”,”path”:”aaf1160b-9176-45d9-aab9-90efd278e05d”}### Report Summary:
Category Id Created At Id Location Match Priority Md5 Report Subject Reported At Reporter Id Sha256 4 2019-04-17T20:53:02.090Z 5760 Processed 0 f13bbc172fe7d394828ccabb25c3c99e test@test.nul Reset password instruction 2019-04-17T16:54:57.000Z 3280 4f6bc0d9c1217a2a6f327423e16b7a6e9294c68cfb33864541bd805fe4ab2d72
cofense-get-report-png-by-id
Retrieves a report by the report ID number and displays as PNG
Base Command
cofense-get-report-png-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| report_id | Report ID PNG output | Required |
| set_white_bg | Change background to white | Optional |
Context Output
There is no context output for this command.
Command Example
!cofense-get-report-png-by-id report_id="5760" set_white_bg="True"
Context Example
{
"InfoFile": {
"EntryID": "616@cc18bdc4-7c64-494c-879c-23c3aee60818",
"Extension": "png",
"Info": "image/png",
"Name": "cofense_report_5760.png",
"Size": 40692,
"Type": "PNG image data, 400 x 369, 8-bit/color RGBA, non-interlaced"
}
}
Human Readable Output
Cofense: PNG of Report 5760
cofense-get-threat-indicators
Threat Indicators that are designated by analysts as malicious, suspicious or benign
Base Command
cofense-get-threat-indicators
Input
| Argument Name | Description | Required |
|---|---|---|
| type | indicator type | Optional |
| level | indicator severity | Optional |
| start_date | designated start date tagged by analyst (format example: YYYY-MM-DD+HH:MM:SS). Default: 6 days ago. | Optional |
| end_date | designated end date from assignment (format example: YYYY-MM-DD+HH:MM:SS). Default: current date. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Cofense.ThreatIndicators | unknown | Threat indicator output |
| Cofense.ThreatIndicators.ID | number | Threat indicator ID in Cofense Triage. |
| Cofense.ThreatIndicators.OperatorId | number | Cofense Triage operator who designated the threat indicator. |
| Cofense.ThreatIndicators.ReportId | number | Associated Report in Cofense Triage. |
| Cofense.ThreatIndicators.ThreatKey | string | Threat indicator type. |
| Cofense.ThreatIndicators.ThreatLevel | string | Threat indicator level. |
| Cofense.ThreatIndicators.ThreatValue | string | Value of the threat indicator. |
Command Example
!cofense-get-threat-indicators type="URL" level="Malicious" start_date="2020-05-28"
Context Example
{
"Cofense": {
"ThreatIndicators": {
"CreatedAt": "2020-05-28T22:14:52.690Z",
"ID": 75,
"OperatorId": 2,
"ReportId": 5760,
"ThreatKey": "URL",
"ThreatLevel": "Malicious",
"ThreatValue": "http://bold-air0example.com/notification.php?email=test@test.net"
}
}
}
Human Readable Output
Threat Indicators
Created At Id Operator Id Report Id Threat Key Threat Level Threat Value 2020-05-28T22:14:52.690Z 75 2 5760 URL Malicious http://bold-air0example.com/notification.php?email=test@test.net
Configuration parameters
host— Server URL (e.g., https://192.168.0.1) (required)user— User (required)token— API Token (required)isFetch— Fetch incidentsincidentType— Incident typeincidentFetchInterval— Incidents Fetch Intervalmailbox_location— Mailbox Location (required)date_range— First fetch time (<number> <time unit>, e.g., 12 hours, 7 days, 3 months, 1 year)category_id— Category ID to fetchmatch_priority— Match Priority - the highest match priority based on rule hits for the reporttags— Tags - CSV list of tags of processed reports by which to filtermax_fetch— Maximum number of incidents to fetch each timeinsecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (7)
-
cofense-get-attachmentRetrieves an attachment by the attachment ID number.
-
cofense-get-report-by-idRetrieves a report by the report ID number.
-
cofense-get-report-png-by-idRetrieves a report by the report ID number and displays as PNG.
-
cofense-get-reporterRetrieves Email address of the reporter by ID.
-
cofense-get-threat-indicatorsThreat Indicators that are designated by analysts as malicious, suspicious or benign.
-
cofense-search-inbox-reportsRuns a query for reports from the `inbox` mailbox.
-
cofense-search-reportsRuns a query for reports.
import functools import itertools import json import math from datetime import datetime, timezone from io import BytesIO import demistomock as demisto import urllib3 from CommonServerPython import * from PIL import Image from urllib3.exceptions import InsecureRequestWarning urllib3.disable_warnings(category=InsecureRequestWarning) TERSE_FIELDS = [ "id", "cluster_id", "reporter_id", "location", "created_at", "reported_at", "report_subject", "report_body", "md5", "sha256", "category_id", "match_priority", "tags", "email_attachments", ] class TriageRequestFailedError(Exception): """Triage responded with something other than a normal 200 response""" def __init__(self, status_code, message): super().__init__(self, status_code, message) self.status_code = status_code self.message = message def __str__(self): return f"Call to Cofense Triage failed ({self.status_code}): {self.message}" class TriageRequestEmptyResponse(Exception): """Triage responded without error, but the result set was unexpectedly empty""" def __init__(self, record_id, record_type): super().__init__(self, record_id, record_type) self.record_id = record_id self.record_type = record_type def __str__(self): return f"Could not find a {self.record_type} with id {self.record_id}" class TriageNoReportersFoundError(Exception): """Triage returned empty results, but the integration expected at least one""" class TriageInstance: def __init__(self, *, host, token, user, disable_tls_verification=False, demisto_params): self.host = host self.token = token self.user = user self.disable_tls_verification = disable_tls_verification self.demisto_params = demisto_params def request(self, endpoint, params=None, body=None, raw_response=False): """ Make a request to the configured Triage instance and return the result. """ response = requests.get( self.api_url(endpoint), headers={ "Authorization": f"Token token={self.user}:{self.token}", "Accept": "application/json", }, params=params, data=body, verify=not self.disable_tls_verification, ) if not response.ok: raise TriageRequestFailedError(response.status_code, response.text) if response.status_code == 206: # 206 indicates Partial Content. The reason will be in the warning header. demisto.debug(str(response.headers)) if raw_response: return response if not response.text or response.text == "[]": return {} try: return response.json() # when installing simplejson the type of exception is requests.exceptions.JSONDecodeError when it is not # possible to load json. except (json.decoder.JSONDecodeError, requests.exceptions.JSONDecodeError) as ex: demisto.debug(str(ex)) raise TriageRequestFailedError(response.status_code, "Could not parse result from Cofense Triage") def api_url(self, endpoint): """Return a full URL for the configured Triage host and the specified endpoint""" endpoint = endpoint.lstrip("/") return f"{self.host}/api/public/v1/{endpoint}" def get_demisto_param(self, name): return self.demisto_params[name] class TriageReport: """ Class representing a Triage report by an end-user of a suspicious message Model associations: TriageReporter - The user who reported the message. A TriageReport has exactly one TriageReporter. """ def __init__(self, triage_instance, attrs): self.triage_instance = triage_instance self.attrs = attrs @property def id(self): return self.attrs["id"] @property def date(self): return self.attrs.get("created_at") @property def category_name(self): return { 1: "Non-Malicious", 2: "Spam", 3: "Crimeware", 4: "Advanced Threats", 5: "Phishing Simulation", }.get(self.attrs["category_id"], "Unknown") @property def severity(self): # Demisto's severity levels are 4 - Critical, 3 - High, 2 - Medium, 1 - Low, 0 - Unknown return { 1: 1, # non malicious -> low 2: 0, # spam -> unknown 3: 2, # crimeware -> medium 4: 2, # advanced threats -> medium 5: 1, # phishing simulation -> low }.get(self.attrs["category_id"], 0) @property def report_subject(self): return self.attrs.get("report_subject") @property def report_body(self): return self.attrs.get("report_body") @property def email_urls(self): return [email_url["url"] for email_url in self.attrs["email_urls"]] @property def email_attachment_hashes(self): return [ [ att["email_attachment_payload"]["md5"], att["email_attachment_payload"]["sha256"], ] for att in self.attrs["email_attachments"] ] @property # type: ignore @functools.lru_cache def reporter(self): return TriageReporter(self.triage_instance, self.attrs["reporter_id"]) @property def terse_attrs(self): return {key: self.attrs[key] for key in self.attrs.keys() & TERSE_FIELDS} def to_dict(self): return { **self.attrs, # Flatten the Reporter object to a set of `reporter_` prefixed attributes **{f"reporter_{k}": v for k, v in self.reporter.attrs.items()}, # type: ignore } def to_json(self): return json.dumps(self.to_dict()) @property # type: ignore @functools.lru_cache def attachment(self): if "HTML" in self.report_body: html_attachment = fileResult(filename=f"{self.id}-report.html", data=self.report_body.encode()) attachment = { "path": html_attachment.get("FileID"), "name": html_attachment.get("File"), } return attachment return None @classmethod def fetch(cls, triage_instance, report_id): return cls(triage_instance, triage_instance.request(f"reports/{report_id}")[0]) class TriageInboxReports: """Represents a set of Triage reports from the `inbox` mailbox""" def __init__( self, triage_instance, *, start_date=None, end_date=None, filter_params={}, max_pages=1, ): self.triage_instance = triage_instance self.start_date = start_date self.end_date = end_date self.filter = TriageInboxReportFilter(filter_params) self.max_pages = max_pages def inbox_reports(self): inbox_reports = [TriageReport(self.triage_instance, response) for response in self.fetch_reports()] return [report for report in inbox_reports if self.filter.is_match(report)] def fetch_reports(self): return itertools.chain.from_iterable(self.fetch_report_pages()) def fetch_report_pages(self): return [ self.triage_instance.request( "inbox_reports", params={ "start_date": self.start_date, "end_date": self.end_date, "page": page_num, }, ) for page_num in range(math.ceil(self.max_pages)) ] class TriageInboxReportFilter: """Performs filtering for Triage Reports""" def __init__(self, filter_params): self.subject = filter_params.get("subject") self.url = filter_params.get("url") self.file_hash = filter_params.get("file_hash") self.reporter_ids = filter_params.get("reporter_ids") def is_match(self, report): return ( (not self.subject or self.subject in report.report_subject) and (not self.url or any(self.url in email_url for email_url in report.email_urls)) and (not self.file_hash or any(self.file_hash in h for h in report.email_attachment_hashes)) and (not self.reporter_ids or report.reporter.id in self.reporter_ids) ) class TriageReporters: """ A set of Triage reporters """ def __init__(self, triage_instance, *, email=None, max_pages=1): self.triage_instance = triage_instance self.email = email self.max_pages = max_pages def reporters(self): return [ TriageReporter( self.triage_instance, response["id"] ) # TODO causes unnecessary extra request---we can just pass in `response`, which has all the fields already # noqa: E501 for response in self.fetch_reporters() ] def fetch_reporters(self): return itertools.chain.from_iterable(self.fetch_reporter_pages()) def fetch_reporter_pages(self): for page_num in range(math.ceil(self.max_pages)): yield self.triage_instance.request("reporters", params={"email": self.email, "page": page_num}) class TriageReporter: """ Class representing an end user who has reported a suspicious message Model associations: TriageReport - A reporter submitted by this user. A TriageReporter may have many TriageReports. """ def __init__(self, triage_instance, reporter_id): """Fetch data for the first matching reporter from Triage""" matching_reporters = triage_instance.request(f"reporters/{reporter_id}") if matching_reporters: self.attrs = matching_reporters[0] else: self.attrs = {} @property def id(self): return self.attrs["id"] @property def email(self): return self.attrs["email"] def exists(self): return bool(self.attrs) def snake_to_camel_keys(snake_list: list[dict]) -> list[dict]: def snake_to_camel(snake_str) -> str: if snake_str == "id": return "ID" components = snake_str.split("_") return "".join(x.title() for x in components) return [{snake_to_camel(k): v for k, v in snake_d.items()} for snake_d in snake_list] def split_snake(string: str) -> str: return string.replace("_", " ").title() def parse_triage_date(date: str): # datetime from isoformat only supports a subset of ISO-8601. # See https://discuss.python.org/t/parse-z-timezone-suffix-in-datetime/2220 if date.endswith("Z"): date = date[:-1] + "+00:00" return datetime.fromisoformat(date) def test_function(triage_instance) -> None: try: response = triage_instance.request("processed_reports") if response: demisto.results("ok") else: raise TriageRequestFailedError( response.status_code, "API call to Cofense Triage failed. Please check integration configuration.\nReason: {response.reason}", ) except Exception as err: demisto.debug(str(err)) raise err def fetch_reports(triage_instance) -> None: """Fetch up to `max_reports` reports since the last time the command was run.""" start_date = triage_instance.get_demisto_param("start_date") max_fetch = triage_instance.get_demisto_param("max_fetch") if triage_instance.get_demisto_param("mailbox_location") == "Inbox_Reports": endpoint = "inbox_reports" else: endpoint = "processed_reports" triage_response = triage_instance.request( endpoint, params={ "category_id": triage_instance.get_demisto_param("category_id"), "match_priority": triage_instance.get_demisto_param("match_priority"), "tags": triage_instance.get_demisto_param("tags"), "start_date": start_date, }, ) already_fetched = set(json.loads(demisto.getLastRun().get("reports_fetched", "[]"))) triage_reports = [TriageReport(triage_instance, report) for report in triage_response if report["id"] not in already_fetched] incidents = [] for report in triage_reports: incident = { "name": f"cofense triage report {report.id}: {report.category_name}", "occurred": report.date, "rawJSON": report.to_json(), "severity": report.severity, } if report.attachment: incident["attachment"] = [report.attachment] incidents.append(incident) already_fetched.add(report.id) if len(incidents) >= max_fetch: break demisto.incidents(incidents) demisto.setLastRun({"reports_fetched": json.dumps(list(already_fetched))}) def search_reports_command(triage_instance) -> None: subject = demisto.getArg("subject") # type: str url = demisto.getArg("url") # type: str file_hash = demisto.getArg("file_hash") # type: str reported_at = parse_date_range(demisto.args().get("reported_at", "7 days"))[0].replace(tzinfo=timezone.utc) # noqa: UP017 created_at = parse_date_range(demisto.args().get("created_at", "7 days"))[0].replace(tzinfo=timezone.utc) # noqa: UP017 try: max_matches = int(demisto.getArg("max_matches")) # type: int except ValueError: return_error("max_matches must be an integer if specified") return verbose = demisto.getArg("verbose") == "true" try: reporters_clause = build_reporters_clause(triage_instance) except TriageNoReportersFoundError: return_outputs("Reporter not found.", {}, {}) return results = search_reports( triage_instance, subject, url, file_hash, reported_at, created_at, reporters_clause, verbose, max_matches, ) if results: ec = {"Cofense.Report(val.ID && val.ID == obj.ID)": snake_to_camel_keys(results)} hr = tableToMarkdown("Reports:", results, headerTransform=split_snake, removeNull=True) return_outputs(hr, ec, results) else: return_outputs("no results were found.", {}, {}) def search_reports( triage_instance, subject=None, url=None, file_hash=None, reported_at=None, created_at=None, reporters_clause={}, verbose=False, max_matches=30, ) -> list: params = {"start_date": reported_at, **reporters_clause} reports = triage_instance.request("processed_reports", params=params) matches = [] for report in reports: if subject and subject != report.get("report_subject"): continue if url and url not in [email_url["url"] for email_url in report["email_urls"]]: continue if created_at and "created_at" in report and created_at >= parse_triage_date(report["created_at"]): continue if ( file_hash and file_hash not in [attachment["email_attachment_payload"]["md5"] for attachment in report["email_attachments"]] and file_hash not in [attachment["email_attachment_payload"]["sha256"] for attachment in report["email_attachments"]] ): continue if not verbose: # extract only relevant fields report = {key: report[key] for key in report.keys() & TERSE_FIELDS} matches.append(report) if len(matches) >= max_matches: break return matches def search_inbox_reports_command(triage_instance) -> None: reported_at = parse_date_range(demisto.args().get("reported_at", "7 days"))[0].replace(tzinfo=timezone.utc) # noqa: UP017 try: reporters_clause = build_reporters_clause(triage_instance) except TriageNoReportersFoundError: return_outputs("Reporter not found.", {}, {}) return try: max_matches = int(demisto.getArg("max_matches")) or 10 except ValueError: return_error("max_matches must be an integer if specified") return max_pages = math.ceil(max_matches / 10) # Triage's number of items per page, rounded up reports = TriageInboxReports( triage_instance, start_date=reported_at, filter_params={ "subject": demisto.getArg("subject"), "url": demisto.getArg("url"), "file_hash": demisto.getArg("file_hash"), **reporters_clause, }, max_pages=max_pages, ).inbox_reports() if not reports: return_outputs("No results found.", {}, {}) return reports_dict = [report.to_dict() for report in reports][:max_matches] ec = {"Cofense.Report(val.ID && val.ID == obj.ID)": snake_to_camel_keys(reports_dict)} hr = tableToMarkdown("Reports:", reports_dict, headerTransform=split_snake, removeNull=True) return_outputs(hr, ec, reports_dict) def build_reporters_clause(triage_instance): reporter_address_or_id = demisto.getArg("reporter") if not reporter_address_or_id: return {} if reporter_address_or_id.isdigit(): return {"reporter_ids": [int(reporter_address_or_id)]} reporters = TriageReporters(triage_instance, email=reporter_address_or_id).reporters() if len(reporters) == 0 or not any(reporter.exists() for reporter in reporters): raise TriageNoReportersFoundError return {"reporter_ids": [reporter.id for reporter in reporters]} def get_all_reporters(triage_instance, time_frame) -> list: res = triage_instance.request("reporters", params={"start_date": time_frame}) if not isinstance(res, list): res = [res] reporters = [reporter.get("email") for reporter in res] return reporters def get_reporter_command(triage_instance) -> None: reporter_id = demisto.getArg("reporter_id") reporter = TriageReporter(triage_instance, reporter_id) if not reporter.exists(): return return_outputs( readable_output="Could not find reporter with matching ID", outputs=reporter_id, raw_response=json.dumps(reporter.attrs), ) camel_case_attrs = snake_to_camel_keys([reporter.attrs])[0] return_outputs( outputs={"Cofense.Reporter(val.Id && val.Id == obj.Id)": camel_case_attrs}, readable_output=tableToMarkdown( "Reporter Results:", reporter.attrs, headerTransform=split_snake, removeNull=True, ), raw_response=json.dumps(reporter.attrs), ) return None def get_attachment_command(triage_instance) -> None: attachment_id = str(demisto.getArg("attachment_id")) # type: str file_name = demisto.getArg("file_name") or attachment_id # type: str res = triage_instance.request(f"attachment/{attachment_id}", raw_response=True) result = fileResult(file_name, res.content) demisto.results(result) def get_report_by_id_command(triage_instance) -> None: report_id = int(demisto.getArg("report_id")) # type: int verbose = demisto.getArg("verbose") == "true" report = TriageReport.fetch(triage_instance, report_id) if not report: raise TriageRequestEmptyResponse(report_id, "Report") if verbose: report_attrs = report.attrs else: report_attrs = report.terse_attrs if report.attachment: demisto.results( { **report.attachment, "HumanReadable": "### Cofense HTML Report:\nHTML report download request has been completed", } ) del report_attrs["report_body"] hr = tableToMarkdown("Report Summary:", report_attrs, headerTransform=split_snake, removeNull=True) ec = {"Cofense.Report(val.ID && val.ID == obj.ID)": snake_to_camel_keys([report_attrs])} return_outputs(readable_output=hr, outputs=ec, raw_response=report.to_json()) def get_threat_indicators_command(triage_instance) -> None: results = triage_instance.request( "triage_threat_indicators", params={ "type": demisto.getArg("type"), "level": demisto.getArg("level"), "start_date": demisto.getArg("start_date"), "end_date": demisto.getArg("end_date"), "page": demisto.getArg("page"), "per_page": demisto.getArg("per_page"), }, ) if not results: return return_outputs("no results were found.", {}) demisto.results( { "Type": entryTypes["note"], "ContentsFormat": formats["markdown"], "Contents": results if results else "no results were found", "HumanReadable": tableToMarkdown( "Threat Indicators:", results, headerTransform=split_snake, removeNull=True, ), "EntryContext": {"Cofense.ThreatIndicators(val.ID && val.ID == obj.ID)": snake_to_camel_keys(results)}, } ) return None def get_report_png_by_id_command(triage_instance) -> None: report_id = int(demisto.getArg("report_id")) # type: int set_white_bg = demisto.args().get("set_white_bg", "False") == "True" # type: bool orig_png = get_report_png_by_id(triage_instance, report_id) if set_white_bg: in_buffer = BytesIO() in_buffer.write(orig_png) in_buffer.seek(0) image = Image.open(in_buffer) canvas = Image.new("RGBA", image.size, (255, 255, 255, 255)) # Empty canvas colour (r,g,b,a) canvas.paste(image, mask=image) # Paste the image onto the canvas, using it's alpha channel as mask out_buffer = BytesIO() canvas.save(out_buffer, format="PNG") out_buffer.seek(0) image_data = out_buffer.getvalue() else: image_data = orig_png cf_file = fileResult(f"cofense_report_{report_id}.png", image_data, entryTypes["image"]) demisto.results( { "Type": entryTypes["image"], "ContentsFormat": formats["text"], "Contents": f"Cofense: PNG of Report {report_id}", "File": cf_file.get("File"), "FileID": cf_file.get("FileID"), } ) def get_report_png_by_id(triage_instance, report_id): """Fetch and return the PNG file associated with the specified report_id""" return triage_instance.request(f"reports/{report_id}.png", raw_response=True).content def build_triage_instance(): demisto_params = { "start_date": parse_date_range(demisto.getParam("date_range"))[0].isoformat(), "max_fetch": int(demisto.getParam("max_fetch")), "category_id": demisto.getParam("category_id"), "match_priority": demisto.getParam("match_priority"), "tags": demisto.getParam("tags"), "mailbox_location": demisto.getParam("mailbox_location"), } return TriageInstance( host=demisto.getParam("host").rstrip("/") if demisto.getParam("host") else "", token=demisto.getParam("token"), user=demisto.getParam("user"), disable_tls_verification=demisto.params().get("insecure", False), demisto_params=demisto_params, ) def main(): try: handle_proxy() triage_instance = build_triage_instance() if demisto.command() == "test-module": test_function(triage_instance) if demisto.command() == "fetch-incidents": fetch_reports(triage_instance) elif demisto.command() == "cofense-search-reports": search_reports_command(triage_instance) elif demisto.command() == "cofense-search-inbox-reports": search_inbox_reports_command(triage_instance) elif demisto.command() == "cofense-get-attachment": get_attachment_command(triage_instance) elif demisto.command() == "cofense-get-reporter": get_reporter_command(triage_instance) elif demisto.command() == "cofense-get-report-by-id": get_report_by_id_command(triage_instance) elif demisto.command() == "cofense-get-report-png-by-id": get_report_png_by_id_command(triage_instance) elif demisto.command() == "cofense-get-threat-indicators": get_threat_indicators_command(triage_instance) except Exception as e: return_error(str(e)) raise if __name__ in ["__main__", "builtin", "builtins"]: main()