Automating Detection-as-Code

Written by John TucknerHead of Research at Tines Labs, Tines

Published on June 30, 2022

This article was posted more than 18 months ago.

In cybersecurity, there has been a shift to adopt more software development principles in order to create security solutions quickly and reliably. Utilization of tools like Git and Continuous Integration/Continuous Deployment (CICD) pipelines have become more common to achieve reliable deployments. At Tines, while we strive to make automation accessible to anyone without development skills, our platform is also highly flexible to accommodate developer-centric uses.

"Detection-as-code” is one such introduction of development principles into cybersecurity. Detection-as-code is a means of managing detection rules and other content for SIEM or XDR in a more structured fashion. Generally, to create a new detection rule or improve an existing one, an analyst would go into the tool's console and utilize that tool's capabilities to make the changes. The changes in the user interface are usually difficult to keep track of and provide little in the way of peer review compared to how software developers update an application. As a result, Detection-as-code has begun utilizing APIs and deployment pipelines to provide the desired auditing capabilities moving security operations closer to software development.

Ideas for detection rules are more prevalent than ever and are shared pervasively on platforms like GitHub. Companies and communities such as Sigma, SOC Prime, Microsoft, and Elastic are all contributing to the public good by sharing their research and rules for use by anyone. The platforms they use to share this content fit nicely into the GitHub Flow model for software development.

Now that more resources are available in platforms that adhere to current software development models, the open-ended question is how to go about actually utilizing all of these resources for security tooling. Of course, it depends on the platforms your organization utilizes, but a major hurdle to getting started is having access to a working example to reference. This article and associated resources aim to be that reference to get started.

Environment overview 

We’ve chosen some widely used and very accessible platforms for you to be able to utilize some of the examples provided.

  • Elastic: SIEM

  • GitHub: detection content development

  • GitHub Actions: CI/CD

  • GitHub Issues: SIEM alert management

  • Tines: alert and response handling

Many other platforms for SIEM or CICD could be used in place of these, but the concepts outlined to start with detection-as-code should not change significantly. Code examples and references mentioned here are contained in this repository unless otherwise noted.

Elastic SIEM configuration 

Using Elastic Cloud is the fastest way to get started with Elastic SIEM. After signing up for an account and creating a new deployment, Elastic SIEM will be available for use.

Using any of the rules listed, we’ll create an Action that will send any detections to a Tines webhook so we can handle alerts that are produced. By doing this, we can also use this webhook destination in other rules we’ll create.

This is the configuration used for the Action:

