Hi all,
We are glad to announce a reusable playbook called Sub-Playbook is delivered in v45. Now, designers can create sub-playbooks to define repeatable activities to use within other playbooks.
A Sub-Playbook is a set of packaged activities that can be placed in a Playbook. When created, the sub-playbook will be able to contain all the objects of a normal playbook in order to minimize complexity and maximize reusability. By using sub-playbooks, Playbook Designers can split a complex process into multiple separate components which allow users to focus on discrete problems.
To be able to use sub-playbook within playbook, you will have to construct the sub-playbook (inputs, compose the canvas, and output reference) first in the following manners:
- Declare inputs (fields, object type, output reference) of the sub-playbook
- Building the sub-playbook on canvas, and operating the data from the triggering playbook
- Define the sub-playbook result output in end point
After sub-playbook is created, you may add and configure the sub-playbook node within playbook so the initiating playbook can pass data as inputs and get data from the sub-playbook output.
There is a post introduced function-based artifact enrichment previously. In this post we will leverage that feature and make it more flexible and reusable with sub-playbook as an example:
1. Create a Sub-playbook, the Start Point panel displays. Add artifact_value
as an input form element to pass the input data from parent playbook when sub-playbook starts. Choose the Artifact as object type. The object type defines the type of input data from the parent playbook.
2. Create condition point, set Artifact Type = built-in artifact type [Malware MD5 hash] as the condition since we only want MD5 hash artifacts to be scanned here.
3. Config VirusTotal Function Inputs to pass artifact type and value from the input form element playbook.inputs.artifact_value
.
4. Process VirusTotal function result. Make Hit publishing criteria via python3 in-product script composed of VT’s detection rate (external TI) and artifact properties (local historical reference). This is based on function-based enrichment to add a Hit card from the scan result. Set the hit criteria to detection rate >= 60%
## Construct artifact hit card from VirusTotal scan result
def add_hit_card():
hit = [
{
"name": "Positives",
"type": "string",
"value": "{} out of {}".format(playbook.functions.results.report.scan.get('positives'), playbook.functions.results.report.scan.get('total'))
},
{
"name": "Scan Date",
"type": "string",
"value": "{}".format(playbook.functions.results.report.scan.get('scan_date'))
},
{
"name": "Scan Report",
"type": "uri",
"value": "{}".format(playbook.functions.results.report.scan.get('permalink'))
}
]
artifact.addHit("VT Function hits added", hit)
msg = u"<p>Artifact: {}</p>".format(artifact.value)
## Determine wheather to add artifact hit if positives scan is returned
if playbook.functions.results.report.scan.get('positives') is not None:
## Define hit threshold and calculate detection rate
HIT_THRESHOLD = 0.6
detection_rate = float(playbook.functions.results.report.scan.get('positives'))/float(playbook.functions.results.report.scan.get('total'))
## Add artifact hit if detection rate >= 60%
if detection_rate >= HIT_THRESHOLD:
add_hit_card()
5. Config End point script, you need to write a script to make that result available to the parent playbook. Here we create a scan summary with the calculated detection rate and the report's permalink. The result is stored in playbook.results
. The End point has a default script with lines that are commented out to help you start. If you do not need to send a result, uncomment the playbook.results = None
line.
def mk_report(link):
return u"<a target='blank' href='{}'>VirusTotal Report</a></p>".format(link)
if playbook.functions.results.report.scan.get('positives') is not None:
## Calculate detection rate
detection_rate = float(playbook.functions.results.report.scan.get('positives'))/float(playbook.functions.results.report.scan.get('total'))
msg = u"<p>Artifact: {}</p>".format(playbook.inputs.artifact_value)
msg = msg + u"<p>Positives: <span style='color:red'>{}</span> out of {} (detection rate is {:.2f}) </p> <p>{}</p>".format(playbook.functions.results.report.scan.get('positives'), playbook.functions.results.report.scan.get('total'), detection_rate, mk_report(playbook.functions.results.report.scan.get('permalink')))
playbook.results = {'msg': msg}
else:
playbook.results = None
6. Config sub-playbook node in parent playbook, you can either use fields or script to manually/programmatically define the input. Here we pass the artifact value as the sub-playbook's input inputs.artifact_value
which is defined in sub-playbook input form. For more information, see Input script and Playbook operations.
7. Get sub-playbook output result from playbook.subplaybooks.results.vt_scan_result
and add to the incident note.
result = playbook.subplaybooks.results.vt_scan_result
if result is not None:
incident.addNote(helper.createRichText(u"<div>{}</div>".format(result['msg'])))
8. Enable the sub-playbook and its parent playbook, create a malicious MD5 hash artifact then run playbook with sub-playbook. The Hit card is added and the summary of scan result is posted in Incident Note.
We hope with Sub-Playbook feature, Playbook designers are able to build and reuse collections of Tasks, Scripts, Functions, Condition Points, and Sub-Playbooks in a Playbook to standardize activities and accelerate the Playbook development process.
Have fun!
This playbook can be downloaded, here:
https://ibm.box.com/v/ArtEnrichPlaybook
For more information, see:
https://www.ibm.com/docs/en/sqsp/45?topic=playbook-sub
-----------------------------------
Sam Wang, IBM Security QRadar SOAR