Skip to content

Commit

Permalink
application detections score fix
Browse files Browse the repository at this point in the history
  • Loading branch information
ljstella committed Nov 15, 2024
1 parent c4eb58c commit c6739f2
Show file tree
Hide file tree
Showing 54 changed files with 1,649 additions and 382 deletions.
40 changes: 33 additions & 7 deletions detections/application/crushftp_server_side_template_injection.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,30 @@ data_source:
- CrushFTP
type: TTP
status: production
description: This analytic is designed to identify attempts to exploit a server-side template injection vulnerability in CrushFTP, designated as CVE-2024-4040. This severe vulnerability enables unauthenticated remote attackers to access and read files beyond the VFS Sandbox, circumvent authentication protocols, and execute arbitrary commands on the affected server. The issue impacts all versions of CrushFTP up to 10.7.1 and 11.1.0 on all supported platforms. It is highly recommended to apply patches immediately to prevent unauthorized access to the system and avoid potential data compromises. The search specifically looks for patterns in the raw log data that match the exploitation attempts, including READ or WRITE actions, and extracts relevant information such as the protocol, session ID, user, IP address, HTTP method, and the URI queried. It then evaluates these logs to confirm traces of exploitation based on the presence of specific keywords and the originating IP address, counting and sorting these events for further analysis.
search: '`crushftp` | rex field=_raw "\[(?<protocol>HTTPS|HTTP):(?<session_id>[^\:]+):(?<user>[^\:]+):(?<src_ip>\d+\.\d+\.\d+\.\d+)\] (?<action>READ|WROTE): \*(?<http_method>[A-Z]+) (?<uri_query>[^\s]+) HTTP/[^\*]+\*" | eval message=if(match(_raw, "INCLUDE") and isnotnull(src_ip), "traces of exploitation by " . src_ip, "false") | search message!=false | rename host as dest | stats count by _time, dest, source, message, src_ip, http_method, uri_query, user, action | sort -_time| `crushftp_server_side_template_injection_filter`'
how_to_implement: CrushFTP Session logs, from Windows or Linux, must be ingested to Splunk. Currently, there is no TA for CrushFTP, so the data must be extracted from the raw logs.
known_false_positives: False positives should be limited, however tune or filter as needed.
description: This analytic is designed to identify attempts to exploit a server-side
template injection vulnerability in CrushFTP, designated as CVE-2024-4040. This
severe vulnerability enables unauthenticated remote attackers to access and read
files beyond the VFS Sandbox, circumvent authentication protocols, and execute arbitrary
commands on the affected server. The issue impacts all versions of CrushFTP up to
10.7.1 and 11.1.0 on all supported platforms. It is highly recommended to apply
patches immediately to prevent unauthorized access to the system and avoid potential
data compromises. The search specifically looks for patterns in the raw log data
that match the exploitation attempts, including READ or WRITE actions, and extracts
relevant information such as the protocol, session ID, user, IP address, HTTP method,
and the URI queried. It then evaluates these logs to confirm traces of exploitation
based on the presence of specific keywords and the originating IP address, counting
and sorting these events for further analysis.
search: '`crushftp` | rex field=_raw "\[(?<protocol>HTTPS|HTTP):(?<session_id>[^\:]+):(?<user>[^\:]+):(?<src_ip>\d+\.\d+\.\d+\.\d+)\]
(?<action>READ|WROTE): \*(?<http_method>[A-Z]+) (?<uri_query>[^\s]+) HTTP/[^\*]+\*"
| eval message=if(match(_raw, "INCLUDE") and isnotnull(src_ip), "traces of exploitation
by " . src_ip, "false") | search message!=false | rename host as dest | stats count
by _time, dest, source, message, src_ip, http_method, uri_query, user, action |
sort -_time| `crushftp_server_side_template_injection_filter`'
how_to_implement: CrushFTP Session logs, from Windows or Linux, must be ingested to
Splunk. Currently, there is no TA for CrushFTP, so the data must be extracted from
the raw logs.
known_false_positives: False positives should be limited, however tune or filter as
needed.
references:
- https://github.com/airbus-cert/CVE-2024-4040
- https://www.bleepingcomputer.com/news/security/crushftp-warns-users-to-patch-exploited-zero-day-immediately/
Expand All @@ -20,7 +40,12 @@ drilldown_searches:
earliest_offset: $info_min_time$
latest_offset: $info_max_time$
- name: View risk events for the last 7 days for - "$dest$"
search: '| from datamodel Risk.All_Risk | search normalized_risk_object IN ("$dest$") starthoursago=168 | stats count min(_time) as firstTime max(_time) as lastTime values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories) as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic) as "ATT&CK Tactics" by normalized_risk_object | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`'
search: '| from datamodel Risk.All_Risk | search normalized_risk_object IN ("$dest$")
starthoursago=168 | stats count min(_time) as firstTime max(_time) as lastTime
values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories)
as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic)
as "ATT&CK Tactics" by normalized_risk_object | `security_content_ctime(firstTime)`
| `security_content_ctime(lastTime)`'
earliest_offset: $info_min_time$
latest_offset: $info_max_time$
rba:
Expand All @@ -29,7 +54,7 @@ rba:
risk_objects:
- field: dest
type: IP Address
risk_score: 64.0
risk_score: 64
threat_objects:
- field: src_ip
type: IP Address
Expand Down Expand Up @@ -62,6 +87,7 @@ tags:
tests:
- name: True Positive Test
attack_data:
- data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1190/crushftp/crushftp.log
- data:
https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1190/crushftp/crushftp.log
sourcetype: crushftp:sessionlogs
source: crushftp
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,53 @@ status: production
type: Hunting
data_source:
- Azure Active Directory Sign-in activity
description: This analytic employs the 3-sigma approach to identify distributed password spray attacks. A
distributed password spray attack is a type of brute force attack where the attacker attempts a few
common passwords against many different accounts, connecting from multiple IP addresses to avoid detection.
By utilizing the Authentication Data Model, this detection is effective for all CIM-mapped authentication
events, providing comprehensive coverage and enhancing security against these attacks.
description: This analytic employs the 3-sigma approach to identify distributed password
spray attacks. A distributed password spray attack is a type of brute force attack
where the attacker attempts a few common passwords against many different accounts,
connecting from multiple IP addresses to avoid detection. By utilizing the Authentication
Data Model, this detection is effective for all CIM-mapped authentication events,
providing comprehensive coverage and enhancing security against these attacks.
search: >-
| tstats `security_content_summariesonly` dc(Authentication.user) AS unique_accounts dc(Authentication.src) as unique_src values(Authentication.app) as app values(Authentication.src) as src count(Authentication.user) as total_failures from datamodel=Authentication.Authentication where Authentication.action="failure" NOT Authentication.src IN ("-","unknown") Authentication.user_agent="*" by Authentication.signature_id, Authentication.user_agent, sourcetype, _time span=10m
| tstats `security_content_summariesonly` dc(Authentication.user) AS unique_accounts
dc(Authentication.src) as unique_src values(Authentication.app) as app values(Authentication.src)
as src count(Authentication.user) as total_failures from datamodel=Authentication.Authentication
where Authentication.action="failure" NOT Authentication.src IN ("-","unknown")
Authentication.user_agent="*" by Authentication.signature_id, Authentication.user_agent,
sourcetype, _time span=10m
| `drop_dm_object_name("Authentication")`
```fill out time buckets for 0-count events during entire search length```
| appendpipe [| timechart limit=0 span=10m count | table _time]
| fillnull value=0 unique_accounts, unique_src
``` Create aggregation field & apply to all null events```
| eval counter=sourcetype+"__"+signature_id
| eventstats values(counter) as fnscounter | eval counter=coalesce(counter,fnscounter)
| stats values(total_failures) as total_failures values(signature_id) as signature_id values(src) as src values(sourcetype) as sourcetype values(app) as app count by counter unique_accounts unique_src user_agent _time
| eventstats values(counter) as fnscounter | eval counter=coalesce(counter,fnscounter) |
stats values(total_failures) as total_failures values(signature_id) as signature_id
values(src) as src values(sourcetype) as sourcetype values(app) as app count by
counter unique_accounts unique_src user_agent _time
``` remove 0 count rows where counter has data```
| sort - _time unique_accounts
| dedup _time counter
``` 3-sigma detection logic ```
| eventstats avg(unique_accounts) as comp_avg_user , stdev(unique_accounts) as comp_std_user avg(unique_src) as comp_avg_src , stdev(unique_src) as comp_std_src by counter user_agent
| eventstats avg(unique_accounts) as comp_avg_user , stdev(unique_accounts) as comp_std_user
avg(unique_src) as comp_avg_src , stdev(unique_src) as comp_std_src by counter user_agent
| eval upperBoundUser=(comp_avg_user+comp_std_user*3), upperBoundsrc=(comp_avg_src+comp_std_src*3)
| eval isOutlier=if((unique_accounts > 30 and unique_accounts >= upperBoundUser) and (unique_src > 30 and unique_src >= upperBoundsrc), 1, 0)
| eval isOutlier=if((unique_accounts > 30 and unique_accounts >= upperBoundUser)
and (unique_src > 30 and unique_src >= upperBoundsrc), 1, 0)
| replace "::ffff:*" with * in src
| where isOutlier=1
| foreach *
[ eval <<FIELD>> = if(<<FIELD>>="null",null(),<<FIELD>>)]
| mvexpand src
| iplocation src
| table _time, unique_src, unique_accounts, total_failures, sourcetype, signature_id, user_agent, src, Country
| mvexpand src | iplocation src | table _time, unique_src, unique_accounts, total_failures,
sourcetype, signature_id, user_agent, src, Country
| eval date_wday=strftime(_time,"%a"), date_hour=strftime(_time,"%H")
| `detect_distributed_password_spray_attempts_filter`
how_to_implement: Ensure that all relevant authentication data is mapped to the Common Information Model (CIM)
and that the src field is populated with the source device information. Additionally, ensure that
fill_nullvalue is set within the security_content_summariesonly macro to include authentication events from
log sources that do not feature the signature_id field in the results.
known_false_positives: It is common to see a spike of legitimate failed authentication events on monday mornings.
how_to_implement: Ensure that all relevant authentication data is mapped to the Common
Information Model (CIM) and that the src field is populated with the source device
information. Additionally, ensure that fill_nullvalue is set within the security_content_summariesonly
macro to include authentication events from log sources that do not feature the
signature_id field in the results.
known_false_positives: It is common to see a spike of legitimate failed authentication
events on monday mornings.
references:
- https://attack.mitre.org/techniques/T1110/003/
rba:
Expand Down Expand Up @@ -74,10 +85,12 @@ tags:
- Authentication.user
- Authentication.src
security_domain: access
manual_test: The dataset & hardcoded timerange doesn't meet the criteria for this detetion.
manual_test: The dataset & hardcoded timerange doesn't meet the criteria for this
detetion.
tests:
- name: True Positive Test
attack_data:
- data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1110.003/azure_ad_distributed_spray/azure_ad_distributed_spray.log
- data:
https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1110.003/azure_ad_distributed_spray/azure_ad_distributed_spray.log
source: azure:monitor:aad
sourcetype: azure:monitor:aad
23 changes: 18 additions & 5 deletions detections/application/detect_new_login_attempts_to_routers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,34 @@ date: '2024-10-17'
author: Bhavin Patel, Splunk
status: experimental
type: TTP
description: The following analytic identifies new login attempts to routers. It leverages authentication logs from the ES Assets and Identity Framework, focusing on assets categorized as routers. The detection flags connections that have not been observed in the past 30 days. This activity is significant because unauthorized access to routers can lead to network disruptions or data interception. If confirmed malicious, attackers could gain control over network traffic, potentially leading to data breaches or further network compromise.
description: The following analytic identifies new login attempts to routers. It leverages
authentication logs from the ES Assets and Identity Framework, focusing on assets
categorized as routers. The detection flags connections that have not been observed
in the past 30 days. This activity is significant because unauthorized access to
routers can lead to network disruptions or data interception. If confirmed malicious,
attackers could gain control over network traffic, potentially leading to data breaches
or further network compromise.
data_source: []
search: '| tstats `security_content_summariesonly` count earliest(_time) as earliest latest(_time) as latest from datamodel=Authentication where Authentication.dest_category=router by Authentication.dest Authentication.user| eval isOutlier=if(earliest >= relative_time(now(), "-30d@d"), 1, 0) | where isOutlier=1| `security_content_ctime(earliest)`| `security_content_ctime(latest)` | `drop_dm_object_name("Authentication")` | `detect_new_login_attempts_to_routers_filter`'
how_to_implement: To successfully implement this search, you must ensure the network router devices are categorized as "router" in the Assets and identity table. You must also populate the Authentication data model with logs related to users authenticating to routing infrastructure.
search: '| tstats `security_content_summariesonly` count earliest(_time) as earliest
latest(_time) as latest from datamodel=Authentication where Authentication.dest_category=router
by Authentication.dest Authentication.user| eval isOutlier=if(earliest >= relative_time(now(),
"-30d@d"), 1, 0) | where isOutlier=1| `security_content_ctime(earliest)`| `security_content_ctime(latest)`
| `drop_dm_object_name("Authentication")` | `detect_new_login_attempts_to_routers_filter`'
how_to_implement: To successfully implement this search, you must ensure the network
router devices are categorized as "router" in the Assets and identity table. You
must also populate the Authentication data model with logs related to users authenticating
to routing infrastructure.
known_false_positives: Legitimate router connections may appear as new connections
references: []
rba:
message: tbd
risk_objects:
- field: user
type: User
risk_score: 25.0
risk_score: 25
- field: dest
type: Hostname
risk_score: 25.0
risk_score: 25
threat_objects: []
tags:
analytic_story:
Expand Down
Loading

0 comments on commit c6739f2

Please sign in to comment.