Skip to content

Commit 58dd7ad

Browse files
committed
Merge branch 'yara-rules' into collect-sigma-rules-api
# Conflicts: # vulnerabilities/improvers/__init__.py # vulnerabilities/migrations/0116_detectionrule.py
2 parents bfe4080 + 315e569 commit 58dd7ad

8 files changed

Lines changed: 371 additions & 6 deletions

File tree

vulnerabilities/improvers/__init__.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from vulnerabilities.pipelines.v2_improvers import relate_severities
3535
from vulnerabilities.pipelines.v2_improvers import sigma_rules
3636
from vulnerabilities.pipelines.v2_improvers import unfurl_version_range as unfurl_version_range_v2
37+
from vulnerabilities.pipelines.v2_improvers import yara_rules
3738
from vulnerabilities.utils import create_registry
3839

3940
IMPROVERS_REGISTRY = create_registry(
@@ -75,9 +76,6 @@
7576
compute_advisory_todo.ComputeToDo,
7677
collect_ssvc_trees.CollectSSVCPipeline,
7778
relate_severities.RelateSeveritiesPipeline,
78-
sigma_rules.SigmaHQImproverPipeline,
79-
sigma_rules.SigmaSamuraiMDRImproverPipeline,
80-
sigma_rules.SigmaMbabinskiImproverPipeline,
81-
sigma_rules.P4T12ICKSigmaImproverPipeline,
79+
yara_rules.YaraRulesImproverPipeline,
8280
]
8381
)

