All Apps and Add-ons

Anomalous Exchange sender daily_bytes dashboard?

nick405060
Motivator

Does anyone have a dashboard that displays anomalies for Exchange daily_bytes by sender? Looking for possible exfil through Exchange.

0 Karma
1 Solution

nick405060
Motivator

Yes. This is a run anywhere dashboard if you have Exchange set up; just replace MYDOMAIN

<dashboard script="button_submit_mail_anomalies.js">
  <label>Anomalies</label>

    <row>
    <panel>
      <html depends="$hide$">
        <style>
          #submit_button{
            width:80px !important;
          }
          #submit_button div[data-component="splunk-core:/splunkjs/mvc/components/LinkList"]{
            width:80px !important;
          }
          #submit_button  button{
            padding: 6px 15px !important;
            border-radius: 3px !important;
            font-weight: 500 !important;
            background-color: #5cc05c !important;
            border: transparent !important;
            color: #fff !important;
          }
          #submit_button  button:hover{
            background-color: #40a540 !important;
            border-color: transparent !important;
          }
        </style>
      </html>
      <input type="time" token="TIMERANGE1">
        <label>Time Range (STDEV Baseline):</label>
        <default>
          <earliest>-30d</earliest>
        </default>
        <change>
          <eval token="earliest_epoch_onChange">case(isnum($TIMERANGE1.earliest$), $TIMERANGE1.earliest$, $TIMERANGE1.earliest$=="now", time(), $TIMERANGE1.earliest$="", 0, true(), relative_time(time(), $TIMERANGE1.earliest$))</eval>
          <eval token="latest_epoch_onChange">case(isnum($TIMERANGE1.latest$), $TIMERANGE1.latest$, $TIMERANGE1.latest$=="now", time(), true(), relative_time(time(), $TIMERANGE1.latest$))</eval>
        </change>
      </input>
      <input type="time" token="TIMERANGE2">
        <label>Time Range (Results Filter):</label>
        <default>
          <earliest>@w0</earliest>
        </default>
        <change>
          <eval token="earliest_epoch_FILTER_onChange">case(isnum($TIMERANGE2.earliest$), $TIMERANGE2.earliest$, $TIMERANGE2.earliest$=="now", time(), $TIMERANGE2.earliest$="", 0, true(), relative_time(time(), $TIMERANGE2.earliest$))</eval>
          <eval token="latest_epoch_FILTER_onChange">case(isnum($TIMERANGE2.latest$), $TIMERANGE2.latest$, $TIMERANGE2.latest$=="now", time(), true(), relative_time(time(), $TIMERANGE2.latest$))</eval>
        </change>
      </input>-->
      <input type="link" id="submit_button">
        <label></label>
        <choice value="submit">Submit</choice>
      </input>
    </panel>
  </row>

  <search id="base">
    <query>
index=msexchange event_id=AGENTINFO sender_domain=MYDOMAIN.com | stats sum(total_bytes) as daily_bytes by sender,date_mday,date_month,date_year | eventstats avg(daily_bytes) as average stdev(daily_bytes) as sdev by sender | eval num_sdevs=(daily_bytes-average)/sdev | eval trigger="$submit_trigger$"
    </query>
    <earliest>$earliest_epoch$</earliest>
    <latest>$latest_epoch$</latest>
  </search>

  <row>
    <panel>        
      <input type="text" token="search">
        <label>Filter results by email:</label>
        <default>*</default>
      </input>
      <table>
        <title>Top 100 Anomalous Senders by Daily Bytes</title>
        <search base="base" id="base2">
          <query>
eval time=strptime(date_mday." ".date_month." ".date_year,"%d %B %Y") | where time >="$earliest_epoch_FILTER$" AND time <="$latest_epoch_FILTER$" |
sort 0 - num_sdevs | head 100 | search sender="$search$" | table sender date_mday date_month date_year daily_bytes average sdev num_sdevs
          </query>
        </search>
        <option name="wrap">true</option>
        <option name="rowNumbers">false</option>
        <option name="drilldown">none</option>
        <option name="dataOverlayMode">none</option>
        <option name="count">25</option>
      </table>
    </panel>
  </row>
  <row>
    <panel>        
      <table>
        <title>Repeat Senders in Top 100</title>
        <search base="base2">
          <query>
