# Splunk usage

### Quick deployment with Splunk docker container

For the quick deployment of a Splunk instance, the [Splunk docker image](https://hub.docker.com/r/splunk/splunk/) (by Splunk) can be used.

```
docker pull splunk/splunk:latest

# Port 8000: Splunk web interface.
# Port 8088: Splunk HTTP event collectors service.
docker run -p [<IP>:]8000:8000 -p [<IP>:]8088:8088 -e "SPLUNK_PASSWORD=<PASSWORD>" -e "SPLUNK_START_ARGS=--accept-license" splunk/splunk:latest
```

### Splunk search Cheat Sheet

**Search commands**

| Command                                                                                                                                                                         | Description                                                                                                                                                                                                                                                | Example                                                                                                                                                           |                                                                                                                                                                                                                                                                                                                                             |                                                                                                                                                                                                                        |                                                                                                                                                                       |                                    |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
| <p><code>dedup \<FIELD></code><br><br><code>dedup \<FIELD1> \<FIELDN></code></p>                                                                                                | Removes events containing an identical value(s) for the specified field(s).                                                                                                                                                                                | `dedup index`                                                                                                                                                     |                                                                                                                                                                                                                                                                                                                                             |                                                                                                                                                                                                                        |                                                                                                                                                                       |                                    |
| `\| eventcount [index=<* \| INDEX>]`                                                                                                                                            | Returns the number of events in the specified indexes.                                                                                                                                                                                                     |                                                                                                                                                                   |                                                                                                                                                                                                                                                                                                                                             |                                                                                                                                                                                                                        |                                                                                                                                                                       |                                    |
| <p><code>fields \[+                                                                                                                                                             | -] \<FIELD></code><br><br><code>fields \<FIELD1> \<FIELDN></code></p>                                                                                                                                                                                      | <p>Keeps or removes the specified fields.<br><br>Default to keeping fields (<code>+</code>).</p>                                                                  |                                                                                                                                                                                                                                                                                                                                             |                                                                                                                                                                                                                        |                                                                                                                                                                       |                                    |
| `iplocation allfields=true <FIELD>`                                                                                                                                             | Extracts location information (city, country, continent, ...) for the IP address by using a local copy of the `ip-to-city-lite.mmdb` IP geolocation database file                                                                                          |                                                                                                                                                                   |                                                                                                                                                                                                                                                                                                                                             |                                                                                                                                                                                                                        |                                                                                                                                                                       |                                    |
| <p><code>rare \[limit=\<INT>] \<FIELD></code><br><br><code>rare \<FIELD1> \<FIELDN></code><br><br><code>rare \<FIELD> by \<FIELD\_GROUP\_BY> \[\<FIELD\_GROUP\_BYN>]</code></p> | <p>Displays the least common value of the specified field or the least common combination of values of the specified fields.<br><br>With the <code>group by</code> close, rare field(s) for each field(s) in the given grouped by fields are returned.</p> | <p><code>...                                                                                                                                                      | rare Process\_Command\_Line</code><br>Returns the rare <code>Process\_Command\_Line</code> fields.<br><br><code>...                                                                                                                                                                                                                         | rare Process\_Command\_Line Account\_Name</code><br>Returns the rare combination of <code>Process\_Command\_Line</code> and <code>Account\_Name</code> fields.<br><br><code>...                                        | rare Process\_Command\_Line by Account\_Name</code><br>Returns the rare <code>Process\_Command\_Line</code> fields for each different <code>Account\_Name</code>.</p> |                                    |
| `rename <FIELD_NAME> AS <NEW_FIELD_NAME>`                                                                                                                                       | <p>Renames the specified field.<br><br>Can be used in a nested <code>search</code> query to rename the pivoting field.</p>                                                                                                                                 | <p>Rename <code>FIELD</code> to <code>NEW\_FIELD</code> to filter on <code>NEW\_FIELD=FIELD\_VALUE</code> in the main search:<br><code>index=\* \[search index=\* | dedup FIELD                                                                                                                                                                                                                                                                                                                                 | rename FIELD AS NEW\_FIELD</code>]<br><br>Rename <code>FIELD</code> to the <code>search</code> keyword to use <code>FIELD\_VALUE</code> as a plain text filter in the main search:<br><code>index=\* \[search index=\* | dedup FIELD                                                                                                                                                           | rename FIELD AS search</code>]</p> |
| `reverse`                                                                                                                                                                       | Reverses the order in which events are displayed (more recent to oldest by default).                                                                                                                                                                       |                                                                                                                                                                   |                                                                                                                                                                                                                                                                                                                                             |                                                                                                                                                                                                                        |                                                                                                                                                                       |                                    |
| <p><code>sort \[limit=\<LIMIT\_INT>] \[+                                                                                                                                        | -] \<FIELD></code><br><br><code>sort \[+                                                                                                                                                                                                                   | -] \<FIELD1> \<FIELDN></code></p>                                                                                                                                 | <p>Sorts results by the specified field(s). The top 10 000 events are returned by default.<br><br>The <code>+</code> (default) and <code>-</code> sign can be used to sort respectively by ascending or descending order.<br><br>Cast functions (<code>nums</code>, <code>str</code>, etc.) can be applied to each fields if necessary.</p> | <p><code>...                                                                                                                                                                                                           | sort -num(size)</code><br>Sorts results by size in descending order.</p>                                                                                              |                                    |
| <p><code>stats count by \<FIELD></code><br><br><code>stats count by \<FIELD1> \<FIELDN></code></p>                                                                              | Counts the number of events by field or for a combination of the specified fields.                                                                                                                                                                         |                                                                                                                                                                   |                                                                                                                                                                                                                                                                                                                                             |                                                                                                                                                                                                                        |                                                                                                                                                                       |                                    |
| `timeformat="%Y-%m-%d %H:%M:%S" earliest="<YYYY-MM-DD HH:MM:SS>" latest="<YYYY-MM-DD HH:MM:SS>"`                                                                                | Filters results in the specified timeframe (with `earliest` and / or `latest`).                                                                                                                                                                            | `timeformat="%Y-%m-%d %H:%M:%S" earliest="2023-01-13 11:12:13" latest="2023-02-01 21:00:00"`                                                                      |                                                                                                                                                                                                                                                                                                                                             |                                                                                                                                                                                                                        |                                                                                                                                                                       |                                    |
| `where <CONDITION>`                                                                                                                                                             | Filters results based on the specified condition(s)                                                                                                                                                                                                        |                                                                                                                                                                   |                                                                                                                                                                                                                                                                                                                                             |                                                                                                                                                                                                                        |                                                                                                                                                                       |                                    |
| `<SELECTION> \| stats earliest(_time) AS Earliest, latest(_time) AS Latest \| convert ctime(Earliest) ctime(Latest)`                                                            | Displays the timestamps of first and last events from the selection                                                                                                                                                                                        |                                                                                                                                                                   |                                                                                                                                                                                                                                                                                                                                             |                                                                                                                                                                                                                        |                                                                                                                                                                       |                                    |
| `eval match=if(match(<FIELD_1>,<FIELD_2>), 1, 0) \| search match=<0 \| 1>`                                                                                                      | Filters events if `FIELD_1` and `FIELD_2` match (`match=1`) / do not match (`match=0`).                                                                                                                                                                    |                                                                                                                                                                   |                                                                                                                                                                                                                                                                                                                                             |                                                                                                                                                                                                                        |                                                                                                                                                                       |                                    |
| `eval <NEW_FIELD>=mvindex(<FIELD>,<0 \| INDEX_START>,<0 \| INDEX_END>)`                                                                                                         | Extracts a subset - `INDEX_START` to `INDEX_END` - from the multivalue field `<FIELD>` into `NEW_FIELD`                                                                                                                                                    |                                                                                                                                                                   |                                                                                                                                                                                                                                                                                                                                             |                                                                                                                                                                                                                        |                                                                                                                                                                       |                                    |

**Example / useful search queries**

| Query                                                                                                                                                                                                                       | Description                                                                                                                                                           |                                               |                                                      |                                                                               |                                 |                                                                                                                                                     |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `\| eventcount index=* summarize=false \| dedup index \| fields index`                                                                                                                                                      | Lists available (non-internal) indexes.                                                                                                                               |                                               |                                                      |                                                                               |                                 |                                                                                                                                                     |
| `index=* sourcetype=wineventlog EventCode=4688 \| rare limit=100 Process_Command_Line`                                                                                                                                      | Returns the 100th rarest process execution command line (from non-default Windows Security logs).                                                                     |                                               |                                                      |                                                                               |                                 |                                                                                                                                                     |
| `index=* sourcetype=xmlwineventlog EventCode=3 DestinationHostname=*<DOMAIN> \| stats count by DestinationHostname, Image`                                                                                                  | Counts the number of hits on each subdomains of `<DOMAIN>` by Image (from Sysmon logs).                                                                               |                                               |                                                      |                                                                               |                                 |                                                                                                                                                     |
| `\| tstats min(_time) as latest max(_time) as earliest WHERE index="<* \| INDEX>" by index, source \| convert timeformat="%Y-%m-%d %H:%M:%S" ctime(earliest) ctime(latest)`                                                 | Retrieves the earliest and latest events of each given types for the specified or all index.                                                                          |                                               |                                                      |                                                                               |                                 |                                                                                                                                                     |
| <p><code>index="\<INDEX>" operationName="Sign-in activity" resultType=0</code><br><code>\[search index="\<INDEX>" operationName="Sign-in activity" resultType IN (50074, 50126, 50140)                                      | dedup properties.userPrincipalName,resultType,properties.ipAddress                                                                                                    | fields properties.ipAddress]</code><br><code> | dedup properties.userPrincipalName                   | table properties.userPrincipalName,resultType,properties.ipAddress</code></p> |                                 |                                                                                                                                                     |
| `<SEARCH> \| regex _raw=".*\*.*"`                                                                                                                                                                                           | Searching for the literal character `*`.                                                                                                                              |                                               |                                                      |                                                                               |                                 |                                                                                                                                                     |
| <p><code>\<SEARCH></code><br><code>                                                                                                                                                                                         | eval time\_epoch=strptime(\<TIMESTAMP\_FIELD>, "\[%Y-%m-%dT%T                                                                                                         | TIMESTAMP\_FORMAT>")</code><br><code>         | eval time\_diff=now() - time\_epoch</code><br><code> | search time\_diff <= 2592000</code><br><code>                                 | sort 0 - time\_epoch</code></p> | Sort events using another timestamp (`TIMESTAMP_FIELD`) of `TIMESTAMP_FORMAT` format, only keeping events newer than 30 days (30d \* 24h \* 3600s). |
| `rex field=<FIELD_TO_EXTRACT_FROM> "(?<<NEW_FIELD>>\\d+\.\\d+\.\\d+\.\\d+)"`                                                                                                                                                | `rex` command to extract an IPv4 from the specified field to the new field using an (dirty) regex.                                                                    |                                               |                                                      |                                                                               |                                 |                                                                                                                                                     |
| `<SELECTION> \| eventstats count AS Count by host \| eventstats earliest(_time) AS Earliest, latest(_time) AS Latest by host \| sort Earliest \| convert ctime(Earliest) ctime(Latest) \| table host,Earliest,Latest,Count` | Displays the timestamps of first and last events as well as the count of total events from the selection by `host`. The `host` field can be replaced by any field(s). |                                               |                                                      |                                                                               |                                 |                                                                                                                                                     |

```
# Retrieve the first and last occurrence of an event (exemple: user,src,dst,dstname,dstport) as well as the total bytes sent and received across all events.
# Add a formatted message resuming the event in an human readable message.

index=* [...]
| eventstats sum(sent) as total_sent by user,src,dst,dstname,dstport
| eventstats sum(rcvd) as total_rcvd by user,src,dst,dstname,dstport
| stats earliest(_time) AS earliest, latest(_time) AS latest by user,src,dst,dstname,dstport,total_sent,total_rcvd
| sort earliest
| eval earliest = strftime(earliest, "%Y-%m-%d %H:%M:%S")
| eval latest = strftime(latest, "%Y-%m-%d %H:%M:%S")
| eval message="First access to " + dstname + " (IP: " + dst + ") from " + src + " for user " + user + ".-newline-Last access: " + latest + ".-newline-Total bytes sent: " + total_sent + " and received: " + total_rcvd + "."
| rex mode=sed field=message "s/-newline-/\n/g"
| table earliest,latest,user,src,dst,dstname,dstport,total_sent,total_rcvd
```

### Splunk apps

**olafhartong's ThreatHunting**

The [`ThreatHunting`](https://github.com/olafhartong/ThreatHunting) `Splunk` application contains multiple dashboards, relying on telemetry from `Sysmon` and mapped on the [`MITRE ATT&CK framework`](https://attack.mitre.org/).

The following `Splunk` applications must be installed for `ThreatHunting` to work:

* [`Punchcard Visualization`](https://splunkbase.splunk.com/app/3129/)
* [`Force Directed App For Splunk`](https://splunkbase.splunk.com/app/3767/)
* [`Splunk Sankey Diagram - Custom Visualization`](https://splunkbase.splunk.com/app/3112/)
* [`Lookup File Editor`](https://splunkbase.splunk.com/app/1724/)

The [`Threathunting` application](https://splunkbase.splunk.com/app/4305/) can then be installed. and will index should be configured on the indexers.

***

### References

<https://docs.splunk.com/Documentation/SplunkCloud/9.0.2208/SearchReference/ListOfSearchCommands>
