def test_checkers(key, subkey, arch, key_attrs, value_attrs, tags_to_apply, triggers_modification, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Test the functionality of `check_all` option is activated/desactivated alone and together with other `check_*` options. Example: <windows_registry check_all="yes">HKEY_SOME_KEY</windows_registry>. Parameters ---------- key: str Root key (HKEY_* constants). subkey: str Path of the key. arch: int Architecture of the key. key_attrs: set Attributes for the key events. value_attrs: set Attributes for the value events. tags_to_apply: set Configuration that will be applied for every case. triggers_modification: boolean True if the given attributes trigger modification events. """ check_apply_test(tags_to_apply, get_configuration['tags']) # Test registry keys. registry_key_cud(key, subkey, wazuh_log_monitor, arch=arch, min_timeout=global_parameters.default_timeout, options=key_attrs, triggers_event_modified=triggers_modification, time_travel=True) # Test registry values. registry_value_cud(key, subkey, wazuh_log_monitor, min_timeout=global_parameters.default_timeout, options=value_attrs, triggers_event_modified=triggers_modification, time_travel=True)
def test_ignore_over_restrict_values(key, subkey, value_name, arch, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Check registry values are ignored according to configuration. Parameters ---------- key : str Root key (HKEY_*) subkey : str path of the registry where the test will be executed. arch : str Architecture of the registry. """ check_apply_test({"ambiguous_ignore_restrict_values"}, get_configuration['tags']) # Test registry keys. registry_value_cud(key, subkey, wazuh_log_monitor, arch=arch, value_list=[value_name], min_timeout=global_parameters.default_timeout, time_travel=True, triggers_event=False)
def test_ambiguous_complex_checks(key, subkey, key_checkers, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Check if the events of every configured key has the proper check attributes. Parameters ---------- key: str Key of the registry (HKEY_* constants). sub_key: str Path of the configured key. key_checkers: set Set of checks that are expected. """ check_apply_test({"complex_checks"}, get_configuration['tags']) # Test registry keys. registry_key_cud(key, subkey, wazuh_log_monitor, min_timeout=global_parameters.default_timeout, options=key_checkers, time_travel=True) # Test registry values. registry_value_cud(key, subkey, wazuh_log_monitor, min_timeout=global_parameters.default_timeout, options=key_checkers, time_travel=True)
def test_tags(key, subkey, arch, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Check the tags functionality by applying some tags an ensuring the events raised for the monitored directory has the expected tags. Parameters ---------- folder : str Directory where the file is being created. name : str Name of the file to be created. content : str, bytes Content to fill the new file. """ defined_tags = get_configuration['metadata']['fim_tags'] def tag_validator(event): assert defined_tags == event['data'][ 'tags'], f'defined_tags are not equal' registry_value_cud( key, subkey, wazuh_log_monitor, arch=arch, time_travel=get_configuration['metadata']['fim_mode'] == 'scheduled', min_timeout=global_parameters.default_timeout, triggers_event=True, validators_after_cud=[tag_validator])
def test_no_diff_regex(key, subkey, arch, value_name, truncated, tags_to_apply, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Check the only files detected are those matching the restrict regex. Parameters ---------- key : str Root key (HKEY_*) subkey : str path of the registry. arch : str Architecture of the registry. value_name : str Name of the value that will be created truncated : bool True if an event must be generated, False otherwise. tags_to_apply : set Run test if match with a configuration identifier, skip otherwise. """ check_apply_test(tags_to_apply, get_configuration['tags']) values = {value_name: "some content"} def report_changes_validator(event): """Validate content_changes attribute exists in the event""" for value in values: folder_str = "{} {}".format( "[x32]" if arch == KEY_WOW64_32KEY else "[x64]", sha1(os.path.join(key, subkey).encode()).hexdigest()) diff_file = os.path.join(WAZUH_PATH, 'queue', 'diff', 'registry', folder_str, sha1(value.encode()).hexdigest()) assert os.path.exists(diff_file), '{diff_file} does not exist' assert event['data'].get( 'content_changes') is not None, 'content_changes is empty' def no_diff_validator(event): """Validate content_changes value is truncated if the file is set to no_diff""" if truncated: assert '<Diff truncated because nodiff option>' in event['data'].get('content_changes'), \ 'content_changes is not truncated' else: assert '<Diff truncated because nodiff option>' not in event['data'].get('content_changes'), \ 'content_changes is truncated' registry_value_cud( key, subkey, wazuh_log_monitor, arch=arch, value_list=values, time_travel=get_configuration['metadata']['fim_mode'] == 'scheduled', min_timeout=global_parameters.default_timeout, triggers_event=True, validators_after_update=[report_changes_validator, no_diff_validator]) # Avoid overlapping of events sleep(0.5)
def test_disk_quota_values(key, subkey, arch, value_name, tags_to_apply, size, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Check that no events are sent when the disk_quota exceeded Parameters ---------- key : str Root key (HKEY_*) subkey : str path of the registry. arch : str Architecture of the registry. value_name : str Name of the value that will be created tags_to_apply : set Run test if match with a configuration identifier, skip otherwise. size : int Size of the content to write in value """ check_apply_test(tags_to_apply, get_configuration['tags']) value_content = generate_string(size, '0') values = {value_name: value_content} _, diff_file = calculate_registry_diff_paths(key, subkey, arch, value_name) def report_changes_validator_no_diff(event): """Validate content_changes attribute exists in the event""" assert event['data'].get( 'content_changes') is None, 'content_changes isn\'t empty' def report_changes_validator_diff(event): """Validate content_changes attribute exists in the event""" assert os.path.exists(diff_file), '{diff_file} does not exist' assert event['data'].get( 'content_changes') is not None, 'content_changes is empty' if size > size_limit_configured: callback_test = report_changes_validator_no_diff else: callback_test = report_changes_validator_diff create_registry(registry_parser[key], subkey, arch) registry_value_cud( key, subkey, wazuh_log_monitor, arch=arch, value_list=values, time_travel=get_configuration['metadata']['fim_mode'] == 'scheduled', min_timeout=global_parameters.default_timeout, triggers_event=True, validators_after_update=[callback_test]) delete_registry(registry_parser[key], subkey, arch) check_time_travel(True, monitor=wazuh_log_monitor)
def test_ambiguous_report_tags(key, subkey, tag, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Check if syscheck detects the event property 'tags' for each configured entry. This test validates both situations, making sure that if tags='no', there won't be a tags event property. Parameters ---------- key: str Key of the registry (HKEY_* constants). sub_key: str Path of the configured key. tag: str Tag that is configured for each entry. If None, the entry isn't configured with a tag. """ check_apply_test({'complex_tags'}, get_configuration['tags']) def no_tag_validator(event): """Validate tags event property does not exist in the event.""" assert 'tags' not in event['data'].keys( ), "'Tags' attribute found in event" def tag_validator(event): """Validate tags event property exists in the event.""" assert tag == event['data']['tags'], 'Defined_tags are not equal' validator_after_create = [no_tag_validator] validator_after_update = [no_tag_validator] validator_after_delete = [no_tag_validator] if tag is not None: validator_after_create = [tag_validator] validator_after_update = [tag_validator] validator_after_delete = [tag_validator] # Test registry values. registry_key_cud(key, subkey, wazuh_log_monitor, min_timeout=global_parameters.default_timeout, time_travel=True, validators_after_create=validator_after_create, validators_after_update=validator_after_update, validators_after_delete=validator_after_delete) # Test registry values. registry_value_cud(key, subkey, wazuh_log_monitor, min_timeout=global_parameters.default_timeout, time_travel=True, validators_after_create=validator_after_create, validators_after_update=validator_after_update, validators_after_delete=validator_after_delete)
def test_ambiguous_restrict(key, sub_keys, is_key, name, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Check restrict configuration events. Check if syscheck detects changes (add, modify, delete) of key/events depending on its restrict configuration. Parameters ---------- key: str Key of the registry (HKEY_* constants). sub_keys: tuple Tuple where the first element is the path of a key that won't raise alerts due to the restrict and the second element is a key that will raise alerts. is_key: boolean Variable to distinguish if the restrict is for keys or for values. name: str String with the name of the value/key that will be created. """ check_apply_test({"ambiguous_restrict"}, get_configuration['tags']) if is_key: registry_key_cud(key, sub_keys[0], wazuh_log_monitor, key_list=[name], arch=KEY_WOW64_64KEY, triggers_event=False, time_travel=True, min_timeout=global_parameters.default_timeout) registry_key_cud(key, sub_keys[1], wazuh_log_monitor, key_list=[name], arch=KEY_WOW64_64KEY, triggers_event=True, time_travel=True, min_timeout=global_parameters.default_timeout) else: registry_value_cud(key, sub_keys[0], wazuh_log_monitor, value_list=[name], arch=KEY_WOW64_64KEY, triggers_event=False, time_travel=True, min_timeout=global_parameters.default_timeout) registry_value_cud(key, sub_keys[1], wazuh_log_monitor, value_list=[name], triggers_event=True, time_travel=True, min_timeout=global_parameters.default_timeout)
def test_ambiguous_checks(key, subkey, key_checkers, subkey_checkers, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Check if syscheck detects the event property 'tags' for each event. This test validates both situations, making sure that if tags='no', there won't be a tags event property. Parameters ---------- key: str Key of the registry (HKEY_* constants). sub_keys: tuple Tuple where ther first element is the configured key and the second is the configured subkey. arch: int Architecture of the key. """ check_apply_test({"ambiguous_checks"}, get_configuration['tags']) # Test registry keys. registry_key_cud( key, subkey[0], wazuh_log_monitor, min_timeout=global_parameters.default_timeout, options=key_checkers, time_travel=get_configuration['metadata']['fim_mode'] == 'scheduled') # Test registry values. registry_value_cud( key, subkey[0], wazuh_log_monitor, min_timeout=global_parameters.default_timeout, options=key_checkers, time_travel=get_configuration['metadata']['fim_mode'] == 'scheduled') # Test registry keys. registry_key_cud( key, subkey[1], wazuh_log_monitor, min_timeout=global_parameters.default_timeout, options=subkey_checkers, time_travel=get_configuration['metadata']['fim_mode'] == 'scheduled') # Test registry values. registry_value_cud( key, subkey[1], wazuh_log_monitor, min_timeout=global_parameters.default_timeout, options=subkey_checkers, time_travel=get_configuration['metadata']['fim_mode'] == 'scheduled')
def test_long_registry_path(get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Check if long key names generates events """ max_value_name = "value_test" for i in range(16372): max_value_name += "a" registry_value_cud(key, sub_key_1, wazuh_log_monitor, arch=arch, time_travel=get_configuration['metadata']['fim_mode'] == 'scheduled', min_timeout=global_parameters.default_timeout, triggers_event=True, value_list=[max_value_name])
def test_registry_changes(key, subkey, arch, value_type, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Check if events appear for subkeys/values of a monitored key """ registry_key_cud(key, subkey, wazuh_log_monitor, arch=arch, time_travel=get_configuration['metadata']['fim_mode'] == 'scheduled', min_timeout=global_parameters.default_timeout, triggers_event=True) registry_value_cud(key, subkey, wazuh_log_monitor, arch=arch, time_travel=get_configuration['metadata']['fim_mode'] == 'scheduled', min_timeout=global_parameters.default_timeout, triggers_event=True, value_type=value_type)
def test_ambiguous_recursion(key, subkey, arch, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Check if syscheck detects the event property 'tags' for each event. This test validates both situations, making sure that if tags='no', there won't be a tags event property. Parameters ---------- key: str Key of the registry (HKEY_* constants). sub_keys: str Path of the subkey that will be used for the test (must have a higher recursion level than the configured key). Example: <windows_registry recursion_level="2">HKLM//some_key</windows_registry> subkey = HKLM//some_key//1//2//3 arch: int Architecture of the key. """ expected_recursion_key = os.path.join(subkey, key_name) check_apply_test({"ambiguous_recursion"}, get_configuration['tags']) registry_key_cud(key, subkey, wazuh_log_monitor, arch=arch, time_travel=True, triggers_event=False, min_timeout=global_parameters.default_timeout) registry_key_cud(key, expected_recursion_key, wazuh_log_monitor, arch=arch, time_travel=True, triggers_event=True, min_timeout=global_parameters.default_timeout) registry_value_cud(key, expected_recursion_key, wazuh_log_monitor, arch=arch, time_travel=True, triggers_event=True, min_timeout=global_parameters.default_timeout)
def test_duplicate_entries_rc(key, subkey, arch, value_list, tags_to_apply, report_changes, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Check registry entries are overwritten when report changes is activated/deactivated. Parameters ---------- key: str Root key (HKEY_* constants). subkey: str path of the registry where the test will be executed. arch: str Architecture of the registry. value_list: list List with the name of the values that will be used for cud. """ check_apply_test(tags_to_apply, get_configuration['tags']) def report_changes_validator(event): """Validate content_changes attribute exists in the event""" if not report_changes: return for value in value_list: folder_str = "{} {}".format( "[x32]" if arch == KEY_WOW64_32KEY else "[x64]", sha1(os.path.join(key, subkey).encode()).hexdigest()) diff_file = os.path.join(WAZUH_PATH, 'queue', 'diff', 'registry', folder_str, sha1(value.encode()).hexdigest()) assert os.path.exists(diff_file), '{diff_file} does not exist' assert event['data'].get( 'content_changes') is not None, 'content_changes is empty' registry_value_cud(key, subkey, wazuh_log_monitor, arch=arch, value_list=value_list, time_travel=True, min_timeout=global_parameters.default_timeout, triggers_event=True, validators_after_update=[report_changes_validator])
def test_duplicate_entries(key, subkey, arch, key_list, value_list, checkers, tags_to_apply, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Check that duplicate antries are overwritten by the last entry. Parameters ---------- key: str Root key (HKEY_*) subkey: str path of the registry where the test will be executed. arch: str Architecture of the registry. key_list: list List with the name of the keys that will be used for cud. If None, registry_key_cud won't be executed. value_list: list List with the name of the values that will be used for cud. If None, registry_value_cud won't be executed. checkers: set Set with the checkers that are expected in the events. """ check_apply_test(tags_to_apply, get_configuration['tags']) # Test registry keys. if key_list is not None: registry_key_cud(key, subkey, wazuh_log_monitor, arch=arch, key_list=key_list, options=checkers, min_timeout=global_parameters.default_timeout, time_travel=True, triggers_event=True) if value_list is not None: registry_value_cud(key, subkey, wazuh_log_monitor, arch=arch, value_list=value_list, options=checkers, min_timeout=global_parameters.default_timeout, time_travel=True, triggers_event=True)
def test_ambiguous_report_changes(key, subkey, value_list, report, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Check if report changes works properly for every configured entry Parameters ---------- key: str Key of the registry (HKEY_* constants). sub_key: str Path of the configured key. value_list: list List with the name of the values that will be used in the cud operation. report: boolean True if the key is configured with report changes. """ check_apply_test({'complex_report_changes'}, get_configuration['tags']) validator_after_update = None def report_changes_validator(event): """Validate content_changes attribute exists in the event""" for value in value_list: folder_str = "{} {}".format( "[x64]", sha1(os.path.join(key, subkey).encode()).hexdigest()) diff_file = os.path.join(WAZUH_PATH, 'queue', 'diff', 'registry', folder_str, sha1(value.encode()).hexdigest()) assert os.path.exists(diff_file), '{diff_file} does not exist' assert event['data'].get( 'content_changes') is not None, 'content_changes is empty' if report: validator_after_update = [report_changes_validator] # Test registry values. registry_value_cud(key, subkey, wazuh_log_monitor, min_timeout=global_parameters.default_timeout, value_list=value_list, time_travel=True, validators_after_update=validator_after_update)
def test_new_key(get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Check that a new monitored key generates events after the next scheduled scan. """ create_registry(registry_parser[key], sub_key_1, arch) check_time_travel(True, monitor=wazuh_log_monitor) registry_value_cud( key, sub_key_1, wazuh_log_monitor, arch=arch, time_travel=get_configuration['metadata']['fim_mode'] == 'scheduled', min_timeout=global_parameters.default_timeout, triggers_event=True)
def test_report_changes_more_changes(key, subkey, arch, value_name, tags_to_apply, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Checks that "More changes..." diff string is MAX_STR_MORE_CHANGES Parameters ---------- key : str Root key (HKEY_*) subkey : str path of the registry. arch : str Architecture of the registry. value_name : str Name of the value that will be created tags_to_apply : set Run test if match with a configuration identifier, skip otherwise. """ check_apply_test(tags_to_apply, get_configuration['tags']) values = {value_name: generate_string(MAX_STR_MORE_CHANGES, '0')} error_str = 'Expected {} in event'.format(MORE_CHANGES_STR) def report_changes_validator(event): """Validate content_changes attribute exists in the event""" for value in values: _, diff_file = calculate_registry_diff_paths( key, subkey, arch, value) assert os.path.exists(diff_file), '{diff_file} does not exist' assert event['data'].get('content_changes')[ -len(MORE_CHANGES_STR):] == MORE_CHANGES_STR, error_str registry_value_cud( key, subkey, wazuh_log_monitor, arch=arch, value_list=values, time_travel=get_configuration['metadata']['fim_mode'] == 'scheduled', min_timeout=global_parameters.default_timeout, triggers_event=True, validators_after_update=[report_changes_validator])
def test_report_changes(key, subkey, arch, value_name, tags_to_apply, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Checks that events of keys configured using report changes are correct. It also checks that the diff file is created for each value. Parameters ---------- key : str Root key (HKEY_*) subkey : str path of the registry. arch : str Architecture of the registry. value_name : str Name of the value that will be created tags_to_apply : set Run test if match with a configuration identifier, skip otherwise. """ check_apply_test(tags_to_apply, get_configuration['tags']) values = {value_name: "some content"} def report_changes_validator(event): """Validate content_changes attribute exists in the event""" for value in values: _, diff_file = calculate_registry_diff_paths( key, subkey, arch, value) assert os.path.exists(diff_file), '{diff_file} does not exist' assert event['data'].get( 'content_changes') is not None, 'content_changes is empty' registry_value_cud( key, subkey, wazuh_log_monitor, arch=arch, value_list=values, time_travel=get_configuration['metadata']['fim_mode'] == 'scheduled', min_timeout=global_parameters.default_timeout, triggers_event=True, validators_after_update=[report_changes_validator])
def test_report_when_deleted_key(key, subkey, arch, value_name, enabled, tags_to_apply, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Check that the diff files are generated when there is a modification in a value and these files are deleted when the value is deleted. It also checks that the diff folder of the key is deleted when the key is deleted. Parameters ---------- key : str Root key (HKEY_*) subkey : str path of the registry. arch : str Architecture of the registry. value_name : str Name of the value that will be created enabled: boolean True if report_changes is enabled tags_to_apply : set Run test if match with a configuration identifier, skip otherwise. """ check_apply_test(tags_to_apply, get_configuration['tags']) vals_after_update = None vals_after_delete = None folder_path, diff_file = calculate_registry_diff_paths( key, subkey, arch, value_name) def report_changes_diff_file_validator(unused_param): """ Validator that checks if the files are created. """ assert os.path.exists(diff_file), f'{diff_file} does not exist' def report_changes_removed_diff_file_validator(unused_param): """ Validator that checks if the files are removed when the values are removed. """ assert not os.path.exists(diff_file), f'{diff_file} does exist' if enabled: vals_after_update = [report_changes_diff_file_validator] vals_after_delete = [report_changes_removed_diff_file_validator] else: vals_after_update = [report_changes_removed_diff_file_validator] vals_after_delete = [report_changes_removed_diff_file_validator] registry_value_cud(key, subkey, wazuh_log_monitor, arch=arch, value_list={value_name: "some content"}, time_travel=True, min_timeout=global_parameters.default_timeout, validators_after_update=vals_after_update, validators_after_delete=vals_after_delete) delete_registry(registry_parser[key], subkey, arch) assert not os.path.exists(folder_path), f'{folder_path} exists'
def test_recursion_level(root_key, registry, arch, edge_limit, ignored_levels, get_configuration, configure_environment, restart_syscheckd, wait_for_fim_start): """ Check that events are generated in the first and last `edge_limit` directory levels in the hierarchy It also checks that no events are generated for levels higher than the configured recursion level. Example: recursion_level = 10 edge_limit = 2 ignored_levels = 1 key = "HKEY_LOCAL_MACHINE" registry = "SOFTWARE\\test_key" subkey = "subkey" With those parameters this function will create values and expect to detect 'added', 'modified' and 'deleted' events for the following registry only, as they are the first and last 2 subkeys within recursion level 10: HKEY_LOCAL_MACHINE\\SOFTWARE\\test_key\\1 HKEY_LOCAL_MACHINE\\SOFTWARE\\test_key\\1\\2 HKEY_LOCAL_MACHINE\\SOFTWARE\\test_key\\1\\2\\3\\4\\5\\6\\7\\8\\9 HKEY_LOCAL_MACHINE\\SOFTWARE\\test_key\\1\\2\\3\\4\\5\\6\\7\\8\\9\\10 As ignored_levels value is 1, this function will also create files on the following subkeys and ensure that no events are raised as they are outside the recursion level specified: HKEY_LOCAL_MACHINE\\SOFTWARE\\test_key\\1\\2\\3\\4\\5\\6\\7\\8\\9\\10\\11 Parameters ---------- root_key : str Registry key **STRING** (HKEY_* constants) registry : str The registry key being monitored by syscheck (indicated in the .conf file without the HKEY_* constant). arch : int Architecture of the registry key edge_limit : int Number of subkeys where the test will monitor events. ignored_levels : int Number of subkeys exceeding the specified recursion_level to verify events are not raised. """ recursion_level = int(rl_dict[registry]) path = registry # Check events in recursion level = 0 registry_value_cud(root_key, path, wazuh_log_monitor, arch=arch, time_travel=True, min_timeout=global_parameters.default_timeout) path_list = list() # For recursion lower levels, execute registry_value_cud in every level. if recursion_level < edge_limit: for level in range(recursion_level): path = os.path.join(path, str(level + 1)) path_list.append(path) else: for level in range(recursion_level): path = os.path.join(path, str(level + 1)) if level < edge_limit or level > recursion_level - edge_limit: path_list.append(path) # Create values only in the first/last `edge_limit` levels of recursion for registry_path in path_list: registry_value_cud(root_key, registry_path, wazuh_log_monitor, arch=arch, time_travel=True, min_timeout=global_parameters.default_timeout, triggers_event=True) # Check that no alerts are generated when levels that exceed the specified recursion_level for n in range(recursion_level, recursion_level + ignored_levels): path = os.path.join(path, str(n + 1)) registry_value_cud(root_key, path, wazuh_log_monitor, arch=arch, time_travel=True, min_timeout=global_parameters.default_timeout, triggers_event=False)