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 take a look at creating basic SPL searches for Splunk (and show a manual conversion of a Sigma rule to a Splunk Detection).

In the last two posts I have covered YARA-L and Kusto query languages for threat detection. In this tutorial the structure of Splunk detections for Analytic Stories are the focus.

Analytic Stories and their corresponding searches (aka detections) are built using YAML files.

In Splunk products Analytic Stories contain much more than just detections, however, for the purpose of this post, it is only the detection content I will focus on.

The detection YAML file contains lots of properties used by Splunk products to process, display and handle the event when it is triggered by the detection.

Splunk Detection YAML Structure

Before I jump into the search (aka the detection logic), lets take a look at the properties that can be used in a detection yml file.

  • id (required): UUID v4 as unique identifier
    • e.g. “fb4c31b0-13e8-4155-8aa5-24de4b8d6717”
  • name (required): Descriptive title of the detection
    • e.g. “Access LSASS Memory for Dump Creation”
  • description (required): A detailed description of the detection
    • e.g. “dbgcore.dll is a specific DLL for Windows core debugging. It is used to obtain a memory dump of a process.”
  • author (required): Author of the detection
    • e.g. “Signals Corps”
  • date (required): date of creation or modification, format yyyy-mm-dd
    • e.g. 2019-12-06
  • version (required): version of detection
    • e.g. 1
  • datamodel (required): datamodel(s) used by the search from list of items
    • e.g. Endpoint
  • type (required): type of detection from list of items
    • e.g. Anomaly
  • known_false_positives (required): description of known false positives
    • e.g. “Administrators can create memory dumps for debugging purposes, but memory dumps of the LSASS process would be unusual.”
  • references (optional): A list of references for the detection
    • e.g. [“https://site1.com”,”https://site2.com”]
  • how_to_implement (optional): information about how to implement. Only needed for non standard implementations
    • e.g. [“This search requires Sysmon Logs and a Sysmon configuration, which includes EventCode 10 for lsass.exe.”]
  • items (optional): An explanation about the purpose of the detection. Unlike description, could be a links to extenal sources
    • e.g. [“https://site1.com”,”https://site2.com”]
  • tags (required): An array of key value pairs for tagging

A more detailed note on tags

The following tags are currently natively supported by other Splunk features (inc. rendering in UI)

  • analytic_story: Relevant Splunk Analytic story. See Analytic Stories
  • mitre_attack_id: MITRE ATT&CK Technique or Sub-technique ID. See MITRE ATT&CK.
  • cis20: The Center for Internet Security (CIS) Top 20 Critical Security Controls reference. See CIS.
  • nist: NIST Cybersecurity Framework reference. See NIST.
  • security_domain: Splunk Security domain. e.g network
  • asset_type: Type of asset being investigated in string format. e.g AWS Instance
  • risk_object: see risk scoring
  • risk_object_type: see risk scoring
  • risk)score: see risk scoring

Here is an example;

tags:
  analytic_story:
  - credential_dumping",
  kill_chain_phases:
  - Action on Objectives
  mitre_attack_id:
  - T1078.004
  cis20:
  - CIS 13
  nist:
  - DE.DP
  security_domain:
  - network
  asset_type:
  - AWS Instance
  risk_object:
  - user
  risk_object_type:
  - network_artifacts
  risk_score:
  -  60

In addition to these standard properties, any "custom_key": "custom_value" pairing can be used in the tag section. For example;

tags:
  product:
  - Splunk Enterprise
  - Splunk Enterprise Security
  - Splunk Cloud

The one property I missed from the YAML structure above was the required search.

Indeed the crucial part of the YAML file is the detection (search) content written in Splunk’s Search Processing Language (SPL).

SPL encompasses all the search commands and their functions, arguments, and clauses. Its syntax was originally based on the Unix pipeline and SQL. The scope of SPL includes data searching, filtering, modification, manipulation, insertion, and deletion.

Like Kusto, SPL is a generic search language for logs, but has seen widespread adoption by security teams using Splunk as a SIEM.

Unlike Kusto, the Splunk data store is not based on a tabular structure. Fields are extracted at search using regular expressions, apart from fixed fields including (but not limited to); index, source, and sourcetype.

sourcetype defines how data is ingested and how fields are assigned. Splunk natively supports common sourcetypes as defined here. Generally sourcetypes define the fields applied to the events for extraction.

In many cases, these fields are defined in Splunk’s Common Information Model (CIM), which is useful in mapping the same fields from different sources (e.g. sourceip, srcip, ip -> src_ip).

At its most basic the Splunk query language supports a range of operators on fields, much like the other search languages covered in previous posts.

sourcetype="aws:cloudtrail" action="success"

I know the sourcetype aws:cloudtrail uses the Authentication CIM (that contains the fieldname action), as documented in the Splunk Add-on for AWS which defines the sourcetype.

Multiple fields are treated with AND operators. So logically this search is asking for data from AWS Cloud Trail and where the action field in the log is equal to success.

Other operators are available, for example NOT;

sourcetype="aws:cloudtrail" NOT action="success"

Now I am filtering out all events where action="success" from Cloud Trail logs.

Another similarity SPL shares with Kusto is the use of the pipe | character, and it works in just the same way – it passes (or ‘pipes’) the data through into the next command.

sourcetype="aws:cloudtrail" action="success" | stats count by action

In this command, first I get all events with action="success", and then I pipe that to a stats count function. This counts the number of logs returned where action="success" and returns the number as a count field.

There are a huge variety search functions available in Splunk, in addition to stats.

You do not even need to search by field=value. Although more inefficient in terms of performance, I can also do a plain text search on the logs;

success | stats count by action

This example will produce a count field, counting number of times the string “success” appears in the logs.

Importantly, you can also specify a time range using the fixed fields earliest and latest.

Here is an example of using a time range in a search that goes back 5 minutes, snapping to the beginning of the minute.

sourcetype="aws:cloudtrail" action="success" earliest=-5m@m latest[email protected]m

There are a wide variety of time modifiers available to use in your queries.

I can also use other commands to filter the results, especially when I want to reduce false positives.

sourcetype="aws:cloudtrail" action="success" earliest=-5m@m latest[email protected]m | stats count by action | where count > 10

Here I am looking for success actions within a 5 minute window, where there are more than 10 success actions are seen within the time window.

Sigma Rule to Splunk Detection

Now you know a little more about Splunk detections, lets try and manually create one from an existing Sigma Rule.

Sigma Rule

Here is a public Sigma Rule detecting the deletion the modification of a user profile to detect anyone is changing password on behalf of other users.;

title: AWS User Login Profile Was Modified
id: 055fb148-60f8-462d-ad16-26926ce050f1 
status: experimental
description: An attacker with the iam:UpdateLoginProfile permission on other users can change the password used to login to the AWS console on any user that already has a login profile setup.
 With this alert, it is used to detect anyone is changing password on behalf of other users.
author: toffeebr33k
date: 2021/08/09
references:
    - https://github.com/RhinoSecurityLabs/AWS-IAM-Privilege-Escalation
logsource:
    product: aws
    service: cloudtrail
detection:
    selection_source:
        eventSource: iam.amazonaws.com
        eventName: UpdateLoginProfile
    filter:
        userIdentity.arn|contains: requestParameters.userName
    condition: selection_source and not filter
fields:
    - userIdentity.arn
    - requestParameters.userName
    - errorCode
    - errorMessage
falsepositives:
    - Legit User Account Administration 
level: high
tags:
    - attack.persistence
    - attack.t1098

Splunk Detection

First I can map everything except for the detection;

name: AWS User Login Profile Was Modified
id: 055fb148-60f8-462d-ad16-26926ce050f1
description: An attacker with the iam:UpdateLoginProfile permission on other users can change the 
password used to login to the AWS console on any user that already has a login profile setup.
 With this alert, it is used to detect anyone is changing password on behalf of other users.
version: 1
date: '2021-08-09'
author: toffeebr33k
type: Hunting
datamodel:
- Change
known_false_positives: 'Legit User Account Administration'
references: ['https://github.com/RhinoSecurityLabs/AWS-IAM-Privilege-Escalation']
tags:
  mitre_attack_id:
  - T1098
  sigma_level: high
  sigma_fields:
  - 'userIdentity.arn'
  - 'requestParameters.userName'
  - 'errorCode'
  - 'errorMessage'
  sigma_status: experimental

A lot of Sigma properties map one-to-one with the Splunk detection properties. I had to manually define the type and datamodel values. For everything else that did not map one-to-one I used the tags property to declare them using the prefix sigma_.

Now all that is left is to write the search.

From the logsource I know the product is AWS Cloud Trail;

logsource:
    product: aws
    service: cloudtrail

Which maps to the sourcetype="aws:cloudtrail" from the Splunk Add-on for AWS, which uses the CIMs Authentication and Change.

The Sigma Rule contains two Search Identifiers, selection_source and filter and a condition that states selection_source and not filter.

This translates into a Splunk search;

sourcetype="aws:cloudtrail" action="updated" | where user!=src_user

I looked up the action, user and src_user from the Splunk Change CIM

user The user or entity performing the change. For account changes, this is the account that was changed. See src_user for user or entity performing the change. Fill out and normalize first to user & src_user, for example when using Assets and Identities in Enterprise Security.

Putting this together, it gives a final Splunk Detection YAML;

name: AWS User Login Profile Was Modified
id: 055fb148-60f8-462d-ad16-26926ce050f1
description: An attacker with the iam:UpdateLoginProfile permission on other users can change the 
password used to login to the AWS console on any user that already has a login profile setup.
 With this alert, it is used to detect anyone is changing password on behalf of other users.
version: 1
date: '2021-08-09'
author: toffeebr33k
type: Hunting
datamodel:
- Change
known_false_positives: 'Legit User Account Administration'
references: ['https://github.com/RhinoSecurityLabs/AWS-IAM-Privilege-Escalation']
tags:
  mitre_attack_id:
  - T1098
  sigma_level: high
  sigma_fields:
  - 'userIdentity.arn'
  - 'requestParameters.userName'
  - 'errorCode'
  - 'errorMessage'
  sigma_status: experimental
search:
  'sourcetype="aws:cloudtrail" action="updated" | where user!=src_user'

Which I can save as AWSUserLoginProfileWasModified.yaml ready for use as a Splunk detection.

Automating Rule Translation

In the next part of the tutorial I will show you how automate the manual process of converting a Sigma Rule into a target format using Sigmac.


Sigma Certification (Virtual and In Person)

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

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




Our brand new Discord!

Like this blog?

Sign up to receive new posts in your inbox.


Stixify

Stixify. Extract machine readable intelligence from unstructured data.

Extract machine readable intelligence from unstructured data.

Obstracts

Obstracts

Turn any blog into structured threat intelligence.


Vulmatch

Vulmatch

Know when software you use is vulnerable, how it is being exploited, and how to detect an attack.

SIEM Rules

SIEM Rules. Your detection engineering database.

View, modify, and deploy SIEM rules for threat hunting.