Managing Identities in Splunk Enterprise Security
Author: Ben Marrable
Release Date: 31/08/21
There are two main reasons for Assets and Identities with Enterprise Security; correlation and context. We need correlation to be able to tie events together as different event sources could report events for an asset based on any of the following:- IP address, MAC Address, a hostname or the assets fully qualified domain name. So it’s important to know that those two events relate to the same asset, and for that we need to tie all the attributes for an asset together. Similarly for Identities with respect to users having multiple usernames in the environment for different applications.
The second reason is for context, in the event of a breach it is important to be able to triage and act upon the breach as quickly as possible. Displaying data around who owns the asset or who manages the user involved in the incident greatly assists in response times. Additionally, it can help just knowing details about an asset whether the security event is actually effective or not and how quickly we need to be responding to the event.
What identity data do we need?
Taken from Splunk docs, we need data on the following fields:
I’ve added an additional column indicating the Active Directory default attribute which corresponds to the Identity field.
Field | Data type | Description | Example | Default AD Mapping |
identity | pipe-delimited strings | Required. A pipe-delimited list of username strings representing the identity. After the merge process completes, this field includes generated values based on the identity lookup configuration settings. | a.vanhelsing|abraham.vanhelsing|a.vanhelsing@acmetech.org | sAMAccountName |
prefix | string | Prefix of the identity. | Ms., Mr. | personalName |
nick | string | Nickname of an identity. | Van Helsing | displayName |
first | string | First name of an identity. | Abraham | givenName |
last | string | Last name of an identity. | Van Helsing | sn |
suffix | string | Suffix of the identity. | M.D., Ph.D | |
string | Email address of an identity. | a.vanhelsing@acmetech.org | ||
phone | string | A telephone number of an identity. | 123-456-7890 | telephoneNumber |
phone2 | string | A secondary telephone number of an identity. | 012-345-6789 | mobile |
managedBy | string | A username representing the manager of an identity. | phb@acmetech.org | manager |
priority | string | Recommended. The priority assigned to the identity for calculating the Urgency field for notable events on Incident Review. An “unknown” priority reduces the assigned Urgency by default. For more information, see How urgency is assigned to notable events in Splunk Enterprise Security. | unknown, low, medium, high or critical. | |
bunit | string | Recommended. A group or department classification for identities. Used for filtering by dashboards in Splunk Enterprise Security. | Field Reps, ITS, Products, HR | department |
category | pipe-delimited strings | Recommended. A pipe-delimited list of logical classifications for identities. Used for asset and identity correlation and categorization. See Asset/Identity Categories. | Privileged|Officer|CISO | |
watchlist | boolean | Marks the identity for activity monitoring. | Accepted values: “true” or empty. See User Activity Monitoring in this manual. | |
startDate | string | The start or hire date of an identity. | Formats: %m/%d/%Y %H:%M, %m/%d/%y %H:%M, %s | whenCreated |
endDate | string | The end or termination date of an identity. | Formats: %m/%d/%Y %H:%M, %m/%d/%y %H:%M, %s | expires |
work_city | string | The primary work site City for an identity. | l | |
work_country | string | The primary work site Country for an identity. | co | |
work_lat | string | The latitude of primary work site City in DD with compass direction. | 37.78N | |
work_long | string | The longitude of primary work site City in DD with compass direction. | 122.41W |
How do we gather this information?
Hopefully you have a central authentication directory, in most organisations that could be Active Directory (AD). Alternatively we could poll this information from a Human Resources database, but for this blog I’m going to detail pulling the information from AD.
First, you will need the Supporting Add-on for Active Directory, also known as SA-LDAPSearch. Install this application onto your ES search head and configure the connection to your domain. Once the app is installed you will now be able to poll the domain using the ldapsearch splunk command. Using a search similar to the following, you will be able to poll the domain and build some priorities and categories from attribute found within active directory:
| ldapsearch domain=SPL search=”(&(objectclass=user) (!(objectClass=computer)))” attrs=”sAMAccountName, personalTitle, displayName, givenName, sn, mail, telephoneNumber, mobile, manager, department, whenCreated, expires, userAccountControl, co, l, title, distinguishedName, memberOf”
| search userAccountControl=”NORMAL_ACCOUNT”
| rename sAMAccountName AS identity, personalTitle AS prefix, displayName AS nick, givenName AS first, sn AS last, mail AS email, telephoneNumber AS phone, mobile AS phone2, manager AS managedBy, whenCreated AS startDate, expires AS endDate, co AS work_country, l AS work_city
| eval suffix=””
| eval watchlist=”false”
| eval comment=”Priority Definement”
| eval priority=case(
match(title,”CEO”),”critical”,
match(memberOf,”Administrators”),”critical”,
match(distinguishedName,”OU=Privileged Accounts”),”high”,
match(distinguishedName,”OU=Service Accounts”),”medium”,
1==1,”low”)
| eval comment=”Category Definement”
| makemv delim=”|” category
| eval category=if(match(distinguishedName,”OU=Privileged Accounts”),mvappend(category,”privileged”),category)
| eval category=if(match(distinguishedName,”OU=Service Accounts”),mvappend(category,”service_account”),category)
| eval category=mvsort(mvdedup(category))
| eval category=mvjoin(category,”|”)
| eval comment=”Department Possible Values Check”
| eval bunit=case(
bunit=”IT”,”IT”,
bunit=”Information Technology”,”IT”,
bunit=”Legal”,”Legal”,
1==1,””)
| eval watchlist=”false”
| lookup identity_locations work_city, work_country OUTPUTNEW work_lat, work_long
| table identity, prefix, nick, givenName, last, suffix, email, phone, phone2, managedBy, priority, bunit, category, watchlist, startDate, endDate, work_city, work_country, work_lat, work_long
| outputlookup identities_from_ad
Let’s break this search down, so we understand each part:
| ldapsearch domain=SPL search=”(&(objectclass=user) (!(objectClass=computer)))” attrs=”sAMAccountName, personalTitle, displayName, givenName, sn, mail, telephoneNumber, mobile, manager, department, whenCreated, expires, userAccountControl, co, l, title, distinguishedName, memberOf”
This part polls the domain, note that it specifies only the attributes that we are after, to limit the request on the domain. It’s also a good idea in large domains to poll the domain in multiple searches utilising the basedn parameter to this search.
| search userAccountControl=”NORMAL_ACCOUNT”
| rename sAMAccountName AS identity, personalTitle AS prefix, displayName AS nick, givenName AS first, sn AS last, mail AS email, telephoneNumber AS phone, mobile AS phone2, manager AS managedBy, whenCreated AS startDate, expires AS endDate, co AS work_country, l AS work_city
| eval suffix=””
| eval watchlist=”false”
This section validates the accounts are user accounts (rather than computer accounts) using the userAccountControl field in AD and renames all the direct mapping fields across to Splunk ES naming convention. Additionally we create a blank field for suffix and set watchlist to false, as we have no suffix or watchlist information in the domain and it’s not possible with the data to compute these terms.
| eval comment=”Priority Definement”
| eval priority=case(
match(title,”CEO”),”critical”,
match(memberOf,”Administrators”),”critical”,
match(distinguishedName,”OU=Privileged Accounts”),”high”,
match(distinguishedName,”OU=Service Accounts”),”medium”,
1==1,”low”)
This section is about defining the priority for each Identity, priority is one of the most critical fields to define and to distinguish between user accounts. Several attributes can be used to give some definition to the search, using a case statement hitting the highest priorities first. Attributes which are useful here are the OU location that the account sits within the domain, groups the account is a member of and of course the accounts job title.
| eval comment=”Category Definement”
| makemv delim=”|” category
| eval category=if(match(distinguishedName,”OU=Privileged Accounts”),mvappend(category,”privileged”),category)
| eval category=if(match(distinguishedName,”OU=Service Accounts”),mvappend(category,”service_account”),category)
| eval category=mvsort(mvdedup(category))
| eval category=mvjoin(category,”|”)
Next we look at defining some categories, categories are useful for dividing data within Splunk, so we can see items such as the number of failed authentication events for privileged accounts.
| eval comment=”Department Possible Values Check”
| eval bunit=case(
bunit=”IT”,”IT”,
bunit=”Information Technology”,”IT”,
bunit=”Legal”,”Legal”,
1==1,””)
This section looks to combine and clean some data which may be populated badly in Active Directory, only matching certain bunits, as it’s quite common for Identities to have various spelling mistakes and alternative forms of departments held with AD.
| lookup identity_locations work_city, work_country OUTPUTNEW work_lat, work_long
Here we poll the city and country held within AD to collect the latitude and longitude from a lookup containing those details for work locations in the business.
| table identity, prefix, nick, givenName, last, suffix, email, phone, phone2, managedBy, priority, bunit, category, watchlist, startDate, endDate, work_city, work_country, work_lat, work_long
| outputlookup identities_from_ad
Finally we output the data into a lookup table file to incorporate into ES.