Part 2: Detection Rules

In this part of the guide, we'll create detection rules that will trigger alerts when Scanner encounters new threat activity. We'll create a few detection rules manually, add out-of-the-box detections, and explore how to use the scanner-cli tool to validate detection rules.

1. Develop a query to use in a detection rule

A natural question arises, "Maybe we can stop the ongoing attack by blocking the IP addresses of the attackers?"

For the sake of this scenario, let's say that we have two tools at our disposal:

  • An internal tool that allows us to manually add IP addresses to a block list in our network firewall settings.

  • An internal webhook that can automate blocking an IP address. For example, this webhook might be powered by a SOAR tool like Torq.

Let's first see if we can generate the full set of IP addresses used by the attackers.

First, we query to get some sample logs for the suspicious users to see if there is an IP address field we can use. Use this as the full query:

userIdentity.userName=(pgibbons mbolton samirn)

Click Run.

Then, click on one of the rows in the search results to view full log details. As we scroll around, we can see a column that contains the IP address of the actor who executed the API call: sourceIPAddress.

Let's use the sourceIPAddress column to gather the full list of IP addresses used by the suspicious users using groupbycount. Here is the full query:

userIdentity.userName=(pgibbons mbolton samirn)
| groupbycount sourceIPAddress

Thankfully, there are only a few IP addresses there.

Let's say we manually add these to our internal block list tool.

But what if the attackers start using new IP addresses? We can use a Scanner detection rule to automatically send these IP addresses to our internal webhook to perform the block operation.

Let's say that the webhook expects the field to be called ip_address_to_block.

We add a section to rename sourceIPAddress to ip_address_to_block:

| rename sourceIPAddress as ip_address_to_block

We perform a simple count aggregation to get the list of unique values of ip_address_to_block.

| groupbycount ip_address_to_block

The result table of groupbycount ip_address_to_block has two columns, namely ip_address_to_block and @q.count. Let's say that we only want to return ip_address_to_block alone. We can use the table command to select a subset of columns to return in the result. In our case, we can select just ip_address_to_block.

| table ip_address_to_block

Here is what the full query looks like:

userIdentity.userName=(pgibbons mbolton samirn)
| rename sourceIPAddress as ip_address_to_block
| groupbycount ip_address_to_block
| table ip_address_to_block

If you run this, it will return a list of unique ip_address_to_block values.

Let's create a detection rule from this query and connect it to our internal webhook.

2. Create a detection rule to monitor attacker IP addresses

In Scanner, a detection rule is a query that runs continuously on all data that is processed during indexing.

These continuous queries populate a rollup data structure in S3 that can be checked at high speed without needing to run all of the machinery of normal ad-hoc queries.

Let's create a detection rule to forward these ip_address_to_block values to an internal webhook.

Navigate to the Detections tab.

If you have no detection rules yet, Click Create Detection Rule. Otherwise, click New > + Create New Rule.

Under Name, put something like this:

Detect IP addresses from customer transaction log attackers

Under Description, put something like this:

Look at AWS CloudTrail activity from a list of known suspicious IAM users who have been exfiltrating customer transaction logs and editing Lambda functions. Send all unique IP addresses they are using to our internal blocklist webhook.

Set Severity to High.

Under Detection Rule > Query, use this query:

userIdentity.userName=(pgibbons mbolton samirn)
| rename sourceIPAddress as ip_address_to_block
| groupbycount ip_address_to_block
| table ip_address_to_block

Set Time Range to 15 minutes to make sure we don't miss activity.

Set Frequency to 1 minute so that the updates happen quickly.

Under Event Sinks, let's look at what it would be like to create a webhook event sink that would route alerts to an internal webhook. (We won't actually create it since the internal webhook is fictional.)

  • Click Create New Sink.

  • Under Type, select Webhook.

  • Here, you would enter the Webhook URL, any Custom HTTP Headers needed, like Authorization, Content-Type, or anything else your internal webhook would need.

  • Then, you would give the event sink a Name and Description and would normally click Create. This would create a new Event Sink that could be used in any detection rule. For now, we can click Cancel.

We can see that the detection will always be sent to the Detections Index, which is an index we can query in Scanner to view triggered detection events.

Click Create Rule.

3. Create a detection rule to find new S3 exfiltrators

More users may join the attack, whether via insider threat collaboration or by being compromised by an external attacker.

We want to be able to detect new users who are also involved in data exfiltration.

Let's create a new rule to look for new users who are exfiltrating data a lot of data over a short time period from the sensitive S3 buckets we saw earlier.

Click New > + Create New Rule.

Under Name, put something like this:

Detect users exfiltrating data from sensitive S3 buckets

Under Description, put something like this:

Look at AWS CloudTrail audit logs to find users who are exfiltrating more than 100MB per hour from some sensitive S3 buckets.