eventstats count by sender | where count >1 | table sender date_mday date_month date_year daily_bytes average sdev num_sdevs
          </query>
        </search>
        <option name="wrap">true</option>
        <option name="rowNumbers">false</option>
        <option name="drilldown">none</option>
        <option name="dataOverlayMode">none</option>
        <option name="count">5</option>
      </table>
    </panel>
  </row>

</dashboard>

JS:

 require([
     'jquery',
     'splunkjs/mvc',
     'splunkjs/mvc/simplexml/ready!'
 ], function($,mvc){
     var submittedTokens = mvc.Components.get("submitted");
     $("#submit_button").click(function(){
         submittedTokens.set("submit_trigger", ""+Math.random());
         submittedTokens.set("earliest_epoch",submittedTokens.get("earliest_epoch_onChange"));
         submittedTokens.set("latest_epoch",submittedTokens.get("latest_epoch_onChange"));
         submittedTokens.set("earliest_epoch_FILTER",submittedTokens.get("earliest_epoch_FILTER_onChange"));
         submittedTokens.set("latest_epoch_FILTER",submittedTokens.get("latest_epoch_FILTER_onChange"));
     });
 });

View solution in original post

0 Karma

nick405060
Motivator

Yes. This is a run anywhere dashboard if you have Exchange set up; just replace MYDOMAIN

<dashboard script="button_submit_mail_anomalies.js">
  <label>Anomalies</label>

    <row>
    <panel>
      <html depends="$hide$">
        <style>
          #submit_button{
            width:80px !important;
          }
          #submit_button div[data-component="splunk-core:/splunkjs/mvc/components/LinkList"]{
            width:80px !important;
          }
          #submit_button  button{
            padding: 6px 15px !important;
            border-radius: 3px !important;
            font-weight: 500 !important;
            background-color: #5cc05c !important;
            border: transparent !important;
            color: #fff !important;
          }
          #submit_button  button:hover{
            background-color: #40a540 !important;
            border-color: transparent !important;
          }
        </style>
      </html>
      <input type="time" token="TIMERANGE1">
        <label>Time Range (STDEV Baseline):</label>
        <default>
          <earliest>-30d</earliest>
        </default>
        <change>
          <eval token="earliest_epoch_onChange">case(isnum($TIMERANGE1.earliest$), $TIMERANGE1.earliest$, $TIMERANGE1.earliest$=="now", time(), $TIMERANGE1.earliest$="", 0, true(), relative_time(time(), $TIMERANGE1.earliest$))</eval>
          <eval token="latest_epoch_onChange">case(isnum($TIMERANGE1.latest$), $TIMERANGE1.latest$, $TIMERANGE1.latest$=="now", time(), true(), relative_time(time(), $TIMERANGE1.latest$))</eval>
        </change>
      </input>
      <input type="time" token="TIMERANGE2">
        <label>Time Range (Results Filter):</label>
        <default>
          <earliest>@w0</earliest>
        </default>
        <change>
          <eval token="earliest_epoch_FILTER_onChange">case(isnum($TIMERANGE2.earliest$), $TIMERANGE2.earliest$, $TIMERANGE2.earliest$=="now", time(), $TIMERANGE2.earliest$="", 0, true(), relative_time(time(), $TIMERANGE2.earliest$))</eval>
          <eval token="latest_epoch_FILTER_onChange">case(isnum($TIMERANGE2.latest$), $TIMERANGE2.latest$, $TIMERANGE2.latest$=="now", time(), true(), relative_time(time(), $TIMERANGE2.latest$))</eval>
        </change>
      </input>-->
      <input type="link" id="submit_button">
        <label></label>
        <choice value="submit">Submit</choice>
      </input>
    </panel>
  </row>

  <search id="base">
    <query>
index=msexchange event_id=AGENTINFO sender_domain=MYDOMAIN.com | stats sum(total_bytes) as daily_bytes by sender,date_mday,date_month,date_year | eventstats avg(daily_bytes) as average stdev(daily_bytes) as sdev by sender | eval num_sdevs=(daily_bytes-average)/sdev | eval trigger="$submit_trigger$"
    </query>
    <earliest>$earliest_epoch$</earliest>
    <latest>$latest_epoch$</latest>
  </search>

  <row>
    <panel>        
      <input type="text" token="search">
        <label>Filter results by email:</label>
        <default>*</default>
      </input>
      <table>
        <title>Top 100 Anomalous Senders by Daily Bytes</title>
        <search base="base" id="base2">
          <query>
