DEV Community

Flimtix
Flimtix

Posted on

Splunk Dashboards

I created these dashboards for splunk to detect some attacks:

Apache Error Log Monitoring Dashboard

<form version="1.1" theme="dark">
  <label>Apache Error Log Monitoring Dashboard</label>
  <description>Monitors Apache error logs for potential security events and path traversal attempts</description>
  <fieldset submitButton="false" autoRun="true"></fieldset>
  <row>
    <panel>
      <title>Amount Of Errors Over Time</title>
      <chart>
        <search>
          <query>source="/var/log/apache2/error.log" sourcetype="apache_error" 
            | eval mytime=strftime(_time,"%Y-%m-%d %H:%M")
            | stats count as error_count by mytime
            | sort -error_count
            </query>
          <earliest>-24h</earliest>
          <latest>now</latest>
        </search>
        <option name="charting.chart">pie</option>
        <option name="charting.drilldown">none</option>
      </chart>
    </panel>
    <panel>
      <title>Error Activity Over Time</title>
      <chart>
        <search>
          <query>source="/var/log/apache2/error.log" sourcetype="apache_error" 
          | timechart span=5m count by host</query>
          <earliest>-24h</earliest>
          <latest>now</latest>
        </search>
        <option name="charting.chart">line</option>
        <option name="charting.drilldown">none</option>
        <option name="charting.legend.placement">bottom</option>
      </chart>
    </panel>
  </row>
  <row>
    <panel>
      <title>Path Traversal Attempts</title>
      <table>
        <search>
          <query>source="/var/log/apache2/error.log" sourcetype="apache_error" "AH00126: Invalid URI" OR "/../" OR ".." OR "%2E%2E"
            | rex field=_raw "GET (?&lt;request_path&gt;[^ ]+) HTTP" 
            | table _time client request_path
            | sort -_time</query>
          <earliest>-24h</earliest>
          <latest>now</latest>
        </search>
        <option name="drilldown">none</option>
      </table>
    </panel>
  </row>
  <row>
    <panel>
      <title>Admin Page Probing</title>
      <chart>
        <search>
          <query>source="/var/log/apache2/error.log" sourcetype="apache_error" "admin" OR "administrator" OR "login" OR "cp" OR "controlpanel" 
          | rex field=_raw "script '(?&lt;requested_script&gt;[^']+)'" 
          | stats count by requested_script 
          | sort -count</query>
          <earliest>-24h</earliest>
          <latest>now</latest>
        </search>
        <option name="charting.chart">bar</option>
        <option name="charting.drilldown">none</option>
        <option name="charting.chart.stackMode">default</option>
        <option name="charting.legend.placement">bottom</option>
      </chart>
    </panel>
  </row>
  <row>
    <panel>
      <title>Top Client IPs</title>
      <chart>
        <search>
          <query>source="/var/log/apache2/error.log" sourcetype="apache_error" 
          | rex field=_raw "\[client (?&lt;client_ip&gt;[^\:]+)\:(?&lt;client_port&gt;\d+)\]" 
          | stats count by client_ip 
          | sort -count</query>
          <earliest>-24h</earliest>
          <latest>now</latest>
        </search>
        <option name="charting.chart">column</option>
        <option name="charting.drilldown">none</option>
      </chart>
    </panel>
    <panel>
      <title>Process IDs with Errors</title>
      <chart>
        <search>
          <query>source="/var/log/apache2/error.log" sourcetype="apache_error" 
          | rex field=_raw "\[pid (?&lt;process_id&gt;\d+)\]" 
          | stats count by process_id 
          | sort -count</query>
          <earliest>-24h</earliest>
          <latest>now</latest>
        </search>
        <option name="charting.chart">pie</option>
        <option name="charting.drilldown">none</option>
      </chart>
    </panel>
  </row>
  <row>
    <panel>
      <title>Recent Critical Events</title>
      <table>
        <search>
          <query>source="/var/log/apache2/error.log" sourcetype="apache_error" "Invalid URI" OR "/etc/shadow" OR "/etc/passwd" OR "../" OR "%2E%2E" OR "/.." 
          | rex field=_raw "GET (?&lt;request_path&gt;[^ ]+)" 
          | rex field=_raw "\[client (?&lt;client_ip&gt;[^\:]+)\:(?&lt;client_port&gt;\d+)\]" 
          | table _time client_ip request_path 
          | sort -_time</query>
          <earliest>-24h</earliest>
          <latest>now</latest>
        </search>
        <option name="count">10</option>
        <option name="drilldown">none</option>
      </table>
    </panel>
  </row>
  <row>
    <panel>
      <title>Search for Suspicious Activity</title>
      <input type="text" token="search_term" searchWhenChanged="true">
        <label>Search Term</label>
        <default>shadow</default>
      </input>
      <table>
        <search>
          <query>source="/var/log/apache2/error.log" sourcetype="apache_error" "$search_term$" 
          | table _time _raw 
          | sort -_time</query>
          <earliest>-24h</earliest>
          <latest>now</latest>
        </search>
        <option name="count">5</option>
        <option name="drilldown">none</option>
      </table>
    </panel>
  </row>
