Skip to content

Commit

Permalink
Deploy Resilient/resilient-community-apps to github.ibm.com/Resilient…
Browse files Browse the repository at this point in the history
…/resilient-community-apps.git:gh-pages
  • Loading branch information
MarkScherfling committed Apr 16, 2024
1 parent 3df4213 commit f10c7c3
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 142 deletions.
Binary file modified .doctrees/environment.pickle
Binary file not shown.
Binary file modified .doctrees/fn_virustotal/README.doctree
Binary file not shown.
109 changes: 41 additions & 68 deletions _sources/fn_virustotal/README.md.txt
Original file line number Diff line number Diff line change
@@ -1,23 +1,3 @@
<!--
This README.md is generated by running:
"resilient-sdk docgen -p fn_virustotal"

This file was generated with resilient-sdk v49.0.4368

It is best edited using a Text Editor with a Markdown Previewer. VS Code
is a good example. Checkout https://guides.github.com/features/mastering-markdown/
for tips on writing with Markdown

All fields followed by "::CHANGE_ME::"" should be manually edited

If you make manual edits and run docgen again, a .bak file will be created

Store any screenshots in the "doc/screenshots" directory and reference them like:
![screenshot: screenshot_1](./screenshots/screenshot_1.png)

NOTE: If your app is available in the container-format only, there is no need to mention the integration server in this readme.
-->

# VirusTotal

## Table of Contents
Expand All @@ -39,12 +19,9 @@
---

## Release Notes
<!--
Specify all changes in this release. Do not remove the release
notes of a previous release
-->
| Version | Date | Notes |
| ------- | ---- | ----- |
| 1.1.1 | Bug fix for connecting to SOAR. |
| 1.1.0 | Update VirusTotal REST API v2 to v3. Playbook support. Task attachment analysis support. |
| 1.0.7 | Add Support for Custom Headers |
| 1.0.6 | Enhanced Rules and Workflows |
Expand All @@ -55,8 +32,8 @@
| 1.0.1 | Proxy support added |

---
### 1.1 Changes
In v1.1, the existing rules and workflows have been replaced with playbooks.
### 1.1.0 Changes
In v1.1.0, the existing rules and workflows have been replaced with playbooks.
This change is made to support the ongoing, newer capabilities of playbooks.
Each playbook has the same functionality as the previous, corresponding rule/workflow.

Expand Down Expand Up @@ -106,13 +83,13 @@ This app supports the IBM Security QRadar SOAR Platform and the IBM Security QRa
The SOAR platform supports two app deployment mechanisms, Edge Gateway (formerly App Host) and integration server.

If deploying to a SOAR platform with an Edge Gateway, the requirements are:
* SOAR platform >= `45.2.0`.
* SOAR platform >= `50.0.0`.
* The app is in a container-based format (available from the AppExchange as a `zip` file).

