|
11 | 11 | import yaml |
12 | 12 | import re |
13 | 13 | import string |
14 | | -from attackcti import attack_client |
| 14 | +#from attackcti import attack_client |
15 | 15 | from colorama import init |
16 | 16 | from colorama import Fore |
17 | 17 | import collections |
18 | 18 |
|
19 | 19 |
|
| 20 | +# Old Tests cover by pySigma 0.10.6 and simgma-cli 0.7.8 |
| 21 | +# Use sigma check --fail-on-error --fail-on-issues --validation-config tests/sigma_cli_conf.yml rules* |
| 22 | +# |
| 23 | +# def test_duplicate_tags(self): sigma-cli validators duplicate_tag |
| 24 | +# def test_all_of_them_condition(self): sigma-cli validator all_of_them_condition |
| 25 | +# def test_missing_id(self): sigma-cli error & validator identifier_existence identifier_uniqueness |
| 26 | +# def test_duplicate_titles(self): sigma-cli validators duplicate_title |
| 27 | +# def test_unknown_value_modifier(self): sigma-cli error & validator SigmaModifierError |
| 28 | +# def test_confirm_correct_mitre_tags(self): sigma-cli validators attacktag |
| 29 | +# def test_optional_tlp(self): sigma-cli validators tlptag |
| 30 | + |
20 | 31 | class TestRules(unittest.TestCase): |
21 | | - @classmethod |
22 | | - def setUpClass(cls): |
23 | | - print("Calling get_mitre_data()") |
24 | | - # Get Current Data from MITRE ATT&CK® |
25 | | - cls.MITRE_ALL = get_mitre_data() |
26 | | - print("Catched data - starting tests...") |
27 | | - |
28 | | - MITRE_TECHNIQUE_NAMES = [ |
29 | | - "process_injection", |
30 | | - "signed_binary_proxy_execution", |
31 | | - "process_injection", |
32 | | - ] # incomplete list |
33 | | - MITRE_TACTICS = [ |
34 | | - "initial_access", |
35 | | - "execution", |
36 | | - "persistence", |
37 | | - "privilege_escalation", |
38 | | - "defense_evasion", |
39 | | - "credential_access", |
40 | | - "discovery", |
41 | | - "lateral_movement", |
42 | | - "collection", |
43 | | - "exfiltration", |
44 | | - "command_and_control", |
45 | | - "impact", |
46 | | - "launch", |
47 | | - ] |
48 | | - # Don't use trademarks in rules - they require non-ASCII characters to be used on we don't want them in our rules |
| 32 | + # @classmethod |
| 33 | + # def setUpClass(cls): |
| 34 | + # print("Calling get_mitre_data()") |
| 35 | + # # Get Current Data from MITRE ATT&CK® |
| 36 | + # cls.MITRE_ALL = get_mitre_data() |
| 37 | + # print("Catched data - starting tests...") |
| 38 | + |
| 39 | + # MITRE_TECHNIQUE_NAMES = [ |
| 40 | + # "process_injection", |
| 41 | + # "signed_binary_proxy_execution", |
| 42 | + # "process_injection", |
| 43 | + # ] # incomplete list |
| 44 | + # MITRE_TACTICS = [ |
| 45 | + # "initial_access", |
| 46 | + # "execution", |
| 47 | + # "persistence", |
| 48 | + # "privilege_escalation", |
| 49 | + # "defense_evasion", |
| 50 | + # "credential_access", |
| 51 | + # "discovery", |
| 52 | + # "lateral_movement", |
| 53 | + # "collection", |
| 54 | + # "exfiltration", |
| 55 | + # "command_and_control", |
| 56 | + # "impact", |
| 57 | + # "launch", |
| 58 | + # ] |
| 59 | + # # Don't use trademarks in rules - they require non-ASCII characters to be used on we don't want them in our rules |
49 | 60 | TRADE_MARKS = {"MITRE ATT&CK", "ATT&CK"} |
50 | 61 |
|
51 | 62 | path_to_rules = [ |
@@ -137,28 +148,29 @@ def test_optional_tags(self): |
137 | 148 | + "There are rules with incorrect/unknown Tags. (please inform us about new tags that are not yet supported in our tests) and check the correct tags here: https://github.com/SigmaHQ/sigma-specification/blob/main/Tags_specification.md ", |
138 | 149 | ) |
139 | 150 |
|
140 | | - def test_confirm_correct_mitre_tags(self): |
141 | | - files_with_incorrect_mitre_tags = [] |
| 151 | + # sigma-cli validators attacktag |
| 152 | + # def test_confirm_correct_mitre_tags(self): |
| 153 | + # files_with_incorrect_mitre_tags = [] |
142 | 154 |
|
143 | | - for file in self.yield_next_rule_file_path(self.path_to_rules): |
144 | | - tags = self.get_rule_part(file_path=file, part_name="tags") |
145 | | - if tags: |
146 | | - for tag in tags: |
147 | | - if tag.startswith("attack.") and tag not in self.MITRE_ALL: |
148 | | - print( |
149 | | - Fore.RED |
150 | | - + "Rule {} has the following incorrect MITRE tag {}".format( |
151 | | - file, tag |
152 | | - ) |
153 | | - ) |
154 | | - files_with_incorrect_mitre_tags.append(file) |
| 155 | + # for file in self.yield_next_rule_file_path(self.path_to_rules): |
| 156 | + # tags = self.get_rule_part(file_path=file, part_name="tags") |
| 157 | + # if tags: |
| 158 | + # for tag in tags: |
| 159 | + # if tag.startswith("attack.") and tag not in self.MITRE_ALL: |
| 160 | + # print( |
| 161 | + # Fore.RED |
| 162 | + # + "Rule {} has the following incorrect MITRE tag {}".format( |
| 163 | + # file, tag |
| 164 | + # ) |
| 165 | + # ) |
| 166 | + # files_with_incorrect_mitre_tags.append(file) |
155 | 167 |
|
156 | | - self.assertEqual( |
157 | | - files_with_incorrect_mitre_tags, |
158 | | - [], |
159 | | - Fore.RED |
160 | | - + "There are rules with incorrect/unknown MITRE Tags. (please inform us about new tags that are not yet supported in our tests) and check the correct tags here: https://attack.mitre.org/ ", |
161 | | - ) |
| 168 | + # self.assertEqual( |
| 169 | + # files_with_incorrect_mitre_tags, |
| 170 | + # [], |
| 171 | + # Fore.RED |
| 172 | + # + "There are rules with incorrect/unknown MITRE Tags. (please inform us about new tags that are not yet supported in our tests) and check the correct tags here: https://attack.mitre.org/ ", |
| 173 | + # ) |
162 | 174 |
|
163 | 175 | # sigma validators duplicate_tag |
164 | 176 | # def test_duplicate_tags(self): |
@@ -933,37 +945,38 @@ def test_optional_license(self): |
933 | 945 | + "There are rules with malformed 'license' fields. (has to be a string )", |
934 | 946 | ) |
935 | 947 |
|
936 | | - def test_optional_tlp(self): |
937 | | - faulty_rules = [] |
938 | | - valid_tlp = [ |
939 | | - "WHITE", |
940 | | - "GREEN", |
941 | | - "AMBER", |
942 | | - "RED", |
943 | | - ] |
944 | | - for file in self.yield_next_rule_file_path(self.path_to_rules): |
945 | | - tlp_str = self.get_rule_part(file_path=file, part_name="tlp") |
946 | | - if tlp_str: |
947 | | - # it exists but isn't a string |
948 | | - if not isinstance(tlp_str, str): |
949 | | - print( |
950 | | - Fore.YELLOW |
951 | | - + "Rule {} has a 'tlp' field that isn't a string.".format(file) |
952 | | - ) |
953 | | - faulty_rules.append(file) |
954 | | - elif not tlp_str.upper() in valid_tlp: |
955 | | - print( |
956 | | - Fore.YELLOW |
957 | | - + "Rule {} has a 'tlp' field with not valid value.".format(file) |
958 | | - ) |
959 | | - faulty_rules.append(file) |
| 948 | + # sigma-cli validators tlptag |
| 949 | + # def test_optional_tlp(self): |
| 950 | + # faulty_rules = [] |
| 951 | + # valid_tlp = [ |
| 952 | + # "WHITE", |
| 953 | + # "GREEN", |
| 954 | + # "AMBER", |
| 955 | + # "RED", |
| 956 | + # ] |
| 957 | + # for file in self.yield_next_rule_file_path(self.path_to_rules): |
| 958 | + # tlp_str = self.get_rule_part(file_path=file, part_name="tlp") |
| 959 | + # if tlp_str: |
| 960 | + # # it exists but isn't a string |
| 961 | + # if not isinstance(tlp_str, str): |
| 962 | + # print( |
| 963 | + # Fore.YELLOW |
| 964 | + # + "Rule {} has a 'tlp' field that isn't a string.".format(file) |
| 965 | + # ) |
| 966 | + # faulty_rules.append(file) |
| 967 | + # elif not tlp_str.upper() in valid_tlp: |
| 968 | + # print( |
| 969 | + # Fore.YELLOW |
| 970 | + # + "Rule {} has a 'tlp' field with not valid value.".format(file) |
| 971 | + # ) |
| 972 | + # faulty_rules.append(file) |
960 | 973 |
|
961 | | - self.assertEqual( |
962 | | - faulty_rules, |
963 | | - [], |
964 | | - Fore.RED |
965 | | - + "There are rules with malformed optional 'tlp' fields. (https://www.cisa.gov/tlp)", |
966 | | - ) |
| 974 | + # self.assertEqual( |
| 975 | + # faulty_rules, |
| 976 | + # [], |
| 977 | + # Fore.RED |
| 978 | + # + "There are rules with malformed optional 'tlp' fields. (https://www.cisa.gov/tlp)", |
| 979 | + # ) |
967 | 980 |
|
968 | 981 | def test_optional_target(self): |
969 | 982 | faulty_rules = [] |
@@ -1602,7 +1615,7 @@ def test_unused_selection(self): |
1602 | 1615 |
|
1603 | 1616 | # self.assertEqual(faulty_rules, [], Fore.RED + "There are rules with common typos in field names.") |
1604 | 1617 |
|
1605 | | - # Sigma error validator SigmaModifierError |
| 1618 | + # Sigma error SigmaModifierError |
1606 | 1619 | # def test_unknown_value_modifier(self): |
1607 | 1620 | # known_modifiers = [ |
1608 | 1621 | # "contains", |
@@ -1909,74 +1922,74 @@ def check_item_for_bad_escapes(item): |
1909 | 1922 | faulty_rules, [], Fore.RED + "There are rules using illegal re-escapes" |
1910 | 1923 | ) |
1911 | 1924 |
|
1912 | | - |
1913 | | -def get_mitre_data(): |
1914 | | - """ |
1915 | | - Use Tags from CTI subrepo to get consitant data |
1916 | | - """ |
1917 | | - cti_path = "cti/" |
1918 | | - cti_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), cti_path) |
1919 | | - |
1920 | | - # Get ATT&CK information |
1921 | | - lift = attack_client(local_path=cti_path) |
1922 | | - # Techniques |
1923 | | - MITRE_TECHNIQUES = [] |
1924 | | - MITRE_TECHNIQUE_NAMES = [] |
1925 | | - MITRE_PHASE_NAMES = set() |
1926 | | - MITRE_TOOLS = [] |
1927 | | - MITRE_GROUPS = [] |
1928 | | - # Techniques |
1929 | | - enterprise_techniques = lift.get_enterprise_techniques() |
1930 | | - for t in enterprise_techniques: |
1931 | | - MITRE_TECHNIQUE_NAMES.append( |
1932 | | - t["name"].lower().replace(" ", "_").replace("-", "_") |
1933 | | - ) |
1934 | | - for r in t.external_references: |
1935 | | - if "external_id" in r: |
1936 | | - MITRE_TECHNIQUES.append(r["external_id"].lower()) |
1937 | | - if "kill_chain_phases" in t: |
1938 | | - for kc in t["kill_chain_phases"]: |
1939 | | - if "phase_name" in kc: |
1940 | | - MITRE_PHASE_NAMES.add(kc["phase_name"].replace("-", "_")) |
1941 | | - # Tools / Malware |
1942 | | - enterprise_tools = lift.get_enterprise_tools() |
1943 | | - for t in enterprise_tools: |
1944 | | - for r in t.external_references: |
1945 | | - if "external_id" in r: |
1946 | | - MITRE_TOOLS.append(r["external_id"].lower()) |
1947 | | - enterprise_malware = lift.get_enterprise_malware() |
1948 | | - for m in enterprise_malware: |
1949 | | - for r in m.external_references: |
1950 | | - if "external_id" in r: |
1951 | | - MITRE_TOOLS.append(r["external_id"].lower()) |
1952 | | - # Groups |
1953 | | - enterprise_groups = lift.get_enterprise_groups() |
1954 | | - for g in enterprise_groups: |
1955 | | - for r in g.external_references: |
1956 | | - if "external_id" in r: |
1957 | | - MITRE_GROUPS.append(r["external_id"].lower()) |
1958 | | - |
1959 | | - # Debugging |
1960 | | - print( |
1961 | | - "MITRE ATT&CK LIST LENGTHS: %d %d %d %d %d" |
1962 | | - % ( |
1963 | | - len(MITRE_TECHNIQUES), |
1964 | | - len(MITRE_TECHNIQUE_NAMES), |
1965 | | - len(list(MITRE_PHASE_NAMES)), |
1966 | | - len(MITRE_GROUPS), |
1967 | | - len(MITRE_TOOLS), |
1968 | | - ) |
1969 | | - ) |
1970 | | - |
1971 | | - # Combine all IDs to a big tag list |
1972 | | - return [ |
1973 | | - "attack." + item |
1974 | | - for item in MITRE_TECHNIQUES |
1975 | | - + MITRE_TECHNIQUE_NAMES |
1976 | | - + list(MITRE_PHASE_NAMES) |
1977 | | - + MITRE_GROUPS |
1978 | | - + MITRE_TOOLS |
1979 | | - ] |
| 1925 | +# sigma-cli validators attacktag |
| 1926 | +# def get_mitre_data(): |
| 1927 | +# """ |
| 1928 | +# Use Tags from CTI subrepo to get consitant data |
| 1929 | +# """ |
| 1930 | +# cti_path = "cti/" |
| 1931 | +# cti_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), cti_path) |
| 1932 | + |
| 1933 | +# # Get ATT&CK information |
| 1934 | +# lift = attack_client(local_path=cti_path) |
| 1935 | +# # Techniques |
| 1936 | +# MITRE_TECHNIQUES = [] |
| 1937 | +# MITRE_TECHNIQUE_NAMES = [] |
| 1938 | +# MITRE_PHASE_NAMES = set() |
| 1939 | +# MITRE_TOOLS = [] |
| 1940 | +# MITRE_GROUPS = [] |
| 1941 | +# # Techniques |
| 1942 | +# enterprise_techniques = lift.get_enterprise_techniques() |
| 1943 | +# for t in enterprise_techniques: |
| 1944 | +# MITRE_TECHNIQUE_NAMES.append( |
| 1945 | +# t["name"].lower().replace(" ", "_").replace("-", "_") |
| 1946 | +# ) |
| 1947 | +# for r in t.external_references: |
| 1948 | +# if "external_id" in r: |
| 1949 | +# MITRE_TECHNIQUES.append(r["external_id"].lower()) |
| 1950 | +# if "kill_chain_phases" in t: |
| 1951 | +# for kc in t["kill_chain_phases"]: |
| 1952 | +# if "phase_name" in kc: |
| 1953 | +# MITRE_PHASE_NAMES.add(kc["phase_name"].replace("-", "_")) |
| 1954 | +# # Tools / Malware |
| 1955 | +# enterprise_tools = lift.get_enterprise_tools() |
| 1956 | +# for t in enterprise_tools: |
| 1957 | +# for r in t.external_references: |
| 1958 | +# if "external_id" in r: |
| 1959 | +# MITRE_TOOLS.append(r["external_id"].lower()) |
| 1960 | +# enterprise_malware = lift.get_enterprise_malware() |
| 1961 | +# for m in enterprise_malware: |
| 1962 | +# for r in m.external_references: |
| 1963 | +# if "external_id" in r: |
| 1964 | +# MITRE_TOOLS.append(r["external_id"].lower()) |
| 1965 | +# # Groups |
| 1966 | +# enterprise_groups = lift.get_enterprise_groups() |
| 1967 | +# for g in enterprise_groups: |
| 1968 | +# for r in g.external_references: |
| 1969 | +# if "external_id" in r: |
| 1970 | +# MITRE_GROUPS.append(r["external_id"].lower()) |
| 1971 | + |
| 1972 | +# # Debugging |
| 1973 | +# print( |
| 1974 | +# "MITRE ATT&CK LIST LENGTHS: %d %d %d %d %d" |
| 1975 | +# % ( |
| 1976 | +# len(MITRE_TECHNIQUES), |
| 1977 | +# len(MITRE_TECHNIQUE_NAMES), |
| 1978 | +# len(list(MITRE_PHASE_NAMES)), |
| 1979 | +# len(MITRE_GROUPS), |
| 1980 | +# len(MITRE_TOOLS), |
| 1981 | +# ) |
| 1982 | +# ) |
| 1983 | + |
| 1984 | +# # Combine all IDs to a big tag list |
| 1985 | +# return [ |
| 1986 | +# "attack." + item |
| 1987 | +# for item in MITRE_TECHNIQUES |
| 1988 | +# + MITRE_TECHNIQUE_NAMES |
| 1989 | +# + list(MITRE_PHASE_NAMES) |
| 1990 | +# + MITRE_GROUPS |
| 1991 | +# + MITRE_TOOLS |
| 1992 | +# ] |
1980 | 1993 |
|
1981 | 1994 |
|
1982 | 1995 | if __name__ == "__main__": |
|
0 commit comments