Set Severity to High.

Under Detection Rule, set Query to the this text:

eventSource=s3.amazonaws.com
eventName=GetObject
requestParameters.bucketName=(
  initech-prod1-customer-financial-txns
  initech-prod1-payment-processing-logs
)
| rename 
  additionalEventData.bytesTransferredOut as bytes_exfiltrated,
  userIdentity.userName as user_name
| stats sum(bytes_exfiltrated) as total_bytes_exfiltrated
  by user_name
| where total_bytes_exfiltrated > 100000000

Set Time Range to 1 hour. This detection rule will analyze the past one hour of logs to look for users that stand out in how much data they are downloading.

Set Frequency to 1 hour. This detection rule will check the condition once per hour to see if anyone has exfiltrated more than 100MB over the time range.

Size of the time range has basically no performance impact. Whether the time range is large or short has basically no impact on query efficiency in detection rules.

As data flows through a detection rule, it is organized into an aggregation roll-up tree data structure that is fast to query over any time range.

Periodically at the frequency specified, Scanner will query that roll-up tree data structure to check if a detection rule condition has been triggered.

Click Create Rule.

With this new rule in place, we will now have detection events that will inform us of candidate users who may be exfiltrating data.

4. Search detection events

When a detection rule is triggered, detection events are added to the Detections Index, which we can search like any other index.

For example, we can look at individual detection events, or compute summaries of detections.

By default, each detection event contains the first 10 rows of the detection rule query results.

When you view a detection event in Scanner, you can click a button to re-run the detection rule's query on the triggered time range to return all of the search results.

Navigate to Detections, and click Search Detections.

This simply opens up the Search view where the index has been narrowed down to the Detections Index. In other words, Search opens up with this query:

@index=_detections

If you have triggered detections in here, you can click on one to view the detection event details. The details include the following information:

  • The name of the detection rule.

  • When the event was triggered.

  • The description of the rule.

  • A preview of the query results. Only shows up to the first 10 rows.

  • The text of the query that was executed.

You can click the Run Query button to re-run the detection rule query on the time range when the event was triggered. This allows you to view all query results for the detection rule query, not just the first 10 results.

5. Summarize detection events

Since the Detections Index (identified as _detections) is just another Scanner search index, you can run queries to summarize the data it contains.

For example, you can summarize with a simple count aggregation, grouped by detection rule name.

@index=_detections
| groupbycount name

To zoom in on a specific time range, like zooming in on a specific spike, you can click and drag on the histogram visualization above the search results table.

6. Add out-of-the-box detection rules from a public GitHub repository

With Scanner, you are welcome to use your own custom detection rules, but Scanner also provides out-of-the-box detections in public GitHub repositories.

Let's add Scanner's out-of-the-box detection rules for AWS CloudTrail by pulling them from the detection-rules-aws-cloudtrail repository on GitHub.

Navigate to Detections.

Click New, and select Add Rules from GitHub.

Under Connected Repositories, click Add Repository.

Under Repository, copy-paste this:

scanner-inc/detection-rules-aws-cloudtrail

Under Branch, select main.

Click Add Repository.

Scanner's out-of-the-box detection rules for AWS CloudTrail will now sync with your environment.

Any changes made upstream to the detection rules will be automatically synced to your Scanner environment.

7. Use the scanner-cli tool to validate and test detection rules

Scanner provides a CLI tool that you can use to validate and test detection rules on your own workstation.

This tool is helpful for teams who maintain detection rules in a GitHub repository.

Let's set things up to allow you to try out scanner-cli.

Use pip install to get the latest version of the tool.

pip install scanner-cli

Clone the public GitHub repository that contains out-of-the-box detection rules for AWS CloudTrail, and change the current directory to the root of the repository.

git clone https://github.com/scanner-inc/detection-rules-aws-cloudtrail.git

The scanner-cli tool uses the Scanner API to validate detection rules and run unit tests. You will need the Scanner API URL and an API key to run commands, which you can get from Settings > API Keys within Scanner.

You can pass the API URL and API key to scanner-cli via environment variables, specifically SCANNER_API_URL and SCANNER_API_KEY.

Alternatively, you can pass them as arguments via the --api-url and --api-key flags.

Let's assume we've set up the environment variables.

Run this command to validate the detection rules in the repository:

scanner-cli validate -r -d ./detection-rules-aws-cloudtrail

The -r flag tells scanner-cli to search for rules recursively, and the -d flag tells it to look in a specific directory.

Run this command to run the unit tests in the detection rules in the repository:

scanner-cli run-tests -r -d ./detection-rules-aws-cloudtrail

Only some detection rules in this repository have unit tests, so run-tests will show "No tests found" for various detections rules.

For more information on building your own detection rules, see our documentation for Detection Rules as Code.

Last updated