vulnerabilities/migrations/0116_detectionrule.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# Generated by Django 5.2.11 on 2026-03-07 14:44
2-
31
import django.db.models.deletion
42
from django.db import migrations, models
53

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# VulnerableCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
7+
# See https://aboutcode.org for more information about nexB OSS projects.
8+
#
9+
from pathlib import Path
10+
11+
from aboutcode.pipeline import LoopProgress
12+
from fetchcode.vcs import fetch_via_vcs
13+
14+
from vulnerabilities.models import AdvisoryAlias
15+
from vulnerabilities.models import AdvisoryV2
16+
from vulnerabilities.models import DetectionRule
17+
from vulnerabilities.models import DetectionRuleTypes
18+
from vulnerabilities.pipelines import VulnerableCodePipeline
19+
from vulnerabilities.utils import find_all_cve
20+
from vulnerabilities.utils import get_advisory_url
21+
22+
23+
class YaraRulesImproverPipeline(VulnerableCodePipeline):
24+
pipeline_id = "yara_rules"
25+
26+
repo_urls = [
27+
"git+https://github.com/elastic/protections-artifacts",
28+
"git+https://github.com/Yara-Rules/rules",
29+
"git+https://github.com/Xumeiquer/yara-forensics",
30+
"git+https://github.com/reversinglabs/reversinglabs-yara-rules",
31+
"git+https://github.com/advanced-threat-research/Yara-Rules",
32+
"git+https://github.com/bartblaze/Yara-rules",
33+
"git+https://github.com/godaddy/yara-rules", # archived
34+
"git+https://github.com/SupportIntelligence/Icewater",
35+
"git+https://github.com/jeFF0Falltrades/YARA-Signatures",
36+
"git+https://github.com/tjnel/yara_repo",
37+
"git+https://github.com/JPCERTCC/jpcert-yara",
38+
"git+https://github.com/mikesxrs/Open-Source-YARA-rules",
39+
"git+https://github.com/fboldewin/YARA-rules",
40+
"git+https://github.com/h3x2b/yara-rules",
41+
"git+https://github.com/roadwy/DefenderYara",
42+
"git+https://github.com/mthcht/ThreatHunting-Keywords-yara-rules",
43+
"git+https://github.com/Neo23x0/signature-base",
44+
"git+https://github.com/malpedia/signator-rules",
45+
"git+https://github.com/baderj/yara",
46+
"git+https://github.com/deadbits/yara-rules", # archived
47+
"git+https://github.com/pmelson/yara_rules",
48+
"git+https://github.com/sbousseaden/YaraHunts",
49+
"git+https://github.com/embee-research/Yara-detection-rules",
50+
"git+https://github.com/RussianPanda95/Yara-Rules",
51+
"git+https://github.com/ail-project/ail-yara-rules",
52+
"git+https://github.com/MalGamy/YARA_Rules",
53+
"git+https://github.com/elceef/yara-rulz",
54+
"git+https://github.com/tenable/yara-rules",
55+
"git+https://github.com/dr4k0nia/yara-rules",
56+
"git+https://github.com/umair9747/yara-rules",
57+
]
58+
59+
license_urls = """
60+
https://github.com/elastic/protections-artifacts/blob/main/LICENSE.txt
61+
https://github.com/Yara-Rules/rules/blob/master/LICENSE
62+
https://github.com/Xumeiquer/yara-forensics/blob/master/LICENSE
63+
https://github.com/reversinglabs/reversinglabs-yara-rules/blob/develop/LICENSE
64+
https://github.com/advanced-threat-research/Yara-Rules/blob/master/LICENSE
65+
https://github.com/bartblaze/Yara-rules/blob/master/LICENSE
66+
https://github.com/godaddy/yara-rules/blob/master/LICENSE.md
67+
https://github.com/SupportIntelligence/Icewater/blob/master/LICENSE
68+
https://github.com/jeFF0Falltrades/YARA-Signatures/blob/master/LICENSE.md
69+
https://github.com/tjnel/yara_repo/blob/master/LICENSE
70+
https://github.com/JPCERTCC/jpcert-yara/blob/main/LICENSE
71+
https://github.com/mthcht/ThreatHunting-Keywords-yara-rules/blob/main/LICENSE
72+
https://github.com/malpedia/signator-rules -> https://creativecommons.org/licenses/by-sa/4.0/
73+
https://github.com/baderj/yara/blob/main/LICENSE
74+
https://github.com/deadbits/yara-rules/blob/master/UNLICENSE
75+
https://github.com/embee-research/Yara-detection-rules/tree/main?tab=readme-ov-file#detection-rule-license-drl-11
76+
https://github.com/ail-project/ail-yara-rules?tab=AGPL-3.0-1-ov-file
77+
https://github.com/MalGamy/YARA_Rules/blob/main/LICENSE.md
78+
https://github.com/elceef/yara-rulz/tree/main?tab=MIT-1-ov-file
79+
https://github.com/tenable/yara-rules/tree/master?tab=BSD-3-Clause-1-ov-file
80+
https://github.com/dr4k0nia/yara-rules/blob/main/LICENSE.md
81+
https://github.com/umair9747/yara-rules?tab=GPL-3.0-1-ov-file
82+
83+
NO-LICENSE: https://github.com/mikesxrs/Open-Source-YARA-rules/
84+
NO-LICENSE: https://github.com/fboldewin/YARA-rules
85+
NO-LICENSE: https://github.com/h3x2b/yara-rules
86+
NO-LICENSE: https://github.com/roadwy/DefenderYara
87+
NO-LICENSE: https://github.com/pmelson/yara_rules
88+
NO-LICENSE: https://github.com/sbousseaden/YaraHunts
89+
NO-LICENSE: https://github.com/RussianPanda95/Yara-Rules
90+
"""
91+
92+
def __init__(self, *args, **kwargs):
93+
super().__init__(*args, **kwargs)
94+
self.vcs_responses = []
95+
96+
@classmethod
97+
def steps(cls):
98+
return (
99+
cls.clone_repos,
100+
cls.collect_and_store_rules,
101+
cls.clean_downloads,
102+
)
103+
104+
def clone_repos(self):
105+
for repo_url in self.repo_urls:
106+
self.log(f"Cloning `{repo_url}`")
107+
try:
108+
response = fetch_via_vcs(repo_url)
109+
if response:
110+
self.vcs_responses.append((response, repo_url))
111+
except Exception as e:
112+
self.log(f"Failed to clone {repo_url}: {e}")
113+
114+
def collect_and_store_rules(self):
115+
for vcs_response, repo_url in self.vcs_responses:
116+
base_directory = Path(vcs_response.dest_dir)
117+
yara_files = [
118+
p
119+
for p in base_directory.rglob("*")
120+
if p.suffix in (".yar", ".yara") and p.is_file()
121+
]
122+
123+
rules_count = len(yara_files)
124+
self.log(f"Processing {rules_count:,d} rules from {repo_url}")
125+
progress = LoopProgress(total_iterations=rules_count, logger=self.log)
126+
for file_path in progress.iter(yara_files):
127+
if not file_path.exists() or not file_path.is_file():
128+
self.log(
129+
f"Skipping file as it no longer exists or is not a file: {file_path}",
130+
level="warning",
131+
)
132+
continue
133+
134+
raw_text = file_path.read_text(encoding="utf-8", errors="ignore")
135+
if not raw_text:
136+
continue
137+
raw_text = raw_text.replace("\x00", "")
138+
139+
repo_url = repo_url.strip("git+")
140+
rule_url = get_advisory_url(
141+
file=file_path,
142+
base_path=base_directory,
143+
url=f"{repo_url}/blob/master/",
144+
)
145+
146+
cve_ids = find_all_cve(f"{file_path}\n{raw_text}")
147+
148+
advisories = set()
149+
for cve_id in cve_ids:
150+
alias = AdvisoryAlias.objects.filter(alias=cve_id).first()
151+
if alias:
152+
for adv in alias.advisories.all():
153+
advisories.add(adv)
154+
else:
155+
advs = AdvisoryV2.objects.filter(advisory_id=cve_id)
156+
for adv in advs:
157+
advisories.add(adv)
158+
159+
detection_rule, _ = DetectionRule.objects.update_or_create(
160+
rule_type=DetectionRuleTypes.YARA,
161+
source_url=rule_url,
162+
defaults={
163+
"rule_text": raw_text,
164+
},
165+
)
166+
167+
for adv in advisories:
168+
detection_rule.related_advisories.add(adv)
169+
170+
def clean_downloads(self):
171+
for vcs_response, _ in self.vcs_responses:
172+
if vcs_response:
173+
self.log(f"Removing cloned repository: {vcs_response.dest_dir}")
174+
vcs_response.delete()
175+
176+
self.vcs_responses = []
177+
178+
def on_failure(self):
179+
self.clean_downloads()
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# VulnerableCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
7+
# See https://aboutcode.org for more information about nexB OSS projects.
8+
#
9+
10+
from pathlib import Path
11+
from unittest.mock import MagicMock
12+
13+
import pytest
14+
15+
from vulnerabilities.models import DetectionRule
16+
from vulnerabilities.pipelines.v2_improvers.yara_rules import YaraRulesImproverPipeline
17+
18+
BASE_DIR = Path(__file__).resolve().parent
19+
TEST_REPO_DIR = (BASE_DIR / "../../test_data/yara").resolve()
20+
21+
22+
@pytest.mark.django_db
23+
def test_collect_and_store_rules_from_test_repo_dir():
24+
mock_vcs_response = MagicMock()
25+
mock_vcs_response.dest_dir = str(TEST_REPO_DIR)
26+
27+
improver = YaraRulesImproverPipeline()
28+
improver.vcs_responses = [(mock_vcs_response, "https://github.com/mock/repo")]
29+
improver.collect_and_store_rules()
30+
31+
assert DetectionRule.objects.exists()
32+
assert DetectionRule.objects.count() == 4
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
rule Windows_Trojan_Xeno_f92ffb82 {
2+
meta:
3+
author = "Elastic Security"
4+
id = "f92ffb82-b743-4df1-9d6b-2afa3b7bb61f"
5+
fingerprint = "2ae1aebd652afb7da5799f46883205b1f3a5c5b01e975b526640407d9bd0d22c"
6+
creation_date = "2024-10-10"
7+
last_modified = "2024-10-24"
8+
threat_name = "Windows.Trojan.Xeno"
9+
reference_sample = "22dbdbcdd4c8b6899006f9f07e87c19b6a2947eeff8cc89c653309379b388cf4"
10+
severity = 50
11+
arch_context = "x86"
12+
scan_context = "file, memory"
13+
license = "Elastic License v2"
14+
os = "windows"
15+
strings:
16+
$a1 = { 28 00 00 0A 7D 0E 00 00 04 02 7B 0E 00 00 04 28 29 00 00 0A 07 7B 03 00 00 04 02 7B 0E 00 00 04 6F 2A 00 00 0A 3A F2 00 00 00 02 7B 07 00 00 04 02 7B 09 00 00 04 6F 32 00 00 06 6F 2B 00 00 0A }
17+
condition:
18+
all of them
19+
}
20+
21+
rule Windows_Trojan_Xeno_89f9f060 {
22+
meta:
23+
author = "Elastic Security"
24+
id = "89f9f060-afc8-427d-ad36-3672016efdf6"
25+
fingerprint = "ddc5bf8c6d5140cb9ea2fbd9b6f1aaab60f506dcd6161a26961958efa4aa42e1"
26+
creation_date = "2024-10-25"
27+
last_modified = "2024-11-26"
28+
threat_name = "Windows.Trojan.Xeno"
29+
reference_sample = "b74733d68e95220ab0630a68ddf973b0c959fd421628e639c1b91e465ba9299b"
30+
severity = 100
31+
arch_context = "x86"
32+
scan_context = "file, memory"
33+
license = "Elastic License v2"
34+
os = "windows"
35+
strings:
36+
$sc_1 = { 8B 44 24 04 89 C6 FF 56 08 68 00 04 00 00 6A 08 50 FF 16 89 C3 8B 06 89 83 2C 01 00 00 8B 46 04 89 83 30 01 00 00 8B 46 08 89 83 34 01 00 00 8B 46 0C 89 83 38 }
37+
$sc_2 = { 55 48 89 E5 48 83 EC 40 49 89 CC 41 FF 54 24 10 48 89 C1 BA 08 00 00 00 41 B8 00 04 00 00 41 FF 14 24 48 89 C3 49 8B 04 24 48 89 83 90 01 00 00 49 8B 44 24 08 }
38+
$str_1 = "SharpInjector" ascii fullword
39+
$str_2 = "HEAVENSGATE_NON_OPERATIONAL" ascii fullword
40+
$str_3 = "ChromeDecryptor" ascii fullword
41+
$str_4 = "DataExtractionStructs" ascii fullword
42+
$str_5 = "XenoStealer" ascii fullword
43+
condition:
44+
(($sc_1 or $sc_2) and ($str_1 or $str_2)) and (1 of ($str_3, $str_4, $str_5))
45+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
rule Linux_Backdoor_Python_00606bac {
2+
meta:
3+
author = "Elastic Security"
4+
id = "00606bac-83eb-4a58-82d2-e4fd16d30846"
5+
fingerprint = "cce1d0e7395a74c04f15ff95f6de7fd7d5f46ede83322b832df74133912c0b17"
6+
creation_date = "2021-01-12"
7+
last_modified = "2021-09-16"
8+
threat_name = "Linux.Backdoor.Python"
9+
reference_sample = "b3e3728d43535f47a1c15b915c2d29835d9769a9dc69eb1b16e40d5ba1b98460"
10+
severity = 100
11+
arch_context = "x86"
12+
scan_context = "file, memory"
13+
license = "Elastic License v2"
14+
os = "linux"
15+
strings:
16+
$a = { F4 01 83 45 F8 01 8B 45 F8 0F B6 00 84 C0 75 F2 83 45 F8 01 8B }
17+
condition:
18+
all of them
19+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
rule Linux_Exploit_CVE_2022_0847_e831c285 {
2+
meta:
3+
author = "Elastic Security"
4+
id = "e831c285-b2b9-49f3-a87c-3deb806e31e4"
5+
fingerprint = "376b791f9bb5f48d0f41ead4e48b5bcc74cb68002bb7c170760428ace169457e"
6+
creation_date = "2022-03-10"
7+
last_modified = "2022-03-14"
8+
threat_name = "Linux.Exploit.CVE-2022-0847"
9+
reference_sample = "c6b2cef2f2bc04e3ae33e0d368eb39eb5ea38d1bca390df47f7096117c1aecca"
10+
severity = 100
11+
arch_context = "x86"
12+
scan_context = "file, memory"
13+
license = "Elastic License v2"
14+
os = "linux"
15+
strings:
16+
$pp = "prepare_pipe"
17+
$s1 = "splice failed"
18+
$s2 = "short splice"
19+
$s3 = "short write"
20+
$s4 = "hijacking suid binary"
21+
$s5 = "Usage: %s TARGETFILE OFFSET DATA"
22+
$s6 = "Usage: %s SUID"
23+
$bs1 = { B8 00 10 00 00 81 7D EC 00 10 00 00 0F 46 45 EC 89 45 FC 8B 55 FC 48 8B 45 D8 48 83 C0 04 8B 00 48 8D 35 }
24+
$bs2 = { B8 00 10 00 00 81 7D F0 00 10 00 00 0F 46 45 F0 89 45 F8 8B 55 F8 48 8B 45 D8 8B 00 48 }
25+
condition:
26+
($pp and 2 of ($s*)) or (all of ($bs*))
27+
}

0 commit comments

Comments
 (0)