If deploying to a SOAR platform with an integration server, the requirements are:
* SOAR platform >= `45.2.0`.
* SOAR platform >= `50.0.0`.
* The app is in the older integration format (available from the AppExchange as a `zip` file which contains a `tar.gz` file).
* Integration server is running `resilient-circuits>=48.0.0`.
* Integration server is running `resilient-circuits>=50.0.0`.
* If using an API key account, make sure the account provides the following minimum permissions:
| Name | Permissions |
| ---- | ----------- |
Expand All @@ -130,7 +107,7 @@ The above guides are available on the IBM Documentation website at [ibm.biz/soar

### Cloud Pak for Security
If you are deploying to IBM Cloud Pak for Security, the requirements are:
* IBM Cloud Pak for Security >= `1.8`.
* IBM Cloud Pak for Security >= `1.10`.
* Cloud Pak is configured with an Edge Gateway.
* The app is in a container-based format (available from the AppExchange as a `zip` file).

Expand All @@ -144,10 +121,10 @@ These guides are available on the IBM Documentation website at [ibm.biz/cp4s-doc
The app **does** support a proxy server.

### Python Environment
Python 3.6 and Python 3.9 are supported.
Python 3.6, 3.9 and 3.11 are supported.
Additional package dependencies may exist for each of these packages:
* bs4==0.0.1
* resilient-circuits>=48.0.0
* resilient-circuits>=50.0.0

### VirusTotal Development Version

Expand Down Expand Up @@ -951,26 +928,26 @@ inputs.vt_data = artifact.value
<p>

```python
import datetime
import json
from datetime import datetime
from json import dumps

VIRUSTOTAL_GUI_URL = "https://www.virustotal.com/gui"

results = playbook.functions.results.vt_scan_results

# Uncomment the following line to have the results json printed formatted to a note.
#pretty_results = json.dumps(results, indent=4, sort_keys=True)
#incident.addNote(helper.createRichText(u"<p>VirusTotal scan of {0}: {1}</p><div>{2}</div>".format(artifact.type, artifact.value, pretty_results)))
# Uncomment the following 2 lines to have the results json printed formatted to a note.
#pretty_results = dumps(results, indent=4, sort_keys=True)
#incident.addNote(helper.createRichText(u"<p>VirusTotal scan of {0}: {1} with artifact_id: {2}</p><div>{3}</div>".format(artifact.type, artifact.value, artifact.id, pretty_results)))

msg = u"<p>VirusTotal scan of {0}: <b>{1}</b></p>".format(artifact.type, artifact.value)
scan = results.get("scan", {})
msg = f"<p>VirusTotal scan of {artifact.type}: <b>{artifact.value}</b> with artifact_id: {artifact.id}</p>"
scan = results.get("content", {}).get("scan", {})
if not scan:
raise Exception("No scan data returned VirusTotal scan {0}: {1}".format(artifact.type, artifact.value))
raise Exception(f"No scan data returned VirusTotal scan {artifact.type}: {artifact.value} with artifact_id: {artifact.id}")

data = scan.get("data", {})
scan_error = scan.get("error", {})
if scan_error:
msg = "{0}Error returned: {1}".format(msg, scan_error)
msg = f"{msg}Error returned: {scan_error}"
#helper.fail("Error returned from VirusTotal scan {0}: {1}: {2}".format(artifact.type, artifact.value, scan_error))

stats = {}
Expand All @@ -986,56 +963,56 @@ if data:
# Write statistics to the note
for k,v in stats.items():
if k.lower() == "malicious":
msg = "{0}{1}: <span style='color:red'>{2}</span><br>".format(msg, k, v)
msg = f"{msg}{k}: <span style='color:red'>{v}</span><br>"
else:
msg = "{0}{1}: {2}<br>".format(msg, k, v)
msg = f"{msg}{k}: {v}<br>"

# Write the last analysis time to the note
last_analysis_date = attributes.get("last_analysis_date", None)
if last_analysis_date:
last_analysis_date_str = datetime.datetime.fromtimestamp(last_analysis_date).strftime('%Y-%b-%d %H:%M:%S')
msg = "{0}<br>Last analysis date: {1}".format(msg, last_analysis_date_str)
last_analysis_date_str = datetime.fromtimestamp(last_analysis_date).strftime('%Y-%b-%d %H:%M:%S')
msg = f"{msg}<br>Last analysis date: {last_analysis_date_str}"

# Add VirusTotal Report link to the note
if data:
uriLookup = { 'Email Attachment': 'file',
'Malware Sample': 'file',
'Malware MD5 Hash': 'file',
'Malware SHA-1 Hash': 'file',
'Malware SHA-256 Hash': 'file',
uriLookup = { 'Email Attachment': 'file',
'Malware Sample': 'file',
'Malware MD5 Hash': 'file',
'Malware SHA-1 Hash': 'file',
'Malware SHA-256 Hash': 'file',
'Other File': 'file',
'RCF 822 Email Message File': 'file',
'RCF 822 Email Message File': 'file',
'File Name': 'file',
'URL': 'url',
'IP Address': 'ip-address',
'DNS Name':'domain'}
'URL': 'url',
'IP Address': 'ip-address',
'DNS Name': 'domain'}
uri_fragment = uriLookup.get(artifact.type, None)
vt_id = data.get("id", None)
if vt_id and uri_fragment:
link_back = "<a href='{0}/{1}/{2}'>VirusTotal Report</a>".format(VIRUSTOTAL_GUI_URL, uri_fragment, vt_id)
msg = "{0}<br>{1}".format(msg, link_back)
link_back = f"<a href='{VIRUSTOTAL_GUI_URL}/{uri_fragment}/{vt_id}'>VirusTotal Report</a>"
msg = f"{msg}<br>{link_back}"

if not stats:
msg = "{0}No stats returned from scan {1}: {2}".format(msg, artifact.type, artifact.value)
msg = f"{msg}No stats returned from scan {artifact.type}: {artifact.value} with artifact_id: {artifact.id}"

incident.addNote(helper.createRichText("<div>{0}</div>".format(msg)))
incident.addNote(helper.createRichText(f"<div>{msg}</div>"))

# Create artifacts from results
last_http_response_content_sha256 = attributes.get("last_http_response_content_sha256", None)
if last_http_response_content_sha256:
incident.addArtifact('Malware SHA-256 Hash', last_http_response_content_sha256, "Created by VirusTotal scan of artifact type: {0} value: {1}".format(artifact.type, artifact.value))
incident.addArtifact('Malware SHA-256 Hash', last_http_response_content_sha256, f"Created by VirusTotal scan of artifact type: {artifact.type} value: {artifact.value} artifact_id: {artifact.id}")

sha256 = attributes.get("sha256", None)
sha256 = attributes.get("sha256", None)
if sha256:
incident.addArtifact('Malware SHA-256 Hash', sha256, "Created by VirusTotal scan of artifact type: {0} value: {1}".format(artifact.type, artifact.value))
incident.addArtifact('Malware SHA-256 Hash', sha256, f"Created by VirusTotal scan of artifact type: {artifact.type} value: {artifact.value} artifact_id: {artifact.id}")

md5 = attributes.get("md5", None)
if md5:
incident.addArtifact('Malware MD5 Hash', md5, "Created by VirusTotal scan of artifact type: {0} value: {1}".format(artifact.type, artifact.value))
incident.addArtifact('Malware MD5 Hash', md5, f"Created by VirusTotal scan of artifact type: {artifact.type} value: {artifact.value} artifact_id: {artifact.id}")

sha1 = attributes.get("sha1", None)
if sha1:
incident.addArtifact('Malware SHA-1 Hash', sha1, "Created by VirusTotal scan of artifact type: {0} value: {1}".format(artifact.type, artifact.value))
incident.addArtifact('Malware SHA-1 Hash', sha1, f"Created by VirusTotal scan of artifact type: {artifact.type} value: {artifact.value} artifact_id: {artifact.id}")
```

</p>
Expand All @@ -1044,10 +1021,6 @@ if sha1:
---






## Playbooks
![screenshot: fn-virustotal-pb ](./doc/screenshots/vt-playbooks.png)

Expand Down
Loading

0 comments on commit f10c7c3

Please sign in to comment.