eval time=strptime(date_mday." ".date_month." ".date_year,"%d %B %Y") | where time >="$earliest_epoch_FILTER$" AND time <="$latest_epoch_FILTER$" |
sort 0 - num_sdevs | head 100 | search sender="$search$" | table sender date_mday date_month date_year daily_bytes average sdev num_sdevs
          </query>
        </search>
        <option name="wrap">true</option>
        <option name="rowNumbers">false</option>
        <option name="drilldown">none</option>
        <option name="dataOverlayMode">none</option>
        <option name="count">25</option>
      </table>
    </panel>
  </row>
  <row>
    <panel>        
      <table>
        <title>Repeat Senders in Top 100</title>
        <search base="base2">
          <query>
eventstats count by sender | where count >1 | table sender date_mday date_month date_year daily_bytes average sdev num_sdevs
          </query>
        </search>
        <option name="wrap">true</option>
        <option name="rowNumbers">false</option>
        <option name="drilldown">none</option>
        <option name="dataOverlayMode">none</option>
        <option name="count">5</option>
      </table>
    </panel>
  </row>

</dashboard>

JS:

 require([
     'jquery',
     'splunkjs/mvc',
     'splunkjs/mvc/simplexml/ready!'
 ], function($,mvc){
     var submittedTokens = mvc.Components.get("submitted");
     $("#submit_button").click(function(){
         submittedTokens.set("submit_trigger", ""+Math.random());
         submittedTokens.set("earliest_epoch",submittedTokens.get("earliest_epoch_onChange"));
         submittedTokens.set("latest_epoch",submittedTokens.get("latest_epoch_onChange"));
         submittedTokens.set("earliest_epoch_FILTER",submittedTokens.get("earliest_epoch_FILTER_onChange"));
         submittedTokens.set("latest_epoch_FILTER",submittedTokens.get("latest_epoch_FILTER_onChange"));
     });
 });
0 Karma

nick405060
Motivator

P.S. I also have an alert for this:

[bytes_anomalies]
action.email = 1
action.email.cc = DELETED
action.email.include.search = 1
action.email.include.trigger = 1
action.email.include.trigger_time = 1
action.email.inline = 1
action.email.message.alert = Machine learning algorithm monitoring possible Exchange data exfil by internal senders.\
\
This alert is ran twice daily at 5AM (producing results since 12AM the previous day) and 5PM PST (producing results since 12AM the current day) with a STDEV baseline of 30 days. Total_bytes over 200MB AND num_sdevs over 4.0 alerted on only.
action.email.sendcsv = 1
action.email.sendresults = 1
action.email.subject = Splunk Alert: Exchange daily_bytes Anomaly Detection ($result.spl_id$)
action.email.to = DELETED
alert.suppress = 0
alert.track = 0
counttype = number of events
cron_schedule = 0 5,17 * * *
dispatch.earliest_time = -30d@d
dispatch.latest_time = now
display.general.type = statistics
display.page.search.tab = statistics
enableSched = 1
quantity = 0
relation = greater than
request.ui_dispatch_app = DELETED
request.ui_dispatch_view = search
search = index=msexchange event_id=AGENTINFO sender_domain=DELETED.com | stats sum(total_bytes) as daily_bytes by sender,date_mday,date_month,date_year | eventstats avg(daily_bytes) as average stdev(daily_bytes) as sdev by sender | eval num_sdevs=(daily_bytes-average)/sdev | \
eval time=strptime(date_mday." ".date_month." ".date_year,"%d %B %Y")  | where time >= relative_time(now(),"-12h@d") AND daily_bytes >= 200000000 AND num_sdevs >= 4.0 | sort 0 - num_sdevs | eval spl_id=strftime(now(),"SPL%m%d%y_%H%M") | table spl_id sender date_mday date_month date_year daily_bytes average sdev num_sdevs
0 Karma
Get Updates on the Splunk Community!

Introducing the 2024 SplunkTrust!

Hello, Splunk Community! We are beyond thrilled to announce our newest group of SplunkTrust members!  The ...

Introducing the 2024 Splunk MVPs!

We are excited to announce the 2024 cohort of the Splunk MVP program. Splunk MVPs are passionate members of ...

Splunk Custom Visualizations App End of Life

The Splunk Custom Visualizations apps End of Life for SimpleXML will reach end of support on Dec 21, 2024, ...