Branch was auto-updated.

This commit is contained in:
srv-rr-gh-researchbt
2023-01-11 12:58:06 -08:00
committed by GitHub
12 changed files with 4030 additions and 0 deletions
@@ -0,0 +1,826 @@
{
"blockly": false,
"blockly_xml": "<xml></xml>",
"category": "Identifier Reputation Analysis",
"coa": {
"data": {
"description": "Detects available indicators and routes them to indicator reputation analysis playbooks. The output of the analysis will update any artifacts, tasks, and indicator tags.\n\nRef: https://d3fend.mitre.org/technique/d3f:IdentifierReputationAnalysis/",
"edges": [
{
"id": "port_9_to_port_1",
"sourceNode": "9",
"sourcePort": "9_out",
"targetNode": "1",
"targetPort": "1_in"
},
{
"id": "port_5_to_port_1",
"sourceNode": "5",
"sourcePort": "5_out",
"targetNode": "1",
"targetPort": "1_in"
},
{
"conditions": [
{
"index": 0
}
],
"id": "port_12_to_port_17",
"sourceNode": "12",
"sourcePort": "12_out",
"targetNode": "17",
"targetPort": "17_in"
},
{
"conditions": [
{
"index": 0
}
],
"id": "port_11_to_port_18",
"sourceNode": "11",
"sourcePort": "11_out",
"targetNode": "18",
"targetPort": "18_in"
},
{
"id": "port_18_to_port_5",
"sourceNode": "18",
"sourcePort": "18_out",
"targetNode": "5",
"targetPort": "5_in"
},
{
"conditions": [
{
"index": 0
}
],
"id": "port_11_to_port_9",
"sourceNode": "11",
"sourcePort": "11_out",
"targetNode": "9",
"targetPort": "9_in"
},
{
"id": "port_17_to_port_19",
"sourceNode": "17",
"sourcePort": "17_out",
"targetNode": "19",
"targetPort": "19_in"
},
{
"conditions": [
{
"index": 0
}
],
"id": "port_19_to_port_11",
"sourceNode": "19",
"sourcePort": "19_out",
"targetNode": "11",
"targetPort": "11_in"
},
{
"conditions": [
{
"index": 1
}
],
"id": "port_19_to_port_20",
"sourceNode": "19",
"sourcePort": "19_out",
"targetNode": "20",
"targetPort": "20_in"
},
{
"id": "port_0_to_port_21",
"sourceNode": "0",
"sourcePort": "0_out",
"targetNode": "21",
"targetPort": "21_in"
},
{
"conditions": [
{
"index": 0
}
],
"id": "port_21_to_port_12",
"sourceNode": "21",
"sourcePort": "21_out",
"targetNode": "12",
"targetPort": "12_in"
},
{
"conditions": [
{
"index": 1
}
],
"id": "port_21_to_port_22",
"sourceNode": "21",
"sourcePort": "21_out",
"targetNode": "22",
"targetPort": "22_in"
}
],
"hash": "b43182bac2c18df81288ffb1cbafde3091b65a6e",
"nodes": {
"0": {
"data": {
"advanced": {
"join": []
},
"functionName": "on_start",
"id": "0",
"type": "start"
},
"errors": {},
"id": "0",
"type": "start",
"warnings": {},
"x": 470,
"y": 0
},
"1": {
"data": {
"advanced": {
"join": []
},
"functionId": 1,
"functionName": "on_finish",
"id": "1",
"type": "end"
},
"errors": {},
"id": "1",
"type": "end",
"userCode": "\n # This function is called after all actions are completed.\n # summary of all the action and/or all details of actions\n # can be collected here.\n\n # summary_json = phantom.get_summary()\n # if 'result' in summary_json:\n # for action_result in summary_json['result']:\n # if 'action_run_id' in action_result:\n # action_results = phantom.get_action_results(action_run_id=action_result['action_run_id'], result_data=False, flatten=False)\n # phantom.debug(action_results)\n\n",
"warnings": {},
"x": 190,
"y": 1358
},
"11": {
"data": {
"advanced": {
"customName": "outputs filter",
"customNameId": 0,
"description": "Routes outputs based on reputation score and report availability.",
"join": [],
"note": "Routes outputs based on reputation score and report availability."
},
"conditions": [
{
"comparisons": [
{
"conditionIndex": 0,
"op": ">=",
"param": "dispatch_reputation_playbooks_1:playbook_output:observable.reputation.score_id",
"value": "0"
}
],
"conditionIndex": 0,
"customName": "reputation tags",
"logic": "and"
}
],
"functionId": 1,
"functionName": "outputs_filter",
"id": "11",
"type": "filter"
},
"errors": {},
"id": "11",
"type": "filter",
"warnings": {
"config": [
"Reconfigure invalid datapath configuration."
]
},
"x": 230,
"y": 852
},
"12": {
"data": {
"advanced": {
"customName": "filter new artifacts",
"customNameId": 0,
"description": "Only dispatch reputation playbooks against new artifacts.",
"join": [],
"note": "Only dispatch reputation playbooks against new artifacts."
},
"conditions": [
{
"comparisons": [
{
"conditionIndex": 0,
"op": "!=",
"param": "artifact:*.id",
"value": "None"
}
],
"conditionIndex": 0,
"customName": "artifacts",
"logic": "and"
}
],
"functionId": 2,
"functionName": "filter_new_artifacts",
"id": "12",
"type": "filter"
},
"errors": {},
"id": "12",
"type": "filter",
"warnings": {},
"x": 370,
"y": 328
},
"17": {
"data": {
"advanced": {
"customName": "Dispatch Reputation Playbooks",
"customNameId": 1,
"join": []
},
"functionId": 1,
"functionName": "dispatch_reputation_playbooks_1",
"id": "17",
"inputs": {
"artifact_ids_include": {
"datapaths": [
"filtered-data:filter_new_artifacts:condition_1:artifact:*.id"
],
"deduplicate": false
},
"indicator_tags_exclude": {
"datapaths": [],
"deduplicate": false
},
"indicator_tags_include": {
"datapaths": [],
"deduplicate": false
},
"playbook_repo": {
"datapaths": [],
"deduplicate": false
},
"playbook_tags": {
"datapaths": [
"reputation"
],
"deduplicate": false
}
},
"playbookName": "dispatch_input_playbooks",
"playbookRepo": 3,
"playbookRepoName": "community",
"playbookType": "data",
"synchronous": true,
"type": "playbook"
},
"errors": {},
"id": "17",
"type": "playbook",
"warnings": {},
"x": 310,
"y": 508
},
"18": {
"data": {
"advanced": {
"customName": "merge reports",
"customNameId": 0,
"description": "Format a note that merges together normalized data. The data will come from the playbooks launched by the Dispatch Reputation Playbooks block.",
"join": [],
"note": "Format a note that merges together normalized data. The data will come from the playbooks launched by the Dispatch Reputation Playbooks block."
},
"customDatapaths": {
"dispatch_reputation_playbooks_1": {
"outputs:observable.type": {
"contains": [],
"isCustomDatapath": true,
"label": "outputs:observable.type",
"value": "dispatch_reputation_playbooks_1:playbook_output:observable.type"
},
"outputs:observable.value": {
"contains": [],
"isCustomDatapath": true,
"label": "outputs:observable.value",
"value": "dispatch_reputation_playbooks_1:playbook_output:observable.value"
}
},
"outputs_filter": {
"condition_1:dispatch_reputation_playbooks_1:outputs:observable.categories": {
"contains": [],
"isCustomDatapath": true,
"label": "condition_1:dispatch_reputation_playbooks_1:outputs:observable.categories",
"value": "filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.categories"
},
"condition_1:dispatch_reputation_playbooks_1:outputs:observable.reputation": {
"contains": [],
"isCustomDatapath": true,
"label": "condition_1:dispatch_reputation_playbooks_1:outputs:observable.reputation",
"value": "filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.reputation"
},
"condition_1:dispatch_reputation_playbooks_1:outputs:observable.reputation.score": {
"contains": [],
"isCustomDatapath": true,
"label": "condition_1:dispatch_reputation_playbooks_1:outputs:observable.reputation.score",
"value": "filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.reputation.score"
},
"condition_1:dispatch_reputation_playbooks_1:outputs:observable.reputation.score_id": {
"contains": [],
"isCustomDatapath": true,
"label": "condition_1:dispatch_reputation_playbooks_1:outputs:observable.reputation.score_id",
"value": "filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.reputation.score_id"
},
"condition_1:dispatch_reputation_playbooks_1:outputs:observable.source": {
"contains": [],
"isCustomDatapath": true,
"label": "condition_1:dispatch_reputation_playbooks_1:outputs:observable.source",
"value": "filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.source"
},
"condition_1:dispatch_reputation_playbooks_1:outputs:observable.source_link": {
"contains": [],
"isCustomDatapath": true,
"label": "condition_1:dispatch_reputation_playbooks_1:outputs:observable.source_link",
"value": "filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.source_link"
},
"condition_1:dispatch_reputation_playbooks_1:outputs:observable.type": {
"contains": [],
"isCustomDatapath": true,
"label": "condition_1:dispatch_reputation_playbooks_1:outputs:observable.type",
"value": "filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.type"
},
"condition_1:dispatch_reputation_playbooks_1:outputs:observable.value": {
"contains": [],
"isCustomDatapath": true,
"label": "condition_1:dispatch_reputation_playbooks_1:outputs:observable.value",
"value": "filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.value"
}
}
},
"functionId": 1,
"functionName": "merge_reports",
"id": "18",
"parameters": [
"filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.type",
"filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.value",
"filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.reputation.score",
"filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.categories",
"filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.source",
"filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.source_link"
],
"template": "SOAR performed Reputation Analysis based on available indicators and playbooks. The following table shows a summary of the information gathered.\n\n| Type | Value | Normalized Score | Categories | Source | Source Link |\n| --- | --- | --- | --- | --- | --- |\n%%\n| {0} | `{1}` | {2} | {3} | {4} | {5} |\n%%",
"type": "format"
},
"errors": {},
"id": "18",
"type": "format",
"warnings": {},
"x": 340,
"y": 1032
},
"19": {
"data": {
"advanced": {
"customName": "outputs decision",
"customNameId": 0,
"description": "Determine if outputs exist.",
"join": [],
"note": "Determine if outputs exist."
},
"conditions": [
{
"comparisons": [
{
"conditionIndex": 0,
"op": "!=",
"param": "dispatch_reputation_playbooks_1:playbook_output:observable",
"value": "None"
}
],
"conditionIndex": 0,
"customName": "outputs exist",
"display": "If",
"logic": "and",
"type": "if"
},
{
"comparisons": [
{
"op": "==",
"param": "",
"value": ""
}
],
"conditionIndex": 1,
"customName": "outputs do not exist",
"display": "Else",
"logic": "and",
"type": "else"
}
],
"functionId": 1,
"functionName": "outputs_decision",
"id": "19",
"type": "decision"
},
"errors": {},
"id": "19",
"type": "decision",
"warnings": {},
"x": 390,
"y": 672
},
"20": {
"data": {
"advanced": {
"join": []
},
"functionId": 1,
"functionName": "add_comment_1",
"id": "20",
"selectMore": false,
"tab": "apis",
"type": "utility",
"utilities": {
"comment": {
"description": "",
"fields": [
{
"description": "",
"label": "comment",
"name": "comment",
"placeholder": "Enter a comment",
"renderType": "datapath",
"required": true
},
{
"hidden": true,
"name": "container",
"required": false
},
{
"hidden": true,
"name": "author",
"required": false
},
{
"hidden": true,
"name": "trace",
"required": false
}
],
"label": "add comment",
"name": "comment"
}
},
"utilityType": "api",
"values": {
"comment": {
"_internal": [
"container",
"author",
"trace"
],
"comment": "No observable data found from playbook."
}
}
},
"errors": {},
"id": "20",
"type": "utility",
"warnings": {},
"x": 450,
"y": 868
},
"21": {
"data": {
"advanced": {
"customName": "artifact decision",
"customNameId": 0,
"description": "Determine if artifacts exist to run through the playbook.",
"join": [],
"note": "Determine if artifacts exist to run through the playbook."
},
"conditions": [
{
"comparisons": [
{
"conditionIndex": 0,
"op": "!=",
"param": "artifact:*.id",
"value": "None"
}
],
"conditionIndex": 0,
"customName": "artifacts exist",
"display": "If",
"logic": "and",
"type": "if"
},
{
"comparisons": [
{
"op": "==",
"param": "",
"value": ""
}
],
"conditionIndex": 1,
"customName": "artifacts do not exist",
"display": "Else",
"logic": "and",
"type": "else"
}
],
"functionId": 2,
"functionName": "artifact_decision",
"id": "21",
"type": "decision"
},
"errors": {},
"id": "21",
"type": "decision",
"warnings": {},
"x": 530,
"y": 148
},
"22": {
"data": {
"advanced": {
"join": []
},
"functionId": 2,
"functionName": "add_comment_2",
"id": "22",
"selectMore": false,
"tab": "apis",
"type": "utility",
"utilities": {
"comment": {
"description": "",
"fields": [
{
"description": "",
"label": "comment",
"name": "comment",
"placeholder": "Enter a comment",
"renderType": "datapath",
"required": true
},
{
"hidden": true,
"name": "container",
"required": false
},
{
"hidden": true,
"name": "author",
"required": false
},
{
"hidden": true,
"name": "trace",
"required": false
}
],
"label": "add comment",
"name": "comment"
}
},
"utilityType": "api",
"values": {
"comment": {
"_internal": [
"container",
"author",
"trace"
],
"comment": "No new artifacts found to perform Dynamic Identifier Reputation Analysis."
}
}
},
"errors": {},
"id": "22",
"type": "utility",
"warnings": {},
"x": 590,
"y": 344
},
"5": {
"data": {
"advanced": {
"customName": "update reputation task",
"customNameId": 0,
"join": []
},
"customFunction": {
"draftMode": false,
"name": "workbook_task_update",
"repoName": "community"
},
"functionId": 3,
"functionName": "update_reputation_task",
"id": "5",
"selectMore": false,
"type": "utility",
"utilities": {
"workbook_task_update": {
"description": "Update a workbook task by task name",
"fields": [
{
"dataTypes": [
"*"
],
"description": "Name of a workbook task (Required)",
"inputType": "item",
"label": "task_name",
"name": "task_name",
"placeholder": "my_task",
"renderType": "datapath",
"required": false
},
{
"dataTypes": [
"*"
],
"description": "Note title goes here (Optional)",
"inputType": "item",
"label": "note_title",
"name": "note_title",
"placeholder": "My Title",
"renderType": "datapath",
"required": false
},
{
"dataTypes": [
"*"
],
"description": "Body of note goes here (Optional)",
"inputType": "item",
"label": "note_content",
"name": "note_content",
"placeholder": "My notes",
"renderType": "datapath",
"required": false
},
{
"dataTypes": [
"*"
],
"description": "One of: incomplete, in_progress, complete (Optional)",
"inputType": "item",
"label": "status",
"name": "status",
"placeholder": "in_progress",
"renderType": "datapath",
"required": false
},
{
"dataTypes": [
"*"
],
"description": "Assigns task to provided owner. Accepts keyword 'current\" to assign task to currently running playbook user. (Optional)",
"inputType": "item",
"label": "owner",
"name": "owner",
"placeholder": "username",
"renderType": "datapath",
"required": false
},
{
"dataTypes": [
"phantom container id"
],
"description": "ID of Phantom Container (Required)",
"inputType": "item",
"label": "container",
"name": "container",
"placeholder": "container:id",
"renderType": "datapath",
"required": false
}
],
"label": "workbook_task_update",
"name": "workbook_task_update"
}
},
"utilityType": "custom_function",
"values": {
"workbook_task_update": {
"container": "container:id",
"note_content": "merge_reports:formatted_data",
"note_title": "Identifier Reputation Analysis Report",
"owner": null,
"status": "complete",
"task_name": "playbook"
}
}
},
"errors": {},
"id": "5",
"type": "utility",
"warnings": {},
"x": 340,
"y": 1210
},
"9": {
"data": {
"advanced": {
"customName": "tag indicators",
"customNameId": 0,
"join": []
},
"customFunction": {
"draftMode": false,
"name": "indicator_tag",
"repoName": "community"
},
"functionId": 6,
"functionName": "tag_indicators",
"id": "9",
"selectMore": false,
"type": "utility",
"utilities": {
"indicator_tag": {
"description": "Tag an existing indicator record. Tags can be overwritten or appended.",
"fields": [
{
"dataTypes": [
"*"
],
"description": "Specifies the indicator which the tag will be added to. Supports a string indicator value or an indicator id.",
"inputType": "item",
"label": "indicator",
"name": "indicator",
"placeholder": "my_indicator",
"renderType": "datapath",
"required": false
},
{
"dataTypes": [
"*"
],
"description": "Comma separated list of tags. Tags should only contain characters Aa-Zz, 0-9, '-', and '_'.",
"inputType": "item",
"label": "tags",
"name": "tags",
"placeholder": "tag1,tag2,...,tagk",
"renderType": "datapath",
"required": false
},
{
"dataTypes": [],
"description": "Either True or False with default as False. If set to True, existing tags on the indicator record will be replaced by the provided input. If set to False, the new tags will be appended to the existing indicator tags.",
"inputType": "item",
"label": "overwrite",
"name": "overwrite",
"placeholder": "False",
"renderType": "datapath",
"required": false
}
],
"label": "indicator_tag",
"name": "indicator_tag"
}
},
"utilityType": "custom_function",
"values": {
"indicator_tag": {
"indicator": "filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.value",
"overwrite": null,
"tags": "filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.reputation.score"
}
}
},
"errors": {},
"id": "9",
"type": "utility",
"warnings": {},
"x": 0,
"y": 1210
}
},
"notes": "Outputs: \n- Tags indicators based on reputation score. \n- Concludes reputation task."
},
"input_spec": null,
"output_spec": null,
"playbook_type": "automation",
"python_version": "3",
"schema": "5.0.8",
"version": "5.5.0.108488"
},
"create_time": "2023-01-09T22:52:13.357641+00:00",
"draft_mode": false,
"labels": [
"*"
],
"tags": [
"D3-IRA"
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

@@ -0,0 +1,314 @@
"""
Detects available indicators and routes them to indicator reputation analysis playbooks. The output of the analysis will update any artifacts, tasks, and indicator tags.\n\nRef: https://d3fend.mitre.org/technique/d3f:IdentifierReputationAnalysis/
"""
import phantom.rules as phantom
import json
from datetime import datetime, timedelta
@phantom.playbook_block()
def on_start(container):
phantom.debug('on_start() called')
# call 'artifact_decision' block
artifact_decision(container=container)
return
@phantom.playbook_block()
def update_reputation_task(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
phantom.debug("update_reputation_task() called")
id_value = container.get("id", None)
merge_reports = phantom.get_format_data(name="merge_reports")
parameters = []
parameters.append({
"owner": None,
"status": "complete",
"container": id_value,
"task_name": "playbook",
"note_title": "Identifier Reputation Analysis Report",
"note_content": merge_reports,
})
################################################################################
## Custom Code Start
################################################################################
# Write your custom code here...
################################################################################
## Custom Code End
################################################################################
phantom.custom_function(custom_function="community/workbook_task_update", parameters=parameters, name="update_reputation_task")
return
@phantom.playbook_block()
def tag_indicators(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
phantom.debug("tag_indicators() called")
filtered_output_0_dispatch_reputation_playbooks_1_output_observable = phantom.collect2(container=container, datapath=["filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.reputation.score","filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.value"])
parameters = []
# build parameters list for 'tag_indicators' call
for filtered_output_0_dispatch_reputation_playbooks_1_output_observable_item in filtered_output_0_dispatch_reputation_playbooks_1_output_observable:
parameters.append({
"tags": filtered_output_0_dispatch_reputation_playbooks_1_output_observable_item[0],
"indicator": filtered_output_0_dispatch_reputation_playbooks_1_output_observable_item[1],
"overwrite": None,
})
################################################################################
## Custom Code Start
################################################################################
# Write your custom code here...
################################################################################
## Custom Code End
################################################################################
phantom.custom_function(custom_function="community/indicator_tag", parameters=parameters, name="tag_indicators")
return
@phantom.playbook_block()
def outputs_filter(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
phantom.debug("outputs_filter() called")
################################################################################
# Routes outputs based on reputation score and report availability.
################################################################################
# collect filtered artifact ids and results for 'if' condition 1
matched_artifacts_1, matched_results_1 = phantom.condition(
container=container,
conditions=[
["dispatch_reputation_playbooks_1:playbook_output:observable.reputation.score_id", ">=", 0]
],
name="outputs_filter:condition_1")
# call connected blocks if filtered artifacts or results
if matched_artifacts_1 or matched_results_1:
merge_reports(action=action, success=success, container=container, results=results, handle=handle, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
tag_indicators(action=action, success=success, container=container, results=results, handle=handle, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
return
@phantom.playbook_block()
def filter_new_artifacts(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
phantom.debug("filter_new_artifacts() called")
################################################################################
# Only dispatch reputation playbooks against new artifacts.
################################################################################
# collect filtered artifact ids and results for 'if' condition 1
matched_artifacts_1, matched_results_1 = phantom.condition(
container=container,
conditions=[
["artifact:*.id", "!=", None]
],
name="filter_new_artifacts:condition_1")
# call connected blocks if filtered artifacts or results
if matched_artifacts_1 or matched_results_1:
dispatch_reputation_playbooks_1(action=action, success=success, container=container, results=results, handle=handle, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
return
@phantom.playbook_block()
def dispatch_reputation_playbooks_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
phantom.debug("dispatch_reputation_playbooks_1() called")
filtered_artifact_0_data_filter_new_artifacts = phantom.collect2(container=container, datapath=["filtered-data:filter_new_artifacts:condition_1:artifact:*.id"])
filtered_artifact_0__id = [item[0] for item in filtered_artifact_0_data_filter_new_artifacts]
inputs = {
"playbook_repo": [],
"playbook_tags": ["reputation"],
"artifact_ids_include": filtered_artifact_0__id,
"indicator_tags_exclude": [],
"indicator_tags_include": [],
}
################################################################################
## Custom Code Start
################################################################################
# Write your custom code here...
################################################################################
## Custom Code End
################################################################################
# call playbook "community/dispatch_input_playbooks", returns the playbook_run_id
playbook_run_id = phantom.playbook("community/dispatch_input_playbooks", container=container, name="dispatch_reputation_playbooks_1", callback=outputs_decision, inputs=inputs)
return
@phantom.playbook_block()
def merge_reports(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
phantom.debug("merge_reports() called")
################################################################################
# Format a note that merges together normalized data. The data will come from
# the playbooks launched by the Dispatch Reputation Playbooks block.
################################################################################
template = """SOAR performed Reputation Analysis based on available indicators and playbooks. The following table shows a summary of the information gathered.\n\n| Type | Value | Normalized Score | Categories | Source | Source Link |\n| --- | --- | --- | --- | --- | --- |\n%%\n| {0} | `{1}` | {2} | {3} | {4} | {5} |\n%%"""
# parameter list for template variable replacement
parameters = [
"filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.type",
"filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.value",
"filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.reputation.score",
"filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.categories",
"filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.source",
"filtered-data:outputs_filter:condition_1:dispatch_reputation_playbooks_1:playbook_output:observable.source_link"
]
################################################################################
## Custom Code Start
################################################################################
# Write your custom code here...
################################################################################
## Custom Code End
################################################################################
phantom.format(container=container, template=template, parameters=parameters, name="merge_reports")
update_reputation_task(container=container)
return
@phantom.playbook_block()
def outputs_decision(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
phantom.debug("outputs_decision() called")
################################################################################
# Determine if outputs exist.
################################################################################
# check for 'if' condition 1
found_match_1 = phantom.decision(
container=container,
conditions=[
["dispatch_reputation_playbooks_1:playbook_output:observable", "!=", None]
])
# call connected blocks if condition 1 matched
if found_match_1:
outputs_filter(action=action, success=success, container=container, results=results, handle=handle)
return
# check for 'else' condition 2
add_comment_1(action=action, success=success, container=container, results=results, handle=handle)
return
@phantom.playbook_block()
def add_comment_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
phantom.debug("add_comment_1() called")
################################################################################
## Custom Code Start
################################################################################
# Write your custom code here...
################################################################################
## Custom Code End
################################################################################
phantom.comment(container=container, comment="No observable data found from playbook.")
return
@phantom.playbook_block()
def artifact_decision(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
phantom.debug("artifact_decision() called")
################################################################################
# Determine if artifacts exist to run through the playbook.
################################################################################
# check for 'if' condition 1
found_match_1 = phantom.decision(
container=container,
conditions=[
["artifact:*.id", "!=", None]
])
# call connected blocks if condition 1 matched
if found_match_1:
filter_new_artifacts(action=action, success=success, container=container, results=results, handle=handle)
return
# check for 'else' condition 2
add_comment_2(action=action, success=success, container=container, results=results, handle=handle)
return
@phantom.playbook_block()
def add_comment_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
phantom.debug("add_comment_2() called")
################################################################################
## Custom Code Start
################################################################################
# Write your custom code here...
################################################################################
## Custom Code End
################################################################################
phantom.comment(container=container, comment="No new artifacts found to perform Dynamic Identifier Reputation Analysis.")
return
@phantom.playbook_block()
def on_finish(container, summary):
phantom.debug("on_finish() called")
################################################################################
## Custom Code Start
################################################################################
# This function is called after all actions are completed.
# summary of all the action and/or all details of actions
# can be collected here.
# summary_json = phantom.get_summary()
# if 'result' in summary_json:
# for action_result in summary_json['result']:
# if 'action_run_id' in action_result:
# action_results = phantom.get_action_results(action_run_id=action_result['action_run_id'], result_data=False, flatten=False)
# phantom.debug(action_results)
################################################################################
## Custom Code End
################################################################################
return
@@ -0,0 +1,20 @@
name: Dynamic Identifier Reputation Analysis
id: fc0edc96-ff2b-48b0-9b4d-63da6783fd64
version: 1
date: '2023-01-11'
author: Kelby Shelton, Splunk
type: Investigation
description: "Detects available indicators and routes them to indicator reputation analysis playbooks. The output of the analysis will update any artifacts, tasks, and indicator tags. https://d3fend.mitre.org/technique/d3f:IdentifierReputationAnalysis/"
playbook: Dynamic_Identifier_Reputation_Analysis
how_to_implement: This playbook looks for artifacts and then dispatches the community Reputation playbooks. This playbook takes the output of those playbooks and nicely formats them into notes and tags indicators with their results.
references:
- https://d3fend.mitre.org/technique/d3f:IdentifierReputationAnalysis/
app_list: []
tags:
platform_tags:
- D3-IRA
playbook_type: Automation
vpe_type: Modern
playbook_fields: []
product:
- Splunk SOAR
@@ -0,0 +1,364 @@
{
"blockly": false,
"blockly_xml": "<xml></xml>",
"category": "Identifier Reputation Analysis",
"coa": {
"data": {
"description": "Accepts a URL and does reputation analysis on the objects. Generates a global report and a per observable sub-report and normalized score. The score can be customized as desired.\n\nRef: https://d3fend.mitre.org/technique/d3f:IdentifierReputationAnalysis/",
"edges": [
{
"id": "port_0_to_port_2",
"sourceNode": "0",
"sourcePort": "0_out",
"targetNode": "2",
"targetPort": "2_in"
},
{
"id": "port_2_to_port_4",
"sourceNode": "2",
"sourcePort": "2_out",
"targetNode": "4",
"targetPort": "4_in"
},
{
"conditions": [
{
"index": 0
}
],
"id": "port_4_to_port_3",
"sourceNode": "4",
"sourcePort": "4_out",
"targetNode": "3",
"targetPort": "3_in"
},
{
"id": "port_3_to_port_5",
"sourceNode": "3",
"sourcePort": "3_out",
"targetNode": "5",
"targetPort": "5_in"
},
{
"id": "port_5_to_port_7",
"sourceNode": "5",
"sourcePort": "5_out",
"targetNode": "7",
"targetPort": "7_in"
},
{
"id": "port_7_to_port_6",
"sourceNode": "7",
"sourcePort": "7_out",
"targetNode": "6",
"targetPort": "6_in"
},
{
"id": "port_6_to_port_1",
"sourceNode": "6",
"sourcePort": "6_out",
"targetNode": "1",
"targetPort": "1_in"
}
],
"hash": "c6a3356c448c9ecaad5287502c3867284b3a6cac",
"nodes": {
"0": {
"data": {
"advanced": {
"join": []
},
"functionName": "on_start",
"id": "0",
"type": "start"
},
"errors": {},
"id": "0",
"type": "start",
"warnings": {},
"x": 19.999999999999986,
"y": -1.9184653865522705e-13
},
"1": {
"data": {
"advanced": {
"join": []
},
"functionName": "on_finish",
"id": "1",
"type": "end"
},
"errors": {},
"id": "1",
"type": "end",
"warnings": {},
"x": 19.999999999999986,
"y": 1180
},
"2": {
"data": {
"action": "url reputation",
"actionType": "investigate",
"advanced": {
"customName": "url reputation",
"customNameId": 0,
"description": "Queries PhishTank for information about the provided URL(s)",
"join": [],
"note": "Queries PhishTank for information about the provided URL(s)"
},
"connector": "PhishTank",
"connectorConfigs": [
"phishtank"
],
"connectorId": "c193026d-46cf-4f17-b4b9-f22525d2d87e",
"connectorVersion": "v1",
"functionId": 1,
"functionName": "url_reputation",
"id": "2",
"parameters": {
"url": "playbook_input:url"
},
"requiredParameters": [
{
"data_type": "string",
"field": "url"
}
],
"type": "action"
},
"errors": {},
"id": "2",
"type": "action",
"warnings": {},
"x": 0,
"y": 148
},
"3": {
"data": {
"advanced": {
"customName": "normalize score url",
"customNameId": 0,
"description": "Contains custom code for normalizing score. Adjust the logic as desired in the documented sections.",
"join": [],
"note": "Contains custom code for normalizing score. Adjust the logic as desired in the documented sections."
},
"functionId": 1,
"functionName": "normalize_score_url",
"id": "3",
"inputParameters": [
"filtered-data:url_result_filter:condition_1:url_reputation:action_result.summary.In_Database",
"filtered-data:url_result_filter:condition_1:url_reputation:action_result.summary.Valid",
"filtered-data:url_result_filter:condition_1:url_reputation:action_result.summary.Verified"
],
"outputVariables": [
"url_score_object",
"scores"
],
"type": "code"
},
"errors": {},
"id": "3",
"type": "code",
"userCode": " \n # Assign variables\n normalize_score_url__url_score_object = []\n normalize_score_url__scores = []\n in_database_list = filtered_result_0_summary_in_database\n valid_list = filtered_result_0_summary_valid\n verified_list = filtered_result_0_summary_verified\n \n \n # Reference for scores: https://schema.ocsf.io/objects/reputation\n score_table = {\n \"-1\": \"Other\",\n \"0\":\"Unknown\",\n \"1\":\"Very_Safe\",\n \"2\":\"Safe\",\n \"3\":\"Probably_Safe\",\n \"4\":\"Leans_Safe\",\n \"5\":\"May_not_be_Safe\",\n \"6\":\"Exercise_Caution\",\n \"7\":\"Suspicious_or_Risky\",\n \"8\":\"Possibly_Malicious\",\n \"9\":\"Probably_Malicious\",\n \"10\":\"Malicious\"\n }\n \n # PhishTank URL Data\n # Adjust logic as desired\n for in_database, valid, verified in zip(in_database_list, valid_list, verified_list):\n \n # Condition 1 - In database but verified not valid phish\n if in_database and verified and not valid:\n score_id = \"2\"\n\n # Condition 2 - In database and valid phish\n elif in_database and valid:\n score_id = \"10\"\n \n # Condition 3 - In database but not verified\n elif in_database and not verified:\n score_id = \"5\"\n \n # Condition 4 - Not in database\n elif not in_database:\n score_id = \"0\"\n \n # Condition 5 - Catch all\n else:\n score_id = \"-1\"\n \n score = score_table[score_id]\n normalize_score_url__url_score_object.append(\n {\n 'score': score, \n 'score_id': score_id\n }\n )\n normalize_score_url__scores.append(score)\n \n\n",
"warnings": {},
"x": 0,
"y": 506
},
"4": {
"data": {
"advanced": {
"customName": "url result filter",
"customNameId": 0,
"description": "Filters successful url reputation results.",
"join": [],
"note": "Filters successful url reputation results."
},
"conditions": [
{
"comparisons": [
{
"conditionIndex": 0,
"op": "==",
"param": "url_reputation:action_result.status",
"value": "success"
}
],
"conditionIndex": 0,
"customName": "success",
"logic": "and"
}
],
"functionId": 1,
"functionName": "url_result_filter",
"id": "4",
"type": "filter"
},
"errors": {},
"id": "4",
"type": "filter",
"warnings": {},
"x": 60,
"y": 326
},
"5": {
"data": {
"advanced": {
"customName": "format report url",
"customNameId": 0,
"description": "Format a summary table with the information gathered from the playbook.",
"join": [],
"note": "Format a summary table with the information gathered from the playbook."
},
"functionId": 1,
"functionName": "format_report_url",
"id": "5",
"parameters": [
"filtered-data:url_result_filter:condition_1:url_reputation:action_result.parameter.url",
"normalize_score_url:custom_function:scores",
"filtered-data:url_result_filter:condition_1:url_reputation:action_result.data.*.phish_detail_page"
],
"template": "SOAR analyzed URL(s) using PhishTank. The table below shows a summary of the information gathered.\n\n| URL | Normalized Score | Report Link | Source |\n| --- | --- | --- | --- |\n%%\n| `{0}` | {1} | {2} | PhishTank |\n%%",
"type": "format"
},
"errors": {},
"id": "5",
"type": "format",
"warnings": {},
"x": 0,
"y": 684
},
"6": {
"data": {
"advanced": {
"customName": "build url output",
"customNameId": 0,
"description": "Generate an observable dictionary to output into the observables data path.",
"join": [],
"note": "Generate an observable dictionary to output into the observables data path."
},
"functionId": 2,
"functionName": "build_url_output",
"id": "6",
"inputParameters": [
"filtered-data:url_result_filter:condition_1:url_reputation:action_result.parameter.url",
"filtered-data:url_result_filter:condition_1:url_reputation:action_result.data.*.phish_detail_page",
"normalize_score_url:custom_function:url_score_object",
"parse_url:custom_function_result.data"
],
"outputVariables": [
"observable_array"
],
"type": "code"
},
"errors": {},
"id": "6",
"type": "code",
"userCode": "\n # Assign variables\n build_url_output__observable_array = []\n url_list = filtered_result_0_parameter_url\n parsed_url_list = parse_url_data\n detail_page_list = filtered_result_0_data___phish_detail_page\n url_reputation_list = normalize_score_url__url_score_object\n \n for url, detail_page, parsed_url, url_rep in zip(url_list, detail_page_list, parsed_url_list, url_reputation_list):\n observable_object = {\n \"value\": url,\n \"type\": \"url\",\n \"reputation\": {\n \"score_id\": url_rep['score_id'],\n \"score\": url_rep['score'],\n },\n \"attributes\": {\n \"hostname\": parsed_url['hostname'],\n \"scheme\": parsed_url['scheme']\n },\n \"source\": \"PhishTank\",\n \"source_link\": detail_page\n }\n if parsed_url['path']:\n observable_object['attributes']['path'] = parsed_url['path']\n if parsed_url['query']:\n observable_object['attributes']['query'] = parsed_url['query']\n if parsed_url['port']:\n observable_object['attributes']['query'] = parsed_url['query']\n \n build_url_output__observable_array.append(observable_object)\n\n",
"warnings": {},
"x": 0,
"y": 1020
},
"7": {
"data": {
"advanced": {
"customName": "parse url",
"customNameId": 0,
"join": []
},
"customFunction": {
"draftMode": false,
"name": "url_parse",
"repoName": "community"
},
"functionId": 1,
"functionName": "parse_url",
"id": "7",
"selectMore": false,
"type": "utility",
"utilities": {
"url_parse": {
"description": "Separate a URL into its components using urlparse() from the urllib module of Python 3.",
"fields": [
{
"dataTypes": [
"url"
],
"description": "The URL to parse",
"inputType": "item",
"label": "input_url",
"name": "input_url",
"placeholder": "artifact:*.cef.requestUrl",
"renderType": "datapath",
"required": false
}
],
"label": "url_parse",
"name": "url_parse"
}
},
"utilityType": "custom_function",
"values": {
"url_parse": {
"input_url": "filtered-data:url_result_filter:condition_1:url_reputation:action_result.parameter.url"
}
}
},
"errors": {},
"id": "7",
"type": "utility",
"warnings": {},
"x": 0,
"y": 860
}
},
"notes": "Inputs: url\nInteractions: PhishTank\nActions: url reputation\nOutputs: report, observables"
},
"input_spec": [
{
"contains": [
"url"
],
"description": "A URL provided for reputation analysis",
"name": "url"
}
],
"output_spec": [
{
"contains": [],
"datapaths": [
"build_url_output:custom_function:observable_array"
],
"deduplicate": false,
"description": "An array of observable dictionaries with value, type, and reputation.",
"metadata": {},
"name": "observable"
},
{
"contains": [],
"datapaths": [
"format_report_url:formatted_data"
],
"deduplicate": false,
"description": "A formatted report.",
"metadata": {},
"name": "markdown_report"
}
],
"playbook_type": "data",
"python_version": "3",
"schema": "5.0.8",
"version": "5.5.0.108488"
},
"create_time": "2023-01-09T21:06:56.266161+00:00",
"draft_mode": false,
"labels": [
"*"
],
"tags": [
"D3-URA",
"D3-IRA",
"reputation",
"url",
"PhishTank"
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

@@ -0,0 +1,320 @@
"""
Accepts a URL and does reputation analysis on the objects. Generates a global report and a per observable sub-report and normalized score. The score can be customized as desired.\n\nRef: https://d3fend.mitre.org/technique/d3f:IdentifierReputationAnalysis/
"""
import phantom.rules as phantom
import json
from datetime import datetime, timedelta
@phantom.playbook_block()
def on_start(container):
phantom.debug('on_start() called')
# call 'url_reputation' block
url_reputation(container=container)
return
@phantom.playbook_block()
def url_reputation(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
phantom.debug("url_reputation() called")
# phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
################################################################################
# Queries PhishTank for information about the provided URL(s)
################################################################################
playbook_input_url = phantom.collect2(container=container, datapath=["playbook_input:url"])
parameters = []
# build parameters list for 'url_reputation' call
for playbook_input_url_item in playbook_input_url:
if playbook_input_url_item[0] is not None:
parameters.append({
"url": playbook_input_url_item[0],
})
################################################################################
## Custom Code Start
################################################################################
# Write your custom code here...
################################################################################
## Custom Code End
################################################################################
phantom.act("url reputation", parameters=parameters, name="url_reputation", assets=["phishtank"], callback=url_result_filter)
return
@phantom.playbook_block()
def normalize_score_url(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
phantom.debug("normalize_score_url() called")
################################################################################
# Contains custom code for normalizing score. Adjust the logic as desired in the
# documented sections.
################################################################################
filtered_result_0_data_url_result_filter = phantom.collect2(container=container, datapath=["filtered-data:url_result_filter:condition_1:url_reputation:action_result.summary.In_Database","filtered-data:url_result_filter:condition_1:url_reputation:action_result.summary.Valid","filtered-data:url_result_filter:condition_1:url_reputation:action_result.summary.Verified"])
filtered_result_0_summary_in_database = [item[0] for item in filtered_result_0_data_url_result_filter]
filtered_result_0_summary_valid = [item[1] for item in filtered_result_0_data_url_result_filter]
filtered_result_0_summary_verified = [item[2] for item in filtered_result_0_data_url_result_filter]
normalize_score_url__url_score_object = None
normalize_score_url__scores = None
################################################################################
## Custom Code Start
################################################################################
# Assign variables
normalize_score_url__url_score_object = []
normalize_score_url__scores = []
in_database_list = filtered_result_0_summary_in_database
valid_list = filtered_result_0_summary_valid
verified_list = filtered_result_0_summary_verified
# Reference for scores: https://schema.ocsf.io/objects/reputation
score_table = {
"-1": "Other",
"0":"Unknown",
"1":"Very_Safe",
"2":"Safe",
"3":"Probably_Safe",
"4":"Leans_Safe",
"5":"May_not_be_Safe",
"6":"Exercise_Caution",
"7":"Suspicious_or_Risky",
"8":"Possibly_Malicious",
"9":"Probably_Malicious",
"10":"Malicious"
}
# PhishTank URL Data
# Adjust logic as desired
for in_database, valid, verified in zip(in_database_list, valid_list, verified_list):
# Condition 1 - In database but verified not valid phish
if in_database and verified and not valid:
score_id = "2"
# Condition 2 - In database and valid phish
elif in_database and valid:
score_id = "10"
# Condition 3 - In database but not verified
elif in_database and not verified:
score_id = "5"
# Condition 4 - Not in database
elif not in_database:
score_id = "0"
# Condition 5 - Catch all
else:
score_id = "-1"
score = score_table[score_id]
normalize_score_url__url_score_object.append(
{
'score': score,
'score_id': score_id
}
)
normalize_score_url__scores.append(score)
################################################################################
## Custom Code End
################################################################################
phantom.save_run_data(key="normalize_score_url:url_score_object", value=json.dumps(normalize_score_url__url_score_object))
phantom.save_run_data(key="normalize_score_url:scores", value=json.dumps(normalize_score_url__scores))
format_report_url(container=container)
return
@phantom.playbook_block()
def url_result_filter(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
phantom.debug("url_result_filter() called")
################################################################################
# Filters successful url reputation results.
################################################################################
# collect filtered artifact ids and results for 'if' condition 1
matched_artifacts_1, matched_results_1 = phantom.condition(
container=container,
conditions=[
["url_reputation:action_result.status", "==", "success"]
],
name="url_result_filter:condition_1")
# call connected blocks if filtered artifacts or results
if matched_artifacts_1 or matched_results_1:
normalize_score_url(action=action, success=success, container=container, results=results, handle=handle, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
return
@phantom.playbook_block()
def format_report_url(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
phantom.debug("format_report_url() called")
################################################################################
# Format a summary table with the information gathered from the playbook.
################################################################################
template = """SOAR analyzed URL(s) using PhishTank. The table below shows a summary of the information gathered.\n\n| URL | Normalized Score | Report Link | Source |\n| --- | --- | --- | --- |\n%%\n| `{0}` | {1} | {2} | PhishTank |\n%%"""
# parameter list for template variable replacement
parameters = [
"filtered-data:url_result_filter:condition_1:url_reputation:action_result.parameter.url",
"normalize_score_url:custom_function:scores",
"filtered-data:url_result_filter:condition_1:url_reputation:action_result.data.*.phish_detail_page"
]
################################################################################
## Custom Code Start
################################################################################
# Write your custom code here...
################################################################################
## Custom Code End
################################################################################
phantom.format(container=container, template=template, parameters=parameters, name="format_report_url")
parse_url(container=container)
return
@phantom.playbook_block()
def build_url_output(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
phantom.debug("build_url_output() called")
################################################################################
# Generate an observable dictionary to output into the observables data path.
################################################################################
filtered_result_0_data_url_result_filter = phantom.collect2(container=container, datapath=["filtered-data:url_result_filter:condition_1:url_reputation:action_result.parameter.url","filtered-data:url_result_filter:condition_1:url_reputation:action_result.data.*.phish_detail_page"])
parse_url__result = phantom.collect2(container=container, datapath=["parse_url:custom_function_result.data"])
normalize_score_url__url_score_object = json.loads(_ if (_ := phantom.get_run_data(key="normalize_score_url:url_score_object")) != "" else "null") # pylint: disable=used-before-assignment
filtered_result_0_parameter_url = [item[0] for item in filtered_result_0_data_url_result_filter]
filtered_result_0_data___phish_detail_page = [item[1] for item in filtered_result_0_data_url_result_filter]
parse_url_data = [item[0] for item in parse_url__result]
build_url_output__observable_array = None
################################################################################
## Custom Code Start
################################################################################
# Assign variables
build_url_output__observable_array = []
url_list = filtered_result_0_parameter_url
parsed_url_list = parse_url_data
detail_page_list = filtered_result_0_data___phish_detail_page
url_reputation_list = normalize_score_url__url_score_object
for url, detail_page, parsed_url, url_rep in zip(url_list, detail_page_list, parsed_url_list, url_reputation_list):
observable_object = {
"value": url,
"type": "url",
"reputation": {
"score_id": url_rep['score_id'],
"score": url_rep['score'],
},
"attributes": {
"hostname": parsed_url['hostname'],
"scheme": parsed_url['scheme']
},
"source": "PhishTank",
"source_link": detail_page
}
if parsed_url['path']:
observable_object['attributes']['path'] = parsed_url['path']
if parsed_url['query']:
observable_object['attributes']['query'] = parsed_url['query']
if parsed_url['port']:
observable_object['attributes']['query'] = parsed_url['query']
build_url_output__observable_array.append(observable_object)
################################################################################
## Custom Code End
################################################################################
phantom.save_run_data(key="build_url_output:observable_array", value=json.dumps(build_url_output__observable_array))
return
@phantom.playbook_block()
def parse_url(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
phantom.debug("parse_url() called")
filtered_result_0_data_url_result_filter = phantom.collect2(container=container, datapath=["filtered-data:url_result_filter:condition_1:url_reputation:action_result.parameter.url"])
parameters = []
# build parameters list for 'parse_url' call
for filtered_result_0_item_url_result_filter in filtered_result_0_data_url_result_filter:
parameters.append({
"input_url": filtered_result_0_item_url_result_filter[0],
})
################################################################################
## Custom Code Start
################################################################################
# Write your custom code here...
################################################################################
## Custom Code End
################################################################################
phantom.custom_function(custom_function="community/url_parse", parameters=parameters, name="parse_url", callback=build_url_output)
return
@phantom.playbook_block()
def on_finish(container, summary):
phantom.debug("on_finish() called")
format_report_url = phantom.get_format_data(name="format_report_url")
build_url_output__observable_array = json.loads(_ if (_ := phantom.get_run_data(key="build_url_output:observable_array")) != "" else "null") # pylint: disable=used-before-assignment
output = {
"observable": build_url_output__observable_array,
"markdown_report": format_report_url,
}
################################################################################
## Custom Code Start
################################################################################
# Write your custom code here...
################################################################################
## Custom Code End
################################################################################
phantom.save_playbook_output_data(output=output)
return
@@ -0,0 +1,25 @@
name: PhishTank URL Reputation Analysis
id: fc0eab96-ff1b-45b0-9b4d-63ca4783fd64
version: 1
date: '2023-01-11'
author: Kelby Shelton, Splunk
type: Investigation
description: "Accepts a URL and does reputation analysis on the objects. Generates a global report and a per observable sub-report and normalized score. The score can be customized as desired."
playbook: PhishTank_URL_Reputation_Analysis
how_to_implement: This input playbook requires the PhishTank connector to be configured. It is designed to work in conjunction with the Dynamic Identifier Reputation Analysis playbook or other playbooks in the same style.
references:
- https://d3fend.mitre.org/technique/d3f:IdentifierReputationAnalysis/
app_list:
- PhishTank
tags:
platform_tags:
- D3-IRA
- D3-URA
- reputation
- url
- PhishTank
playbook_type: Input
vpe_type: Modern
playbook_fields: []
product:
- Splunk SOAR
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

File diff suppressed because it is too large Load Diff
@@ -0,0 +1,31 @@
name: VirusTotal v3 Identifier Reputation Analysis
id: fc0edc96-ff2b-48b0-9b4d-63da67d3fe74
version: 1
date: '2023-01-11'
author: Kelby Shelton, Lou Stella, Splunk
type: Investigation
description: "Accepts a URL, IP, Domain, or File_Hash and does reputation analysis on the objects. Generates a global report and a per observable sub-report and normalized score. The score can be customized based on a variety of factors."
playbook: VirusTotal_v3_Identifier_Reputation_Analysis
how_to_implement: This input playbook requires the VirusTotal v3 connector to be configured. It is designed to work in conjunction with the Dynamic Identifier Reputation Analysis playbook or other playbooks in the same style.
references:
- https://d3fend.mitre.org/technique/d3f:IdentifierReputationAnalysis/
app_list:
- VirusTotal v3
tags:
platform_tags:
- reputation
- url
- ip
- domain
- file_hash
- D3-IRA
- D3-URA
- D3-DNRA
- D3-IPRA
- D3-FHRA
- VirusTotal_v3
playbook_type: Input
vpe_type: Modern
playbook_fields: []
product:
- Splunk SOAR