Skip to content

Commit cdb8350

Browse files
Merge branch 'main' into terrancedejesus/issue5353
2 parents 80df7bc + 166da45 commit cdb8350

File tree

84 files changed

+4967
-689
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+4967
-689
lines changed

detection_rules/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ def parse_rules_config(path: Path | None = None) -> RulesConfig: # noqa: PLR091
227227
raise ValueError(f"rules config file does not exist: {path}")
228228
loaded = yaml.safe_load(path.read_text())
229229
elif CUSTOM_RULES_DIR:
230-
path = Path(CUSTOM_RULES_DIR) / "_config.yaml"
230+
path = Path(CUSTOM_RULES_DIR).expanduser() / "_config.yaml"
231231
if not path.exists():
232232
raise FileNotFoundError(
233233
"""

detection_rules/etc/non-ecs-schema.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@
145145
"kibana.alert.rule.threat.tactic.id": "keyword",
146146
"kibana.alert.workflow_status": "keyword",
147147
"kibana.alert.rule.rule_id": "keyword",
148-
"kibana.alert.rule.name": "keyword",
148+
"kibana.alert.rule.name": "keyword",
149149
"kibana.alert.risk_score": "long",
150150
"kibana.alert.rule.type": "keyword",
151151
"kibana.alert.rule.threat.tactic.name": "keyword"
@@ -237,7 +237,8 @@
237237
"o365.audit.ExtendedProperties.ResultStatusDetail": "keyword",
238238
"o365.audit.OperationProperties.Name": "keyword",
239239
"o365.audit.OperationProperties.Value": "keyword",
240-
"o365.audit.OperationCount": "long"
240+
"o365.audit.OperationCount": "long",
241+
"o365.audit.AppAccessContext.AADSessionId": "keyword"
241242
},
242243
"logs-okta*": {
243244
"okta.debug_context.debug_data.flattened.requestedScopes": "keyword",

detection_rules/schemas/definitions.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ def validator_wrapper(value: Any) -> Any:
7676
CONDITION_VERSION_PATTERN = re.compile(rf"^\^{_version}$")
7777
VERSION_PATTERN = f"^{_version}$"
7878
MINOR_SEMVER = re.compile(r"^\d+\.\d+$")
79-
FROM_SOURCES_REGEX = re.compile(r"^\s*FROM\s+(?P<sources>.+?)\s*(?:\||\bmetadata\b|//|$)", re.IGNORECASE | re.MULTILINE)
79+
FROM_SOURCES_REGEX = re.compile(
80+
r"^\s*FROM\s+(?P<sources>(?:.+?(?:,\s*)?\n?)+?)\s*(?:\||\bmetadata\b|//|$)", re.IGNORECASE | re.MULTILINE
81+
)
8082
BRANCH_PATTERN = f"{VERSION_PATTERN}|^master$"
8183
ELASTICSEARCH_EQL_FEATURES = {
8284
"allow_negation": (Version.parse("8.9.0"), None),

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "detection_rules"
3-
version = "1.5.17"
3+
version = "1.5.19"
44
description = "Detection Rules is the home for rules used by Elastic Security. This repository is used for the development, maintenance, testing, validation, and release of rules for Elastic Security’s Detection Engine."
55
readme = "README.md"
66
requires-python = ">=3.12"

rules/linux/command_and_control_curl_wget_spawn_via_nodejs_parent.toml renamed to rules/cross-platform/command_and_control_curl_wget_spawn_via_nodejs_parent.toml

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
[metadata]
22
creation_date = "2025/09/18"
3-
integration = ["endpoint", "crowdstrike"]
3+
integration = ["endpoint", "windows", "system", "sentinel_one_cloud_funnel", "crowdstrike", "auditd_manager"]
44
maturity = "production"
5-
updated_date = "2025/10/17"
5+
updated_date = "2025/11/26"
66

77
[rule]
88
author = ["Elastic"]
@@ -12,7 +12,18 @@ command and control behavior. Adversaries may use Node.js to download additional
1212
the system.
1313
"""
1414
from = "now-9m"
15-
index = ["logs-endpoint.events.process*", "logs-crowdstrike.fdr*"]
15+
index = [
16+
"endgame-*",
17+
"logs-crowdstrike.fdr*",
18+
"logs-endpoint.events.process-*",
19+
"logs-sentinel_one_cloud_funnel.*",
20+
"logs-system.security*",
21+
"logs-windows.forwarded*",
22+
"logs-windows.sysmon_operational-*",
23+
"winlogbeat-*",
24+
"auditbeat-*",
25+
"logs-auditd_manager.auditd-*"
26+
]
1627
language = "eql"
1728
license = "Elastic License v2"
1829
name = "Curl or Wget Spawned via Node.js"
@@ -46,7 +57,7 @@ This rule flags Node.js launching curl or wget, directly or via a shell, a commo
4657
- Rebuild and redeploy the workload from a known-good image, remove the malicious child_process code path from the Node.js application, restore validated configs/data, rotate any keys or tokens used by that service, and verify no further curl/wget spawns occur post-recovery.
4758
- Harden by removing curl/wget from runtime images where not required, enforcing egress allowlists for the service, constraining execution with AppArmor/SELinux/seccomp and least-privilege service accounts, and adding CI/CD checks to block package.json postinstall scripts or code that shells out to downloaders.
4859
"""
49-
risk_score = 21
60+
risk_score = 47
5061
rule_id = "d9af2479-ad13-4471-a312-f586517f1243"
5162
setup = """## Setup
5263
@@ -73,28 +84,38 @@ For more details on Elastic Agent configuration settings, refer to the [helper g
7384
- To complete the integration, select "Add Elastic Agent to your hosts" and continue to the next section to install the Elastic Agent on your hosts.
7485
For more details on Elastic Defend refer to the [helper guide](https://www.elastic.co/guide/en/security/current/install-endpoint.html).
7586
"""
76-
severity = "low"
87+
severity = "medium"
7788
tags = [
7889
"Domain: Endpoint",
7990
"OS: Linux",
91+
"OS: Windows",
92+
"OS: macOS",
8093
"Use Case: Threat Detection",
8194
"Tactic: Command and Control",
82-
"Data Source: Elastic Defend",
8395
"Resources: Investigation Guide",
96+
"Data Source: Elastic Defend",
97+
"Data Source: Elastic Endgame",
98+
"Data Source: Windows Security Event Logs",
99+
"Data Source: Sysmon",
100+
"Data Source: SentinelOne",
84101
"Data Source: Crowdstrike",
102+
"Data Source: Auditd Manager",
85103
]
86104
timestamp_override = "event.ingested"
87105
type = "eql"
88106
query = '''
89-
process where host.os.type == "linux" and event.type == "start" and event.action in ("exec", "ProcessRollup2") and process.parent.name == "node" and (
107+
process where event.type == "start" and
108+
event.action in ("exec", "exec_event", "start", "ProcessRollup2", "executed", "process_started") and
109+
process.parent.name in ("node", "bun", "node.exe", "bun.exe") and (
90110
(
91-
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish") and
92-
process.args == "-c" and process.command_line like~ ("*curl*", "*wget*")
111+
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "cmd.exe", "bash.exe", "powershell.exe") and
112+
process.command_line like~ ("*curl*http*", "*wget*http*")
93113
) or
94114
(
95-
process.name in ("curl", "wget")
115+
process.name in ("curl", "wget", "curl.exe", "wget.exe")
96116
)
97-
)
117+
) and
118+
not process.command_line like ("*127.0.0.1*", "*localhost*")
98119
'''
99120

100121
[[rule.threat]]
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
[metadata]
2+
creation_date = "2025/11/28"
3+
integration = ["endpoint", "windows", "system", "m365_defender", "sentinel_one_cloud_funnel", "crowdstrike", "auditd_manager"]
4+
maturity = "production"
5+
updated_date = "2025/11/28"
6+
7+
[rule]
8+
author = ["Elastic"]
9+
description = """
10+
This rule detects the execution of Gitleaks, a tool used to search for high-entropy strings and secrets in code
11+
repositories, which may indicate an attempt to access credentials.
12+
"""
13+
false_positives = [
14+
"""
15+
Gitleaks is a legitimate open-source tool used by security professionals and developers to search for sensitive
16+
information, such as passwords, API keys, and other secrets, within code repositories. It is commonly employed
17+
during security assessments and code reviews to identify potential vulnerabilities.
18+
""",
19+
]
20+
from = "now-9m"
21+
index = [
22+
"endgame-*",
23+
"logs-crowdstrike.fdr*",
24+
"logs-endpoint.events.process-*",
25+
"logs-m365_defender.event-*",
26+
"logs-sentinel_one_cloud_funnel.*",
27+
"logs-system.security*",
28+
"logs-windows.forwarded*",
29+
"logs-windows.sysmon_operational-*",
30+
"winlogbeat-*",
31+
"auditbeat-*",
32+
"logs-auditd_manager.auditd-*"
33+
]
34+
language = "eql"
35+
license = "Elastic License v2"
36+
name = "Potential Secret Scanning via Gitleaks"
37+
note = """## Triage and analysis
38+
39+
> **Disclaimer**:
40+
> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.
41+
42+
### Investigating Potential Secret Scanning via Gitleaks
43+
44+
This alert fires when a host launches Gitleaks, a secret-scanning utility that hunts high-entropy strings and credentials in source code and repositories, signaling potential credential harvesting. An attacker may clone internal repos or traverse local workspace directories, drop a portable gitleaks binary in /tmp or %TEMP%, run recursive scans with wide rule sets and JSON output, then archive the results to exfiltrate tokens, API keys, and passwords for lateral movement and service impersonation.
45+
46+
### Possible investigation steps
47+
48+
- Review the full command line to identify --path/--repo/--report/--format flags, which reveal scope and whether results are being written for exfiltration.
49+
- Examine parent and ancestry plus user session to determine if it was launched by CI/dev tooling versus an interactive shell, and note execution from temp or unusual directories suggesting a dropped portable binary.
50+
- Locate and inspect newly created artifacts (gitleaks.json, .sarif, .csv, zip archives) near the event time, confirm the presence of secrets, and map their sensitivity to affected systems.
51+
- Correlate with network and data movement around the event for clones to internal repos and outbound transfers to cloud storage, paste sites, or email, and capture repository URLs or destinations if present.
52+
- Trace how the binary arrived by checking recent downloads and file writes (curl/wget, package managers, GitHub releases), verify the binary’s hash and signer, and compare against known-good sources.
53+
54+
### False positive analysis
55+
56+
- A developer or security team member intentionally runs gitleaks to audit internal code for secrets during routine hygiene, producing local report artifacts and showing normal parent processes without exfiltration behavior.
57+
- A user invokes gitleaks with --version or --help to validate installation or review usage, which generates a process start event but performs no scanning or credential access.
58+
59+
### Response and remediation
60+
61+
- If the run was unauthorized or executed from /tmp, %TEMP%, or a user profile, terminate gitleaks.exe/gitleaks, isolate the host from the network, and capture the binary path and hash for forensics.
62+
- Quarantine report artifacts produced by the run (gitleaks.json, .sarif, .csv, and any zip archives) by securing copies for evidence, removing world-readable permissions, and deleting residual copies from the working directory, Downloads, repo folders, and CI workspaces after collection.
63+
- Eradicate tooling by removing the dropped gitleaks binary and any wrapper scripts or CI job steps that invoke it, and enforce execution blocking for gitleaks in user-writable paths via application control or EDR policy.
64+
- Immediately revoke and rotate any secrets confirmed in the reports or repository (cloud API keys, service tokens, SSH keys, credentials), purge them from repo history (git filter-repo/BFG) if present, redeploy updated secrets from the vault, and force password resets for affected accounts.
65+
- Review git activity and data movement around the event for repo clones and exports, and inspect outbound transfers of report files to cloud storage, paste sites, or email; escalate to Incident Response and Legal if any report left the device or if production/customer credentials are exposed.
66+
- Harden going forward by enabling approved server-side and CI secret scanning, enforcing pre-commit hooks, prohibiting PATs with broad scopes, restricting egress to paste/file-sharing sites, and blocking execution of portable binaries from temp and user-writable locations."""
67+
references = [
68+
"https://www.elastic.co/blog/shai-hulud-worm-npm-supply-chain-compromise",
69+
"https://socket.dev/blog/shai-hulud-strikes-again-v2",
70+
]
71+
risk_score = 47
72+
rule_id = "f92171ed-a4d3-4baa-98f9-4df1652cb11b"
73+
severity = "medium"
74+
tags = [
75+
"Domain: Endpoint",
76+
"OS: Linux",
77+
"OS: Windows",
78+
"OS: macOS",
79+
"Use Case: Threat Detection",
80+
"Tactic: Credential Access",
81+
"Data Source: Elastic Endgame",
82+
"Data Source: Elastic Defend",
83+
"Data Source: Windows Security Event Logs",
84+
"Data Source: Microsoft Defender for Endpoint",
85+
"Data Source: Sysmon",
86+
"Data Source: SentinelOne",
87+
"Data Source: Crowdstrike",
88+
"Data Source: Auditd Manager",
89+
"Resources: Investigation Guide",
90+
]
91+
timestamp_override = "event.ingested"
92+
type = "eql"
93+
query = '''
94+
process where event.type == "start" and event.action like ("exec", "exec_event", "start", "ProcessRollup2", "executed", "process_started", "Process Create*") and
95+
process.name : ("gitleaks.exe", "gitleaks")
96+
'''
97+
98+
[[rule.threat]]
99+
framework = "MITRE ATT&CK"
100+
101+
[[rule.threat.technique]]
102+
id = "T1003"
103+
name = "OS Credential Dumping"
104+
reference = "https://attack.mitre.org/techniques/T1003/"
105+
106+
[[rule.threat.technique]]
107+
id = "T1555"
108+
name = "Credentials from Password Stores"
109+
reference = "https://attack.mitre.org/techniques/T1555/"
110+
111+
[rule.threat.tactic]
112+
id = "TA0006"
113+
name = "Credential Access"
114+
reference = "https://attack.mitre.org/tactics/TA0006/"

0 commit comments

Comments
 (0)