Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
12 changes: 12 additions & 0 deletions Splunk SOAR/DomainTools_Feeds_Domain_Hotlist/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## DomainTools Feeds Domain Hotlist Playbook

This playbook retrieves newly observed domains from DomainTools Real Time Unified Feeds from a given `sessionID`, `before`, and/or `after` params. It will save the Domain Hotlist feeds list in a csv file with naming convention - `domaintools_feed_domain_hotlist_<YYYYMMDD>_<hhmmss>.csv`. The flow will continue to retrieve Domain Hotlist feeds based on the scheduled run

#### DomainTools API Asset

**The DomainTools playbooks in this repo will require an asset called `domaintoolscreds`** for a DomainTools API username and key. This asset is used to retrieve Domain Hotlist feeds data via the DomainTools API during playbook execution. Current action selected is `domain_hotlist_feed` and it requires `sessionID`, `before`, and/or `after` input parameters. Optional input parameters are `domain` and `top`.
<br>

#### Installation

Download the tar file in this directory and import the playbook using that file. The asset accessed in the playbook is for DomainTools API credentials. Point the playbook to the `domaintoolscreds` asset, save the playbook, make sure it's active, and give it a shot.
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
{
"blockly": false,
"blockly_xml": "<xml></xml>",
"category": "Uncategorized",
"coa": {
"data": {
"description": "",
"edges": [
{
"id": "port_0_to_port_2",
"sourceNode": "0",
"sourcePort": "0_out",
"targetNode": "2",
"targetPort": "2_in"
},
{
"id": "port_2_to_port_3",
"sourceNode": "2",
"sourcePort": "2_out",
"targetNode": "3",
"targetPort": "3_in"
},
{
"id": "port_3_to_port_1",
"sourceNode": "3",
"sourcePort": "3_out",
"targetNode": "1",
"targetPort": "1_in"
}
],
"hash": "286c15eed27262925745bfb80a40129e99bc925f",
"nodes": {
"0": {
"data": {
"advanced": {
"join": []
},
"functionName": "on_start",
"id": "0",
"type": "start"
},
"errors": {},
"id": "0",
"type": "start",
"warnings": {},
"x": 19.999999999999986,
"y": -1.2789769243681803e-13
},
"1": {
"data": {
"advanced": {
"join": []
},
"functionName": "on_finish",
"id": "1",
"type": "end"
},
"errors": {},
"id": "1",
"type": "end",
"warnings": {},
"x": 19.999999999999986,
"y": 443.9999999999998
},
"2": {
"data": {
"action": "domain hotlist feed",
"actionType": "investigate",
"advanced": {
"join": []
},
"connector": "DomainTools Iris Investigate",
"connectorConfigs": [
"domaintoolscreds"
],
"connectorId": "f18b7ef9-0cbd-4dbb-b8ed-ce62e17f0603",
"connectorVersion": "v1",
"functionId": 1,
"functionName": "domain_hotlist_feed_1",
"id": "2",
"loop": {
"enabled": false,
"exitAfterUnit": "m",
"exitAfterValue": 10,
"exitConditionEnabled": false,
"exitLoopAfter": 2,
"pauseUnit": "m",
"pauseValue": 2
},
"parameters": {
"before": "",
"session_id": "integrations-testing",
"top": ""
},
"requiredParameters": [],
"type": "action"
},
"errors": {},
"id": "2",
"type": "action",
"userCode": "\n # Write your custom code here...\n\n",
"warnings": {},
"x": 0,
"y": 140
},
"3": {
"data": {
"advanced": {
"customName": "output domain risk list",
"customNameId": 0,
"join": []
},
"functionId": 1,
"functionName": "output_domain_risk_list",
"id": "3",
"inputParameters": [
"domain_hotlist_feed_1:action_result.data"
],
"outputVariables": [],
"type": "code"
},
"errors": {},
"id": "3",
"type": "code",
"userCode": "\n # Write your custom code here...\n from datetime import datetime\n import csv\n \n event_name = container.get(\"name\")\n file_name = f\"domaintools_feed_domain_hotlist_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv\"\n phantom.debug(f\"dt debug - exporting Domain Hotlist to {file_name} file.\")\n \n with open(f\"/opt/phantom/vault/tmp/{file_name}\", \"w\", newline='') as report_csv_file:\n headers = [\"domain\", \"timestamp\", \"phishing_risk\", \"malware_risk\", \"spam_risk\", \"proximity_risk\", \"overall_risk\", \"expires\"]\n writer = csv.DictWriter(report_csv_file, fieldnames=headers)\n \n writer.writeheader()\n for data in domain_hotlist_feed_1_result_item_0[0] or []:\n writer.writerow(data)\n \n # Define the CEF data in a Python dictionary\n cef_data = {\n \"destinationDnsDomain\": data.get(\"domain\"),\n \"timestamp\": data.get(\"timestamp\"),\n \"phishing_risk\": data.get(\"phishing_risk\"),\n \"malware_risk\": data.get(\"malware_risk\"),\n \"spam_risk\": data.get(\"spam_risk\"),\n \"proximity_risk\": data.get(\"proximity_risk\"),\n \"overall_risk\": data.get(\"overall_risk\"),\n \"expires\": data.get(\"expires\"),\n }\n # Use the dictionary to create a new artifact\n phantom.add_artifact(\n container=container,\n label=\"domaintools-realtime-feeds\",\n severity=\"high\",\n name=\"Domain Hotlist Feed\",\n cef_data=cef_data\n )\n\n success, message, vault_id = phantom.vault_add(container=container, file_location=f\"/opt/phantom/vault/tmp/{file_name}\", file_name=file_name)\n \n if not success:\n phantom.error(f\"dt error - Error creating {file_name} file. Message: {message}\")\n return\n\n\n",
"warnings": {},
"x": 0,
"y": 300
}
},
"notes": "",
"origin": {
"playbook_id": 364,
"playbook_name": "DomainTools Feeds Domain Risk",
"playbook_repo_id": 2,
"playbook_repo_name": "local"
}
},
"input_spec": null,
"output_spec": null,
"playbook_trigger": "artifact_created",
"playbook_type": "automation",
"python_version": "3",
"schema": "5.0.17",
"version": "6.4.0.90"
},
"create_time": "2025-09-05T18:47:19.464749+00:00",
"draft_mode": false,
"labels": [
"events"
],
"tags": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
"""

"""


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 'domain_hotlist_feed_1' block
domain_hotlist_feed_1(container=container)

return

@phantom.playbook_block()
def domain_hotlist_feed_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, loop_state_json=None, **kwargs):
phantom.debug("domain_hotlist_feed_1() called")

# phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))

parameters = []

parameters.append({
"before": "",
"session_id": "integrations-testing",
"top": "",
})

################################################################################
## Custom Code Start
################################################################################

# Write your custom code here...

################################################################################
## Custom Code End
################################################################################

phantom.act("domain hotlist feed", parameters=parameters, name="domain_hotlist_feed_1", assets=["domaintoolscreds"], callback=output_domain_risk_list)

return


@phantom.playbook_block()
def output_domain_risk_list(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, loop_state_json=None, **kwargs):
phantom.debug("output_domain_risk_list() called")

domain_hotlist_feed_1_result_data = phantom.collect2(container=container, datapath=["domain_hotlist_feed_1:action_result.data"], action_results=results)

domain_hotlist_feed_1_result_item_0 = [item[0] for item in domain_hotlist_feed_1_result_data]

################################################################################
## Custom Code Start
################################################################################

# Write your custom code here...
from datetime import datetime
import csv

event_name = container.get("name")
file_name = f"domaintools_feed_domain_hotlist_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
phantom.debug(f"dt debug - exporting Domain Hotlist to {file_name} file.")

with open(f"/opt/phantom/vault/tmp/{file_name}", "w", newline='') as report_csv_file:
headers = ["domain", "timestamp", "phishing_risk", "malware_risk", "spam_risk", "proximity_risk", "overall_risk", "expires"]
writer = csv.DictWriter(report_csv_file, fieldnames=headers)

writer.writeheader()
for data in domain_hotlist_feed_1_result_item_0[0] or []:
writer.writerow(data)

# Define the CEF data in a Python dictionary
cef_data = {
"destinationDnsDomain": data.get("domain"),
"timestamp": data.get("timestamp"),
"phishing_risk": data.get("phishing_risk"),
"malware_risk": data.get("malware_risk"),
"spam_risk": data.get("spam_risk"),
"proximity_risk": data.get("proximity_risk"),
"overall_risk": data.get("overall_risk"),
"expires": data.get("expires"),
}
# Use the dictionary to create a new artifact
phantom.add_artifact(
container=container,
label="domaintools-realtime-feeds",
severity="high",
name="Domain Hotlist Feed",
cef_data=cef_data
)

success, message, vault_id = phantom.vault_add(container=container, file_location=f"/opt/phantom/vault/tmp/{file_name}", file_name=file_name)

if not success:
phantom.error(f"dt error - Error creating {file_name} file. Message: {message}")
return


################################################################################
## Custom Code End
################################################################################

phantom.save_block_result(key="output_domain_risk_list__inputs:0:domain_hotlist_feed_1:action_result.data", value=json.dumps(domain_hotlist_feed_1_result_item_0))

return


@phantom.playbook_block()
def on_finish(container, summary):
phantom.debug("on_finish() called")

################################################################################
## Custom Code Start
################################################################################

# Write your custom code here...

################################################################################
## Custom Code End
################################################################################

return