Posted by:

David Greenwood

David Greenwood, Chief of Signal

If you are reading this blog post via a 3rd party source it is very likely that many parts of it will not render correctly. Please view the post on signalscorps.com for the full interactive viewing experience.

In this post I will show you how to create a Playbook from scratch.

Note: this tutorial is written for CACAO version 1.1 (published on 2022-03-01). Some of the concepts discussed might not be correct for future versions of CACAO.

The last three weeks have shown you the core concepts to CACAO Playbooks. You are probably drafting some of your own.

In this post I will show you the process I go through to write a playbook from start to finish.

Planning how your Playbook will work is the first critical thing. As you start to write more Playbooks, you can begin to reuse steps created for other Playbooks.

I’m going to build a detection playbook playbook-type: "prevention". This Playbook will update my endpoints and detection tools with high confidence threat intelligence.

It will work like so;

  1. For the start step it will take observables of type IPv4, IPv6, domain, and url (with very high confidence) from a threat intelligence platform (TIP) and use that intelligence to
  2. To keep track of the changes that will follow, a ticket will be opened in my ticket management solution
  3. Then the following parallel steps will happen;
    • The intelligence will be added to my firewall blocklist
    • The intelligence will be added to my EDR blocklist
    • The intelligence will be added to a detection rule in my SIEM
  4. Once these actions are complete, the ticket will updated to detail the changes made and the Playbook will end.

Note, this Playbook is for demonstration purposes and would need some tuning and improvements to be production ready – namely the steps to add to security tooling.

As a visual person before I start, I also like to mockup the playbook in a flow diagram. I turn to PowerPoint to begin with to draw out a user flow (yes, I know that Figma, LucidChart, etc. offer better functionality). Here is what my proposed Playbook looks like;

CACAO prevention playbook flow

You can see the Playbook interacts with my TIP, ticket manager, firewall, EDR and SIEM. In this Playbook, all these interactions can fully automated.

Let’s get to work.

To begin with, I need the general metadata for the playbook;

Which in JSON looks like so;

{
    "type": "playbook",
    "spec_version": "1.1",
    "id": "playbook--cb1642af-d568-422e-95e3-f8108f48fbfa",
    "name": "Add high confidence IOCs to security tooling",
    "description": "This playbook will periodically collect high confidence (>95) observables of type IPv4, IPv6, domain, and url, from the TIP and then send to firewall, SIEM and EDR blocklists. All actions will be logged in the ticket management tool.",
    "playbook_types": [
        "prevention"
    ],
    "created_by": "identity--a99a2297-3044-4011-9a7e-2ff15e056b65",
    "created": "2022-12-26T00:00:00.000Z",
    "modified": "2022-12-26T00:00:00.000Z",
    "severity": 95,
    "external_references": [
        {
            "name": "Signals Corps Blog",
            "url": "https://www.signalscorps.com/blog/"
        }
    ],
    "features": {
        "parallel_processing": true,
        "data_markings": true
    },
    "markings": [
        "marking-tlp--def161e3-0337-4767-8f0b-196324452ae6"
    ],
    "data_marking_definitions": {
        "marking-tlp--def161e3-0337-4767-8f0b-196324452ae6": {
            "type": "marking-tlp",
            "spec_version": "1.1",
            "id": "marking-tlp--def161e3-0337-4767-8f0b-196324452ae6",
            "created": "2021-04-19T23:32:24.399Z",
            "modified": "2021-04-19T23:32:24.399Z",
            "tlp_level": "TLP-GREEN"
        }
    }
}

Now I need to start define each of the steps and how they will work.

The input to initiate the playbook will always be an observable (either an ipv4 address, ipv6 address, url, or domain). Therefore I can also add this as a Playbook variable;

    "playbook_variables": {
        "$$observable$$": {
            "type": "string",
            "description": "Either an ipv4 address, ipv6 address, url, or domain input to the playbook",
            "value": "<value populated dynamically>",
            "constant": true
        }
    }

Note, I use string as the type so this variable con cover all observable types received (versus creating four different variables for each type).