[{{#context.alerts}}{{{.}}},{{/context.alerts}}null]

Additionally, set a custom header of content-type: text/plain.Once the Action is created, we export the rule to get the raw configuration of the Action, like the Action ID, that we will use later when we’re writing our rule as code.

The Elastic detection rules repository 

Elastic provides its detection rules and takes contributions in a GitHub repository. Every time a new rule is added to their repository, a number of checks and tests are run to ensure that the rules will be deployed successfully to Elastic SIEM. These checks form a starting point for our uses as well.

Fork or clone Elastic's repository to create a new version to modify. This will enable all changes, such as new rules, to the upstream repository owned by Elastic to be added to the new repository. Cloning the repository will remove that upstream link, and any new rules will need to be brought over via another process.

With this new repository, in the rules directory, create a new directory named custom that will contain newly created rules for our purposes. For this example, the rule located at /rules/windows/discovery_whoami_command_activity.toml is copied to the custom directory as /rules/custom/discovery_whoami_command_activity_tines.toml and modified to create the first custom rule that will be added to Elastic SIEM.

When we edit the new rule, we’ll update the name of the rule as it will appear in Elastic SIEM and add to the TOML file the alert configuration that was set above and exported to the JSON file containing the rule action configuration.

Next is configuring the testing and deployment of the new rule that was created using GitHub Actions.

GitHub Actions CICD setup 

GitHub Actions are defined in each repository as YAML files in the .github/workflows directory. In this instance, some of what Elastic provides will be used as inspiration but it will be mostly reconfigured for the detection-as-code use. The file that will be kept is lock-versions.yml, and two new files will be created called pull-request.yml for pull request testing and deploy.yml to deploy to Elastic SIEM after rule changes are approved.

In the workflow file for pull requests, GitHub will utilize a Python script provided by Elastic in the repository to validate and test that the added rules meet a high configuration standard and won't produce errors when deployed to Elastic SIEM.

The workflow file for deploying changes includes a slightly modified script, update_rules.py, provided by Stijn Holzhauer of the Elastic community that will create or update the rules in Elastic SIEM. This script handles the connection to Elastic SIEM using environment variables for the Kibana URL, Kibana user, and Kibana password to interact with the Kibana API.

The environment variables are set using GitHub repository secrets and are local to the repository and GitHub Actions running the workflows.

Making rule changes 

At this point, rule changes can be made following the Github Flow in order to update Elastic SIEM from our code repository. A new code branch is first created. The custom rule can be edited in that code branch with a new matching query for detection purposes.

For my “whoami” rule, it was made to match against Windows hosts, which use the executable “whoami.exe”, but if it should match against Mac hosts, it could be changed to just “whoami”.

process where event.type in ("start", "process_started") and process.name : "whoami.exe"

changed to

process where event.type in ("start", "process_started") and process.name : "whoami"

After committing and making a pull request, the pull request workflow testing the rule and its required components will run.

Once the tests run successfully, the pull request can be merged into the main code branch and the rules will be deployed via the deploy workflow.

Handling alerts in Tines 

With the detection rule deployed and the Tines webhook ready to receive alerts, we can begin building out the Tines Story to handle the alerts. Instead of traditional incident management solutions like ServiceNow or Jira, this example will utilize GitHub Issues for alert management. This has a couple of benefits as our detection rules are already managed in GitHub, GitHub Issues are free to use, and any Issue opened can be directly related to a rule definition change for rule tuning purposes.

The Tines Story begins with the webhook that we have configured in our Elastic SIEM alert configuration that we started with. After receiving alerts, their payloads should be parsed, and each individual payload should create a new GitHub Issue.

The resulting GitHub Issue will contain the most important contextual information highlighted to the analyst, response actions to take to remediate the alert, and the raw alert payload for any additional information required for that specific alert.

Alert tuning 

As time passes, rules will need to be updated to ensure they match the right criteria and avoid creating false-positive alerts. Continuing the example, if rule matches containing the host vanilla.local was declared a false positive, the rule could be tuned to exclude any logs matching the host vanilla.local.

To make that change, in the code, the rule query will change from:

process where event.type in ("start", "process_started") and process.name : "whoami"

to:

process where event.type in ("start", "process_started") and process.name : "whoami" and host.name != "vanilla.local"

Once committed, a pull request can be opened that will show and track how the rule changes over time. The existing alert (or multiple alerts) that are Issues can be referenced in the pull request as reasons for the update in the rule.

Once tested, approved, and merged, the rule will be updated in Elastic SIEM and will no longer match against the host vanilla.local.

Achieving Detection-as-Code 

While a considerable amount of work and care can go into creating the foundation for detection-as-code, there are great benefits in reliable deployments, automated syntax checking, validation of rules, and tracking of changes in platforms like GitHub. Without using any of these specific tools or services, the same outcomes can be achieved in many different ways, with no one being the absolute correct implementation. If you have thought about moving towards detection-as-code, we hope this provides a framework for you to do so. As security processes continue to move more into software developer-centric models, opportunities like detection-as-code will become ever more common.

The Tines Story to Create GitHub Issues from Elastic SIEM alerts is ready for you to import, use, and customize via our Story Library by using the button below.

Loading story...

Built by you,
powered by Tines

Already have an account? Log in.