Skip to content

Commit 97daa61

Browse files
committed
Merge branch 'obs_to_rba' into improve_lookup_regex
2 parents deefd57 + 753b3b0 commit 97daa61

File tree

9 files changed

+280
-117
lines changed

9 files changed

+280
-117
lines changed

.github/workflows/test_against_escu.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ jobs:
3535
with:
3636
path: security_content
3737
repository: splunk/security_content
38+
ref: rba_migration
3839

3940
#Install the given version of Python we will test against
4041
- name: Install Required Python Version

contentctl/input/new_content_questions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def get_questions_detection(cls) -> list[dict[str,Any]]:
4848
{
4949
'type': 'checkbox',
5050
'message': 'Your data source',
51-
'name': 'data_source',
51+
'name': 'data_sources',
5252
#In the future, we should dynamically populate this from the DataSource Objects we have parsed from the data_sources directory
5353
'choices': sorted(DataSource._value2member_map_ )
5454

contentctl/objects/abstract_security_content_objects/detection_abstract.py

Lines changed: 200 additions & 92 deletions
Large diffs are not rendered by default.

contentctl/objects/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535

3636
class App_Base(BaseModel,ABC):
37+
3738
model_config = ConfigDict(validate_default=True, arbitrary_types_allowed=True, extra='forbid')
3839
uid: Optional[int] = Field(default=None)
3940
title: str = Field(description="Human-readable name used by the app. This can have special characters.")

contentctl/objects/detection_tags.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
class DetectionTags(BaseModel):
3939
# detection spec
40+
4041
model_config = ConfigDict(validate_default=False, extra='forbid')
4142
analytic_story: list[Story] = Field(...)
4243
asset_type: AssetType = Field(...)
@@ -64,7 +65,6 @@ def severity(self)->RiskSeverity:
6465

6566
# TODO (#249): Add pydantic validator to ensure observables are unique within a detection
6667
observable: List[Observable] = []
67-
message: str = Field(...)
6868
product: list[SecurityContentProductName] = Field(..., min_length=1)
6969
throttling: Optional[Throttling] = None
7070
security_domain: SecurityDomain = Field(...)
@@ -144,8 +144,6 @@ def serialize_model(self):
144144
"cis20": self.cis20,
145145
"kill_chain_phases": self.kill_chain_phases,
146146
"nist": self.nist,
147-
"observable": self.observable,
148-
"message": self.message,
149147
"risk_score": self.risk_score,
150148
"security_domain": self.security_domain,
151149
"risk_severity": self.severity,

contentctl/objects/mitre_attack_enrichment.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ def standardize_contributors(cls, contributors:list[str] | None) -> list[str]:
8484
return contributors
8585

8686
class MitreAttackEnrichment(BaseModel):
87+
8788
ConfigDict(extra='forbid')
8889
mitre_attack_id: MITRE_ATTACK_ID_TYPE = Field(...)
8990
mitre_attack_technique: str = Field(...)

contentctl/objects/rba.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from enum import Enum
2+
from pydantic import BaseModel
3+
from abc import ABC
4+
from typing import Set
5+
6+
7+
8+
class RiskObjectType(str, Enum):
9+
SYSTEM = "system"
10+
USER = "user"
11+
OTHER = "other"
12+
13+
class ThreatObjectType(str, Enum):
14+
CERTIFICATE_COMMON_NAME = "certificate_common_name"
15+
CERTIFICATE_ORGANIZATION = "certificate_organization"
16+
CERTIFICATE_SERIAL = "certificate_serial"
17+
CERTIFICATE_UNIT = "certificate_unit"
18+
COMMAND = "command"
19+
DOMAIN = "domain"
20+
EMAIL_ADDRESS = "email_address"
21+
EMAIL_SUBJECT = "email_subject"
22+
FILE_HASH = "file_hash"
23+
FILE_NAME = "file_name"
24+
FILE_PATH = "file_path"
25+
HTTP_USER_AGENT = "http_user_agent"
26+
IP_ADDRESS = "ip_address"
27+
PROCESS = "process"
28+
PROCESS_NAME = "process_name"
29+
PARENT_PROCESS = "parent_process"
30+
PARENT_PROCESS_NAME = "parent_process_name"
31+
PROCESS_HASH = "process_hash"
32+
REGISTRY_PATH = "registry_path"
33+
REGISTRY_VALUE_NAME = "registry_value_name"
34+
REGISTRY_VALUE_TEXT = "registry_value_text"
35+
SERVICE = "service"
36+
SYSTEM = "system"
37+
TLS_HASH = "tls_hash"
38+
URL = "url"
39+
40+
class risk_object(BaseModel):
41+
field: str
42+
type: RiskObjectType
43+
score: int
44+
45+
def __hash__(self):
46+
return hash((self.field, self.type, self.score))
47+
48+
class threat_object(BaseModel):
49+
field: str
50+
type: ThreatObjectType
51+
52+
def __hash__(self):
53+
return hash((self.field, self.type))
54+
55+
class rba_object(BaseModel, ABC):
56+
message: str
57+
risk_objects: Set[risk_object]
58+
threat_objects: Set[threat_object]

contentctl/output/templates/savedsearches_detections.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ action.escu.providing_technologies = null
4444
action.escu.analytic_story = {{ objectListToNameList(detection.tags.analytic_story) | tojson }}
4545
{% if detection.deployment.alert_action.rba.enabled%}
4646
action.risk = 1
47-
action.risk.param._risk_message = {{ detection.tags.message | escapeNewlines() }}
47+
action.risk.param._risk_message = {{ detection.rba.message | escapeNewlines() }}
4848
action.risk.param._risk = {{ detection.risk | tojson }}
4949
action.risk.param._risk_score = 0
5050
action.risk.param.verbose = 0

contentctl/templates/detections/endpoint/anomalous_usage_of_7zip.yml

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,35 +38,31 @@ drilldown_searches:
3838
search: '| from datamodel Risk.All_Risk | search normalized_risk_object IN ($user$, $dest$) starthoursago=168 endhoursago=1 | 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)`'
3939
earliest_offset: $info_min_time$
4040
latest_offset: $info_max_time$
41+
rba:
42+
message: An instance of $parent_process_name$ spawning $process_name$ was identified
43+
on endpoint $dest$ by user $user$. This behavior is indicative of suspicious loading
44+
of 7zip.
45+
risk_objects:
46+
- field: user
47+
type: user
48+
score: 56
49+
- field: dest
50+
type: system
51+
score: 60
52+
threat_objects:
53+
- field: parent_process_name
54+
type: parent_process_name
55+
- field: process_name
56+
type: process_name
4157
tags:
4258
analytic_story:
4359
- Cobalt Strike
4460
asset_type: Endpoint
4561
confidence: 80
4662
impact: 80
47-
message: An instance of $parent_process_name$ spawning $process_name$ was identified
48-
on endpoint $dest$ by user $user$. This behavior is indicative of suspicious loading
49-
of 7zip.
5063
mitre_attack_id:
5164
- T1560.001
5265
- T1560
53-
observable:
54-
- name: user
55-
type: User
56-
role:
57-
- Victim
58-
- name: dest
59-
type: Hostname
60-
role:
61-
- Victim
62-
- name: parent_process_name
63-
type: Process
64-
role:
65-
- Attacker
66-
- name: process_name
67-
type: Process
68-
role:
69-
- Attacker
7066
product:
7167
- Splunk Enterprise
7268
- Splunk Enterprise Security

0 commit comments

Comments
 (0)