The first step in the playbook is the to get the TIP. In reality, I need some logic in front of the playbook to call the TIP for observables, populate the variable value one by one (because it’s likely more than one will be returned), and start the Playbook. I’m not going to write that out here, not least because I don’t have a TIP of my own, but imagine this logic is written in a shell script which I’ll call in the start step as follows;

        "start--ef7aad50-6408-447b-ae85-c07908a479c2": {
            "type": "start",
            "name": "Get Observable from TIP",
            "description": "Gets an ipv4 address, ipv6 address, url, or domain observable from the TIP to be used in the playbooks",
            "on_completion": "single--91f507ac-cc0a-408c-8eec-5e6de588eff5",
            "commands": [
                {
                    "type": "manual",
                    "command": "Get observable from TIP"
                }
            ]
        }

Now I need to define the next step (single--91f507ac-cc0a-408c-8eec-5e6de588eff5) to open the ticket. First I will define the target;

            "targets": {
                "target--13baefee-52ff-4a2f-8d1d-5f7bde9fae50": {
                    "type": "security-infrastructure-category",
                    "category": ["ticketing"],
                    "name": "ServiceNow"
            }

And then the command;

            "commands": [
                {
                    "type": "bash",
                    "command": "./create_snow_ticket.sh"
                }
            ]

I use another script to trigger this. The logic here would essentially authenticate, structure and send the request ServiceNow.

Put together I get the second step;

        "single--91f507ac-cc0a-408c-8eec-5e6de588eff5": {
            "type": "single",
            "name": "Create ServiceNow Ticket",
            "description": "Keep a audit trail of changes about to me made",
            "on_completion": "parallel--1125c93a-73ea-447c-8827-26edfb4c07f4",
            "targets": {
                "target--13baefee-52ff-4a2f-8d1d-5f7bde9fae50": {
                    "type": "security-infrastructure-category",
                    "category": ["ticketing"],
                    "name": "ServiceNow"
            },
            "commands": [
                {
                    "type": "bash",
                    "command": "./create_snow_ticket.sh $$observable$$"
                }
            ]
        }

You’ll see I also pass the $$observable$$ variable to the script. This can then be used in the script to create a more descriptive ticket, e.g. “Adding $$observable$$ to security tools”.

Now I need to define the three parallel steps to be performed;

  1. Add to firewall blocklist
  2. Add to EDR blocklist
  3. Add to SIEM detection rules

First I need to describe the parrallel step, that will include the three single steps to perform these actions;

        "parallel--1125c93a-73ea-447c-8827-26edfb4c07f4": {
            "type": "parallel",
            "name": "Update security tools",
            "description": "This step will update the firewall, client EDR, and SIEM in parallel",
            "next_steps": [
                "single--34cb6e38-e722-4e6d-b824-d89cd1391ba6",
                "single--f75f6576-58cd-48ca-9689-03427d631d31",
                "single--672d8cf9-2734-479f-8bd0-f16473193072"
            ]
        }

Breaking these out into the three single steps;

Firewall;

        "single--34cb6e38-e722-4e6d-b824-d89cd1391ba6": {
            "type": "single",
            "name": "Add to firewall blocklist",
            "description": "Add the observable to CISCO ASA",
            "on_completion": "end--b9bda8c2-8345-4f69-a4b1-c1296d116869",
            "targets": {
                "target--c570618b-12f4-4d3e-9dd7-6bbf44667e8d": {
                    "type": "security-infrastructure-category",
                    "category": ["firewall"],
                    "name": "Cisco"
            },
            "commands": [
                {
                    "type": "bash",
                    "command": "./add_to_firewall_blocklist.sh"
                }
            ]
        }

EDR;

        "single--f75f6576-58cd-48ca-9689-03427d631d31": {
            "type": "single",
            "name": "Add to EDR blocklist",
            "description": "Add the observable to Crowdstrike endpoints",
            "on_completion": "end--b9bda8c2-8345-4f69-a4b1-c1296d116869",
            "targets": {
                "target--49f5f029-fcf9-4b75-a90a-749aff404a63": {
                    "type": "security-infrastructure-category",
                    "category": ["endpoint"],
                    "name": "Crowdstrike"
            },
            "commands": [
                {
                    "type": "bash",
                    "command": "./add_to_edr_blocklist.sh"
                }
            ]
        }

SIEM

        "single--672d8cf9-2734-479f-8bd0-f16473193072": {
            "type": "single",
            "name": "Add to SIEM detection searches",
            "description": "Add the observable to Splunk threat intel KVstore",
            "on_completion": "end--b9bda8c2-8345-4f69-a4b1-c1296d116869",
            "targets": {
                "target--e4b6fd0b-9d08-472d-83b0-d9c388d510d1": {
                    "type": "security-infrastructure-category",
                    "category": ["siem"],
                    "name": "Splunk"
            },
            "commands": [
                {
                    "type": "bash",
                    "command": "./add_as_detection_rule.sh"
                }
            ]
        }

You will see these three parrallel steps all point to a single step (end--b9bda8c2-8345-4f69-a4b1-c1296d116869) – that is closing the ticket. This is the end step in our flow, as the ID shows.

        "end--b9bda8c2-8345-4f69-a4b1-c1296d116869": {
            "type": "end",
            "name": "Close the ServiceNow ticket",
            "description": "Close the service now ticket",
            "targets": {
                "target--13baefee-52ff-4a2f-8d1d-5f7bde9fae50": {
                    "type": "security-infrastructure-category",
                    "category": ["ticketing"],
                    "name": "ServiceNow"
            },
            "commands": [
                {
                    "type": "bash",
                    "command": "./close_snow_ticket.sh $$observable$$"
                }
            ]
        }

You will likely need to capture the responses of some steps (e.g. the ticket ID generated by ServiceNow in the second step and load this as its own variable in the Playbook). My simple approach for this demo assumes the observable value alone can be used to identify the ticket (which is very unlikely and/or very erroneous).

Putting this altogether, I have the complete Playbook;

{
    "type": "playbook",
    "spec_version": "1.1",
    "id": "playbook--cb1642af-d568-422e-95e3-f8108f48fbfa",
    "name": "Add high confidence IOCs to security tooling",
    "description": "This playbook will periodically collect high confidence (>95) observables of type IPv4, IPv6, domain, and url, from the TIP and then send to firewall, SIEM and EDR blocklists. All actions will be logged in the ticket management tool.",
    "playbook_types": [
        "prevention"
    ],
    "created_by": "identity--a99a2297-3044-4011-9a7e-2ff15e056b65",
    "created": "2022-12-26T00:00:00.000Z",
    "modified": "2022-12-26T00:00:00.000Z",
    "severity": 95,
    "external_references": [
        {
            "name": "Signals Corps Blog",
            "url": "https://www.signalscorps.com/blog/"
        }
    ],
    "features": {
        "parallel_processing": true,
        "data_markings": true
    },
    "markings": [
        "marking-tlp--def161e3-0337-4767-8f0b-196324452ae6"
    ],
    "data_marking_definitions": {
        "marking-tlp--def161e3-0337-4767-8f0b-196324452ae6": {
            "type": "marking-tlp",
            "spec_version": "1.1",
            "id": "marking-tlp--def161e3-0337-4767-8f0b-196324452ae6",
            "created": "2021-04-19T23:32:24.399Z",
            "modified": "2021-04-19T23:32:24.399Z",
            "tlp_level": "TLP-GREEN"
        }
    },
    "workflow_start": "start--ef7aad50-6408-447b-ae85-c07908a479c2",
    "workflow": {
        "start--ef7aad50-6408-447b-ae85-c07908a479c2": {
            "type": "start",
            "name": "Get Observable from TIP",
            "description": "Gets an ipv4 address, ipv6 address, url, or domain observable from the TIP to be used in the playbooks",
            "on_completion": "single--91f507ac-cc0a-408c-8eec-5e6de588eff5",
            "commands": [
                {
                    "type": "manual",
                    "command": "Get observable from TIP"
                }
            ]
        },
        "single--91f507ac-cc0a-408c-8eec-5e6de588eff5": {
            "type": "single",
            "name": "Create ServiceNow Ticket",
            "description": "Keep a audit trail of changes about to me made",
            "on_completion": "parallel--1125c93a-73ea-447c-8827-26edfb4c07f4",
            "targets": {
                "target--13baefee-52ff-4a2f-8d1d-5f7bde9fae50": {
                    "type": "security-infrastructure-category",
                    "category": ["ticketing"],
                    "name": "ServiceNow"
            },
            "commands": [
                {
                    "type": "bash",
                    "command": "./create_snow_ticket.sh $$observable$$"
                }
            ]
        },
        "parallel--1125c93a-73ea-447c-8827-26edfb4c07f4": {
            "type": "parallel",
            "name": "Update security tools",
            "description": "This step will update the firewall, client EDR, and SIEM in parallel",
            "next_steps": [
                "single--34cb6e38-e722-4e6d-b824-d89cd1391ba6",
                "single--f75f6576-58cd-48ca-9689-03427d631d31",
                "single--672d8cf9-2734-479f-8bd0-f16473193072"
            ]
        },
        "single--34cb6e38-e722-4e6d-b824-d89cd1391ba6": {
            "type": "single",
            "name": "Add to firewall blocklist",
            "description": "Add the observable to CISCO ASA",
            "on_completion": "end--b9bda8c2-8345-4f69-a4b1-c1296d116869",
            "targets": {
                "target--c570618b-12f4-4d3e-9dd7-6bbf44667e8d": {
                    "type": "security-infrastructure-category",
                    "category": ["firewall"],
                    "name": "Cisco"
            },
            "commands": [
                {
                    "type": "bash",
                    "command": "./add_to_firewall_blocklist.sh"
                }
            ]
        },
        "single--f75f6576-58cd-48ca-9689-03427d631d31": {
            "type": "single",
            "name": "Add to EDR blocklist",
            "description": "Add the observable to Crowdstrike endpoints",
            "on_completion": "end--b9bda8c2-8345-4f69-a4b1-c1296d116869",
            "targets": {
                "target--49f5f029-fcf9-4b75-a90a-749aff404a63": {
                    "type": "security-infrastructure-category",
                    "category": ["endpoint"],
                    "name": "Crowdstrike"
            },
            "commands": [
                {
                    "type": "bash",
                    "command": "./add_to_edr_blocklist.sh"
                }
            ]
        },
        "single--672d8cf9-2734-479f-8bd0-f16473193072": {
            "type": "single",
            "name": "Add to SIEM detection searches",
            "description": "Add the observable to Splunk threat intel KVstore",
            "on_completion": "end--b9bda8c2-8345-4f69-a4b1-c1296d116869",
            "targets": {
                "target--e4b6fd0b-9d08-472d-83b0-d9c388d510d1": {
                    "type": "security-infrastructure-category",
                    "category": ["siem"],
                    "name": "Splunk"
            },
            "commands": [
                {
                    "type": "bash",
                    "command": "./add_as_detection_rule.sh"
                }
            ]
        },
        "end--b9bda8c2-8345-4f69-a4b1-c1296d116869": {
            "type": "end",
            "name": "Close the ServiceNow ticket",
            "description": "Close the service now ticket",
            "targets": {
                "target--13baefee-52ff-4a2f-8d1d-5f7bde9fae50": {
                    "type": "security-infrastructure-category",
                    "category": ["ticketing"],
                    "name": "ServiceNow"
            },
            "commands": [
                {
                    "type": "bash",
                    "command": "./close_snow_ticket.sh $$observable$$"
                }
            ]
        }
    }
}

The CACAO specification also describes the process of signing Playbooks to add an additional level of data security.

All the Playbooks I create are public by default and can be downloaded from public sources so this is less of a concern to me right now, and will be ignored in this post.

CONGRATULATIONS!

You have made it to the end of this short course.

CACAO Playbooks are still in draft phases. If you’re reading these posts a few months after publication you should beware they might be slightly outdated and lacking some of the newer features.

I’m hopeful we’ll see CACAO take off as a playbook standard in the coming years.

If you have any questions about the content in this tutorial, please do not hesitate to drop us a message on Slack.


CACAO Certification (Virtual and In Person)

The content used in this post is a small subset of our full training material used in our CACAO training.

If you want to join a select group of certified CACAO professionals, subscribe to our newsletter below to be notified of new course dates.




Discuss this post


Signals Corps Slack

Never miss an update


Sign up to receive new articles in your inbox as they published.