</form>
Enter fullscreen mode Exit fullscreen mode

Path Traversal Attempts


<form version="1.1" theme="dark">
  <label>Path Traversal Attempts</label>
  <description></description>
  <row>
    <panel>
      <title>Top Missing Scripts</title>
      <chart>
        <search>
          <query>index=main sourcetype=apache_error "not found or unable to stat" 
| rex field=_raw "script '(?&lt;script_path&gt;[^']+)' not found" 
| stats count by script_path 
| sort -count</query>
        </search>
        <option name="charting.chart">bar</option>
        <option name="charting.legend.placement">right</option>
        <option name="height">250</option>
      </chart>
    </panel>
    <panel>
      <title>Path Traversal Attempts</title>
      <chart>
        <search>
          <query>index=main sourcetype=apache_error "Invalid URI" 
| regex _raw="(\.\./){2,}" 
| stats count by host, source, _time 
| sort -_time</query>
        </search>
        <option name="charting.chart">column</option>
        <option name="height">250</option>
      </chart>
    </panel>
  </row>
  <row>
    <panel>
      <title>Recent PHP Errors</title>
      <table>
        <search>
          <query>index=main sourcetype=apache_error "php7:error" 
| rex field=_raw "script '(?&lt;script&gt;[^']+)' not found" 
| table _time, script, client, host</query>
        </search>
        <option name="count">10</option>
      </table>
    </panel>
    <panel>
      <title>Uncommon Events</title>
      <table>
        <search>
          <query>index=main sourcetype=apache_error 
| rare _raw 
| table _time, _raw</query>
        </search>
        <option name="count">10</option>
      </table>
    </panel>
  </row>
</form>
Enter fullscreen mode Exit fullscreen mode

SSH Brute Force Attack Dashboard

<dashboard version="1.1" theme="light">
  <label>SSH Brute Force Attack Dashboard</label>
  <description>Monitor and detect SSH brute force activities in real time</description>
  <row>
    <panel>
      <title>SSH Login Attempts Over Time</title>
      <chart>
        <search>
          <query>
            index=* sourcetype="auth"
            | search "ssh*" AND ("Failed password" OR "authentication failure" OR "Invalid user")
            | bucket span=1m _time
            | stats count as login_attempts by _time
          </query>
          <earliest>-24h@h</earliest>
          <latest>now</latest>
        </search>
        <option name="charting.chart">line</option>
      </chart>
    </panel>

    <panel>
      <title>Top Attacking IPs</title>
      <chart>
        <search>
          <query>
            index=* sourcetype="auth"
            | search "ssh*" AND ("Failed password" OR "authentication failure" OR "Invalid user")
            | eval src_ip=coalesce(src_ip, source_ip, src, clientip, rhost)
            | stats count by src_ip
            | sort -count
            | head 10
          </query>
          <earliest>-24h@h</earliest>
          <latest>now</latest>
        </search>
        <option name="charting.chart">bar</option>
      </chart>
    </panel>
  </row>

  <row>
    <panel>
      <title>Top Targeted Usernames</title>
      <chart>
        <search>
          <query>
            index=* sourcetype="auth"
            | search "ssh*" AND ("Failed password" OR "authentication failure" OR "Invalid user")
            | rex field=_raw "(?:for|user)\s+(?:invalid user\s+)?(?&lt;user&gt;\w+)"
            | stats count by user
            | sort -count
            | head 10
          </query>
          <earliest>-24h@h</earliest>
          <latest>now</latest>
        </search>
        <option name="charting.chart">pie</option>
      </chart>
    </panel>

    <panel>
      <title>Success vs Failure Attempts</title>
      <chart>
        <search>
          <query>
            index="*" sourcetype="auth" "ssh*" 
| eval status=case(
    like(_raw, "%Accepted password%"), "Success",
    like(_raw, "%Failed password%") OR like(_raw, "%authentication failure%") OR like(_raw, "%Invalid user%"), "Failure"
)
| stats count by status
          </query>
          <earliest>-24h@h</earliest>
          <latest>now</latest>
        </search>
        <option name="charting.chart">pie</option>
      </chart>
    </panel>
  </row>

  <row>
    <panel>
      <title>Detailed SSH Brute Force Attempts</title>
      <table>
        <search>
          <query>
            index=* sourcetype="auth"
            | search "ssh*" AND ("Failed password" OR "authentication failure" OR "Invalid user")
            | rex field=_raw "(?:for|user)\s+(?:invalid user\s+)?(?&lt;user&gt;\w+)"
            | eval src_ip=coalesce(src_ip, source_ip, src, clientip, rhost)
            | table _time, src_ip, user, host, _raw
          </query>
          <earliest>-24h@h</earliest>
          <latest>now</latest>
        </search>
      </table>
    </panel>
  </row>
</dashboard>
Enter fullscreen mode Exit fullscreen mode

Top comments (0)