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 (?<request_path>[^ ]+) 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 '(?<requested_script>[^']+)'"
| 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 (?<client_ip>[^\:]+)\:(?<client_port>\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 (?<process_id>\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 (?<request_path>[^ ]+)"
| rex field=_raw "\[client (?<client_ip>[^\:]+)\:(?<client_port>\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>
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 '(?<script_path>[^']+)' 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 '(?<script>[^']+)' 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>
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+)?(?<user>\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+)?(?<user>\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>
Top comments (0)