From 536ad78fc2009c1c1789ea2098ab593560e9f4f1 Mon Sep 17 00:00:00 2001 From: Florian Roth Date: Tue, 31 Mar 2020 11:30:14 +0200 Subject: [PATCH 01/94] refactor: following best practices reg main functions in Python https://realpython.com/python-main-function/ --- tools/merge_sigma | 28 ++-- tools/sigma-similarity | 82 ++++++------ tools/sigma-uuid | 128 +++++++++--------- tools/sigma2misp | 72 +++++----- tools/sigmac | 298 +++++++++++++++++++++-------------------- 5 files changed, 314 insertions(+), 294 deletions(-) diff --git a/tools/merge_sigma b/tools/merge_sigma index e043a35c..1a266913 100755 --- a/tools/merge_sigma +++ b/tools/merge_sigma @@ -21,18 +21,22 @@ import yaml from sigma.parser.collection import SigmaCollectionParser -argparser = argparse.ArgumentParser(description="Convert Sigma rules into SIEM signatures.") -argparser.add_argument("input", help="Sigma input file") -cmdargs = argparser.parse_args() +def main(): + argparser = argparse.ArgumentParser(description="Convert Sigma rules into SIEM signatures.") + argparser.add_argument("input", help="Sigma input file") + cmdargs = argparser.parse_args() -try: - f = open(cmdargs.input, "r") -except IOError as e: - print("Error while opening input file: %s" % str(e), file=sys.stderr) - sys.exit(1) + try: + f = open(cmdargs.input, "r") + except IOError as e: + print("Error while opening input file: %s" % str(e), file=sys.stderr) + sys.exit(1) -content = "".join(f.readlines()) -f.close() -sc = SigmaCollectionParser(content) + content = "".join(f.readlines()) + f.close() + sc = SigmaCollectionParser(content) -print(yaml.dump_all(sc, default_flow_style=False)) + print(yaml.dump_all(sc, default_flow_style=False)) + +if __name__ == "__main__": + main() diff --git a/tools/sigma-similarity b/tools/sigma-similarity index de5022c3..38a74d8a 100755 --- a/tools/sigma-similarity +++ b/tools/sigma-similarity @@ -56,46 +56,50 @@ class SigmaNormalizationBackend(SingleTextQueryBackend): else: return " | {}({}) by {} {} {}".format(agg.aggfunc_notrans, agg.aggfield, agg.groupfield, agg.cond_op, agg.condition) -backend = SigmaNormalizationBackend(SigmaConfiguration()) +def main(): + backend = SigmaNormalizationBackend(SigmaConfiguration()) -if args.recursive: - paths = [ p for pathname in args.inputs for p in pathlib.Path(pathname).glob("**/*") if p.is_file() ] -else: - paths = [ pathlib.Path(pathname) for pathname in args.inputs ] + if args.recursive: + paths = [ p for pathname in args.inputs for p in pathlib.Path(pathname).glob("**/*") if p.is_file() ] + else: + paths = [ pathlib.Path(pathname) for pathname in args.inputs ] -primary_paths = None -if args.primary: - with open(args.primary, "r") as f: - primary_paths = { pathname.strip() for pathname in f.readlines() } + primary_paths = None + if args.primary: + with open(args.primary, "r") as f: + primary_paths = { pathname.strip() for pathname in f.readlines() } -parsed = { - str(path): SigmaCollectionParser(path.open().read()) - for path in paths - } -converted = { - str(path): list(sigma_collection.generate(backend)) - for path, sigma_collection in parsed.items() - } -converted_flat = ( - (path, i, normalized) - for path, nlist in converted.items() - for i, normalized in zip(range(len(nlist)), nlist) - ) -converted_pairs_iter = itertools.combinations(converted_flat, 2) -if primary_paths: - converted_pairs = [ pair for pair in converted_pairs_iter if pair[0][0] in primary_paths or pair[1][0] in paths ] -else: - converted_pairs = list(converted_pairs_iter) -similarities = [ - (item1[:2], item2[:2], difflib.SequenceMatcher(None, item1[2], item2[2]).ratio()) - for item1, item2 in progressbar.progressbar(converted_pairs) - ] + parsed = { + str(path): SigmaCollectionParser(path.open().read()) + for path in paths + } + converted = { + str(path): list(sigma_collection.generate(backend)) + for path, sigma_collection in parsed.items() + } + converted_flat = ( + (path, i, normalized) + for path, nlist in converted.items() + for i, normalized in zip(range(len(nlist)), nlist) + ) + converted_pairs_iter = itertools.combinations(converted_flat, 2) + if primary_paths: + converted_pairs = [ pair for pair in converted_pairs_iter if pair[0][0] in primary_paths or pair[1][0] in paths ] + else: + converted_pairs = list(converted_pairs_iter) + similarities = [ + (item1[:2], item2[:2], difflib.SequenceMatcher(None, item1[2], item2[2]).ratio()) + for item1, item2 in progressbar.progressbar(converted_pairs) + ] -i = 0 -for similarity in sorted(similarities, key=lambda s: s[2], reverse=True): - if args.min_similarity and similarity[2] * 100 < args.min_similarity: # finish after similarity drops below minimum - break - print("{:70} | {:2} | {:70} | {:2} | {:>3.2%}".format(*similarity[0], *similarity[1], similarity[2])) - i += 1 - if args.top and i >= args.top: # end after $top pairs - break + i = 0 + for similarity in sorted(similarities, key=lambda s: s[2], reverse=True): + if args.min_similarity and similarity[2] * 100 < args.min_similarity: # finish after similarity drops below minimum + break + print("{:70} | {:2} | {:70} | {:2} | {:>3.2%}".format(*similarity[0], *similarity[1], similarity[2])) + i += 1 + if args.top and i >= args.top: # end after $top pairs + break + +if __name__ == "__main__": + main() diff --git a/tools/sigma-uuid b/tools/sigma-uuid index 85a9ab61..0fb58329 100755 --- a/tools/sigma-uuid +++ b/tools/sigma-uuid @@ -7,19 +7,6 @@ from uuid import uuid4, UUID import yaml from sigma.output import SigmaYAMLDumper -argparser = ArgumentParser(description="Assign and verfify UUIDs of Sigma rules") -argparser.add_argument("--verify", "-V", action="store_true", help="Verify existence and uniqueness of UUID assignments. Exits with error code if verification fails.") -argparser.add_argument("--verbose", "-v", action="store_true", help="Be verbose.") -argparser.add_argument("--recursive", "-r", action="store_true", help="Recurse into directories.") -argparser.add_argument("--error", "-e", action="store_true", help="Exit with error code 10 on verification failures.") -argparser.add_argument("inputs", nargs="+", help="Sigma rule files or repository directories") -args = argparser.parse_args() - -if args.recursive: - paths = [ p for pathname in args.inputs for p in Path(pathname).glob("**/*") if p.is_file() ] -else: - paths = [ Path(pathname) for pathname in args.inputs ] - def print_verbose(*arg, **kwarg): if args.verbose: print(*arg, **kwarg) @@ -28,56 +15,73 @@ def print_verbose(*arg, **kwarg): def yaml_preserve_order(self, dict_data): return self.represent_mapping("tag:yaml.org,2002:map", dict_data.items()) -yaml.add_representer(dict, yaml_preserve_order) +def main(): + argparser = ArgumentParser(description="Assign and verfify UUIDs of Sigma rules") + argparser.add_argument("--verify", "-V", action="store_true", help="Verify existence and uniqueness of UUID assignments. Exits with error code if verification fails.") + argparser.add_argument("--verbose", "-v", action="store_true", help="Be verbose.") + argparser.add_argument("--recursive", "-r", action="store_true", help="Recurse into directories.") + argparser.add_argument("--error", "-e", action="store_true", help="Exit with error code 10 on verification failures.") + argparser.add_argument("inputs", nargs="+", help="Sigma rule files or repository directories") + args = argparser.parse_args() -uuids = set() -passed = True -for path in paths: - print_verbose("Rule {}".format(str(path))) - with path.open("r") as f: - rules = list(yaml.safe_load_all(f)) - - if args.verify: - i = 1 - for rule in rules: - if "title" in rule: # Rule with a title should also have a UUID - try: - UUID(rule["id"]) - except ValueError: # id is not a valid UUID - print("Rule {} in file {} has a malformed UUID '{}'.".format(i, str(path), rule["id"])) - passed = False - except KeyError: # rule has no id - print("Rule {} in file {} has no UUID.".format(i, str(path))) - passed = False - i += 1 + if args.recursive: + paths = [ p for pathname in args.inputs for p in Path(pathname).glob("**/*") if p.is_file() ] else: - newrules = list() - changed = False - i = 1 - for rule in rules: - if "title" in rule and "id" not in rule: # only assign id to rules that have a title and no id - newrule = dict() - changed = True - for k, v in rule.items(): - newrule[k] = v - if k == "title": # insert id after title - uuid = uuid4() - newrule["id"] = str(uuid) - print("Assigned UUID '{}' to rule {} in file {}.".format(uuid, i, str(path))) - newrules.append(newrule) - else: - newrules.append(rule) - i += 1 + paths = [ Path(pathname) for pathname in args.inputs ] - if changed: - with path.open("w") as f: - yaml.dump_all(newrules, f, Dumper=SigmaYAMLDumper, indent=4, width=160, default_flow_style=False) + yaml.add_representer(dict, yaml_preserve_order) -if not passed: - print("The Sigma rules listed above don't have an ID. The ID must be:") - print("* Contained in the 'id' attribute") - print("* a valid UUIDv4 (randomly generated)") - print("* Unique in this repository") - print("Please generate one with the sigma-uuid tool or here: https://www.uuidgenerator.net/version4") - if args.error: - exit(10) + uuids = set() + passed = True + for path in paths: + print_verbose("Rule {}".format(str(path))) + with path.open("r") as f: + rules = list(yaml.safe_load_all(f)) + + if args.verify: + i = 1 + for rule in rules: + if "title" in rule: # Rule with a title should also have a UUID + try: + UUID(rule["id"]) + except ValueError: # id is not a valid UUID + print("Rule {} in file {} has a malformed UUID '{}'.".format(i, str(path), rule["id"])) + passed = False + except KeyError: # rule has no id + print("Rule {} in file {} has no UUID.".format(i, str(path))) + passed = False + i += 1 + else: + newrules = list() + changed = False + i = 1 + for rule in rules: + if "title" in rule and "id" not in rule: # only assign id to rules that have a title and no id + newrule = dict() + changed = True + for k, v in rule.items(): + newrule[k] = v + if k == "title": # insert id after title + uuid = uuid4() + newrule["id"] = str(uuid) + print("Assigned UUID '{}' to rule {} in file {}.".format(uuid, i, str(path))) + newrules.append(newrule) + else: + newrules.append(rule) + i += 1 + + if changed: + with path.open("w") as f: + yaml.dump_all(newrules, f, Dumper=SigmaYAMLDumper, indent=4, width=160, default_flow_style=False) + + if not passed: + print("The Sigma rules listed above don't have an ID. The ID must be:") + print("* Contained in the 'id' attribute") + print("* a valid UUIDv4 (randomly generated)") + print("* Unique in this repository") + print("Please generate one with the sigma-uuid tool or here: https://www.uuidgenerator.net/version4") + if args.error: + exit(10) + +if __name__ == "__main__": + main() diff --git a/tools/sigma2misp b/tools/sigma2misp index 5229c338..8d604cba 100755 --- a/tools/sigma2misp +++ b/tools/sigma2misp @@ -27,43 +27,47 @@ class MISPImportArgumentParser(argparse.ArgumentParser): def convert_arg_line_to_args(self, line : str): return ("--" + line.lstrip("--")).split() -argparser = MISPImportArgumentParser() -argparser.add_argument("--url", "-u", default="https://localhost", help="URL of MISP instance") -argparser.add_argument("--key", "-k", required=True, help="API key") -argparser.add_argument("--insecure", "-I", action="store_false", help="Disable TLS certifcate validation.") -argparser.add_argument("--event", "-e", type=int, help="Add Sigma rule to event with this ID. If not set, create new event.") -argparser.add_argument("--same-event", "-s", action="store_true", help="Import all Sigma rules to the same event, if no event is set.") -argparser.add_argument("--info", "-i", default="Sigma import", help="Event Information field for newly created MISP event.") -argparser.add_argument("--recursive", "-r", action="store_true", help="Recursive traversal of directory") -argparser.add_argument("sigma", nargs="+", help="Sigma rule file that should be imported") -args = argparser.parse_args() +def main(): + argparser = MISPImportArgumentParser() + argparser.add_argument("--url", "-u", default="https://localhost", help="URL of MISP instance") + argparser.add_argument("--key", "-k", required=True, help="API key") + argparser.add_argument("--insecure", "-I", action="store_false", help="Disable TLS certifcate validation.") + argparser.add_argument("--event", "-e", type=int, help="Add Sigma rule to event with this ID. If not set, create new event.") + argparser.add_argument("--same-event", "-s", action="store_true", help="Import all Sigma rules to the same event, if no event is set.") + argparser.add_argument("--info", "-i", default="Sigma import", help="Event Information field for newly created MISP event.") + argparser.add_argument("--recursive", "-r", action="store_true", help="Recursive traversal of directory") + argparser.add_argument("sigma", nargs="+", help="Sigma rule file that should be imported") + args = argparser.parse_args() -if args.recursive: - paths = [ p for pathname in args.sigma for p in pathlib.Path(pathname).glob("**/*") if p.is_file() ] -else: - paths = [ pathlib.Path(sigma) for sigma in args.sigma ] - -misp = PyMISP(args.url, args.key, args.insecure) -if args.event: - if hasattr(misp, "get"): - eventid = misp.get(args.event)["Event"]["id"] + if args.recursive: + paths = [ p for pathname in args.sigma for p in pathlib.Path(pathname).glob("**/*") if p.is_file() ] else: - eventid = misp.get_event(args.event)["Event"]["id"] + paths = [ pathlib.Path(sigma) for sigma in args.sigma ] -first = True + misp = PyMISP(args.url, args.key, args.insecure) + if args.event: + if hasattr(misp, "get"): + eventid = misp.get(args.event)["Event"]["id"] + else: + eventid = misp.get_event(args.event)["Event"]["id"] -for sigma in paths: - if not args.event and (first or not args.same_event): - eventid = create_new_event() - print("Importing Sigma rule {} into MISP event {}...".format(sigma, eventid, end="")) - f = sigma.open("rt") + first = True - if hasattr(misp, "add_named_attribute"): - misp.add_named_attribute(eventid, "sigma", f.read()) - else: - event = misp.get_event(eventid, pythonify=True) - event.add_attribute("sigma", f.read()) - misp.update_event(event) + for sigma in paths: + if not args.event and (first or not args.same_event): + eventid = create_new_event() + print("Importing Sigma rule {} into MISP event {}...".format(sigma, eventid, end="")) + f = sigma.open("rt") - f.close() - first = False + if hasattr(misp, "add_named_attribute"): + misp.add_named_attribute(eventid, "sigma", f.read()) + else: + event = misp.get_event(eventid, pythonify=True) + event.add_attribute("sigma", f.read()) + misp.update_event(event) + + f.close() + first = False + +if __name__ == "__main__": + main() diff --git a/tools/sigmac b/tools/sigmac index 89129e7b..e1aff610 100755 --- a/tools/sigmac +++ b/tools/sigmac @@ -115,15 +115,6 @@ def set_argparser(): return argparser -argparser = set_argparser() -cmdargs = argparser.parse_args() - -scm = SigmaConfigurationManager() - -logger = logging.getLogger(__name__) -if cmdargs.debug: # pragma: no cover - logger.setLevel(logging.DEBUG) - def list_backends(): for backend in sorted(backends.getBackendList(), key=lambda backend: backend.identifier): if cmdargs.debug: @@ -140,154 +131,167 @@ def list_modifiers(): for modifier_id, modifier in modifiers.items(): print("{:>10} : {}".format(modifier_id, modifier.__doc__)) -if cmdargs.lists: - print("Backends:") - list_backends() +def main(): + argparser = set_argparser() + cmdargs = argparser.parse_args() - print() - print("Configurations:") - list_configurations(cmdargs.target) + scm = SigmaConfigurationManager() - print() - print("Modifiers:") - list_modifiers() - sys.exit(0) -elif len(cmdargs.inputs) == 0: - print("Nothing to do!") - argparser.print_usage() - sys.exit(0) + logger = logging.getLogger(__name__) + if cmdargs.debug: # pragma: no cover + logger.setLevel(logging.DEBUG) -if cmdargs.target is None: - print("No target selected, select one with -t/--target") - argparser.print_usage() - sys.exit(ERR_NO_TARGET) + if cmdargs.lists: + print("Backends:") + list_backends() -rulefilter = None -if cmdargs.filter: - try: - rulefilter = SigmaRuleFilter(cmdargs.filter) - except SigmaRuleFilterParseException as e: - print("Parse error in Sigma rule filter expression: %s" % str(e), file=sys.stderr) - sys.exit(ERR_RULE_FILTER_PARSING) - -sigmaconfigs = SigmaConfigurationChain() -backend_class = backends.getBackend(cmdargs.target) -if cmdargs.config is None: - if backend_class.config_required and not cmdargs.shoot_yourself_in_the_foot: - print("The backend you want to use usually requires a configuration to generate valid results. Please provide one with --config/-c.", file=sys.stderr) - print("Available choices for this backend (get complete list with --lists/-l):") + print() + print("Configurations:") list_configurations(cmdargs.target) - sys.exit(ERR_CONFIG_REQUIRED) - if backend_class.default_config is not None: - cmdargs.config = backend_class.default_config -if cmdargs.config: - order = 0 - for conf_name in cmdargs.config: + print() + print("Modifiers:") + list_modifiers() + sys.exit(0) + elif len(cmdargs.inputs) == 0: + print("Nothing to do!") + argparser.print_usage() + sys.exit(0) + + if cmdargs.target is None: + print("No target selected, select one with -t/--target") + argparser.print_usage() + sys.exit(ERR_NO_TARGET) + + rulefilter = None + if cmdargs.filter: try: - sigmaconfig = scm.get(conf_name) - if sigmaconfig.order is not None: - if sigmaconfig.order <= order and not cmdargs.shoot_yourself_in_the_foot: - print("The configurations were provided in the wrong order (order key check in config file)", file=sys.stderr) - sys.exit(ERR_CONFIG_ORDER) - order = sigmaconfig.order + rulefilter = SigmaRuleFilter(cmdargs.filter) + except SigmaRuleFilterParseException as e: + print("Parse error in Sigma rule filter expression: %s" % str(e), file=sys.stderr) + sys.exit(ERR_RULE_FILTER_PARSING) + sigmaconfigs = SigmaConfigurationChain() + backend_class = backends.getBackend(cmdargs.target) + if cmdargs.config is None: + if backend_class.config_required and not cmdargs.shoot_yourself_in_the_foot: + print("The backend you want to use usually requires a configuration to generate valid results. Please provide one with --config/-c.", file=sys.stderr) + print("Available choices for this backend (get complete list with --lists/-l):") + list_configurations(cmdargs.target) + sys.exit(ERR_CONFIG_REQUIRED) + if backend_class.default_config is not None: + cmdargs.config = backend_class.default_config + + if cmdargs.config: + order = 0 + for conf_name in cmdargs.config: try: - if cmdargs.target not in sigmaconfig.config["backends"]: - print("The configuration '{}' is not valid for backend '{}'. Valid choices are: {}".format(conf_name, cmdargs.target, ", ".join(sigmaconfig.config["backends"])), file=sys.stderr) - sys.exit(ERR_CONFIG_ORDER) - except KeyError: + sigmaconfig = scm.get(conf_name) + if sigmaconfig.order is not None: + if sigmaconfig.order <= order and not cmdargs.shoot_yourself_in_the_foot: + print("The configurations were provided in the wrong order (order key check in config file)", file=sys.stderr) + sys.exit(ERR_CONFIG_ORDER) + order = sigmaconfig.order + + try: + if cmdargs.target not in sigmaconfig.config["backends"]: + print("The configuration '{}' is not valid for backend '{}'. Valid choices are: {}".format(conf_name, cmdargs.target, ", ".join(sigmaconfig.config["backends"])), file=sys.stderr) + sys.exit(ERR_CONFIG_ORDER) + except KeyError: + pass + + sigmaconfigs.append(sigmaconfig) + except OSError as e: + print("Failed to open Sigma configuration file %s: %s" % (conf_name, str(e)), file=sys.stderr) + exit(ERR_OPEN_CONFIG_FILE) + except (yaml.parser.ParserError, yaml.scanner.ScannerError) as e: + print("Sigma configuration file %s is no valid YAML: %s" % (conf_name, str(e)), file=sys.stderr) + exit(ERR_CONFIG_INVALID_YAML) + except SigmaConfigParseError as e: + print("Sigma configuration parse error in %s: %s" % (conf_name, str(e)), file=sys.stderr) + exit(ERR_CONFIG_PARSING) + + backend_options = BackendOptions(cmdargs.backend_option, cmdargs.backend_config) + backend = backend_class(sigmaconfigs, backend_options) + + filename = cmdargs.output + if filename: + try: + out = open(filename, "w", encoding='utf-8') + except (IOError, OSError) as e: + print("Failed to open output file '%s': %s" % (filename, str(e)), file=sys.stderr) + exit(ERR_OUTPUT) + else: + out = sys.stdout + + error = 0 + for sigmafile in get_inputs(cmdargs.inputs, cmdargs.recurse): + logger.debug("* Processing Sigma input %s" % (sigmafile)) + try: + if cmdargs.inputs == ['-']: + f = sigmafile + else: + f = sigmafile.open(encoding='utf-8') + parser = SigmaCollectionParser(f, sigmaconfigs, rulefilter) + results = parser.generate(backend) + for result in results: + print(result, file=out) + except OSError as e: + print("Failed to open Sigma file %s: %s" % (sigmafile, str(e)), file=sys.stderr) + error = ERR_OPEN_SIGMA_RULE + except (yaml.parser.ParserError, yaml.scanner.ScannerError) as e: + print("Sigma file %s is no valid YAML: %s" % (sigmafile, str(e)), file=sys.stderr) + error = ERR_INVALID_YAML + if not cmdargs.defer_abort: + sys.exit(error) + except (SigmaParseError, SigmaCollectionParseError) as e: + print("Sigma parse error in %s: %s" % (sigmafile, str(e)), file=sys.stderr) + error = ERR_SIGMA_PARSING + if not cmdargs.defer_abort: + sys.exit(error) + except NotSupportedError as e: + print("The Sigma rule requires a feature that is not supported by the target system: " + str(e), file=sys.stderr) + if not cmdargs.ignore_backend_errors: + error = ERR_NOT_SUPPORTED + if not cmdargs.defer_abort: + sys.exit(error) + except BackendError as e: + print("Backend error in %s: %s" % (sigmafile, str(e)), file=sys.stderr) + if not cmdargs.ignore_backend_errors: + error = ERR_BACKEND + if not cmdargs.defer_abort: + sys.exit(error) + except (NotImplementedError, TypeError) as e: + print("An unsupported feature is required for this Sigma rule (%s): " % (sigmafile) + str(e), file=sys.stderr) + print("Feel free to contribute for fun and fame, this is open source :) -> https://github.com/Neo23x0/sigma", file=sys.stderr) + if not cmdargs.ignore_backend_errors: + error = ERR_NOT_IMPLEMENTED + if not cmdargs.defer_abort: + sys.exit(error) + except PartialMatchError as e: + print("Partial field match error: %s" % str(e), file=sys.stderr) + if not cmdargs.ignore_backend_errors: + error = ERR_PARTIAL_FIELD_MATCH + if not cmdargs.defer_abort: + sys.exit(error) + except FullMatchError as e: + print("Full field match error", file=sys.stderr) + if not cmdargs.ignore_backend_errors: + error = ERR_FULL_FIELD_MATCH + if not cmdargs.defer_abort: + sys.exit(error) + finally: + try: + f.close() + except: pass - sigmaconfigs.append(sigmaconfig) - except OSError as e: - print("Failed to open Sigma configuration file %s: %s" % (conf_name, str(e)), file=sys.stderr) - exit(ERR_OPEN_CONFIG_FILE) - except (yaml.parser.ParserError, yaml.scanner.ScannerError) as e: - print("Sigma configuration file %s is no valid YAML: %s" % (conf_name, str(e)), file=sys.stderr) - exit(ERR_CONFIG_INVALID_YAML) - except SigmaConfigParseError as e: - print("Sigma configuration parse error in %s: %s" % (conf_name, str(e)), file=sys.stderr) - exit(ERR_CONFIG_PARSING) + result = backend.finalize() + if result: + print(result, file=out) + out.close() -backend_options = BackendOptions(cmdargs.backend_option, cmdargs.backend_config) -backend = backend_class(sigmaconfigs, backend_options) + sys.exit(error) -filename = cmdargs.output -if filename: - try: - out = open(filename, "w", encoding='utf-8') - except (IOError, OSError) as e: - print("Failed to open output file '%s': %s" % (filename, str(e)), file=sys.stderr) - exit(ERR_OUTPUT) -else: - out = sys.stdout - -error = 0 -for sigmafile in get_inputs(cmdargs.inputs, cmdargs.recurse): - logger.debug("* Processing Sigma input %s" % (sigmafile)) - try: - if cmdargs.inputs == ['-']: - f = sigmafile - else: - f = sigmafile.open(encoding='utf-8') - parser = SigmaCollectionParser(f, sigmaconfigs, rulefilter) - results = parser.generate(backend) - for result in results: - print(result, file=out) - except OSError as e: - print("Failed to open Sigma file %s: %s" % (sigmafile, str(e)), file=sys.stderr) - error = ERR_OPEN_SIGMA_RULE - except (yaml.parser.ParserError, yaml.scanner.ScannerError) as e: - print("Sigma file %s is no valid YAML: %s" % (sigmafile, str(e)), file=sys.stderr) - error = ERR_INVALID_YAML - if not cmdargs.defer_abort: - sys.exit(error) - except (SigmaParseError, SigmaCollectionParseError) as e: - print("Sigma parse error in %s: %s" % (sigmafile, str(e)), file=sys.stderr) - error = ERR_SIGMA_PARSING - if not cmdargs.defer_abort: - sys.exit(error) - except NotSupportedError as e: - print("The Sigma rule requires a feature that is not supported by the target system: " + str(e), file=sys.stderr) - if not cmdargs.ignore_backend_errors: - error = ERR_NOT_SUPPORTED - if not cmdargs.defer_abort: - sys.exit(error) - except BackendError as e: - print("Backend error in %s: %s" % (sigmafile, str(e)), file=sys.stderr) - if not cmdargs.ignore_backend_errors: - error = ERR_BACKEND - if not cmdargs.defer_abort: - sys.exit(error) - except (NotImplementedError, TypeError) as e: - print("An unsupported feature is required for this Sigma rule (%s): " % (sigmafile) + str(e), file=sys.stderr) - print("Feel free to contribute for fun and fame, this is open source :) -> https://github.com/Neo23x0/sigma", file=sys.stderr) - if not cmdargs.ignore_backend_errors: - error = ERR_NOT_IMPLEMENTED - if not cmdargs.defer_abort: - sys.exit(error) - except PartialMatchError as e: - print("Partial field match error: %s" % str(e), file=sys.stderr) - if not cmdargs.ignore_backend_errors: - error = ERR_PARTIAL_FIELD_MATCH - if not cmdargs.defer_abort: - sys.exit(error) - except FullMatchError as e: - print("Full field match error", file=sys.stderr) - if not cmdargs.ignore_backend_errors: - error = ERR_FULL_FIELD_MATCH - if not cmdargs.defer_abort: - sys.exit(error) - finally: - try: - f.close() - except: - pass - -result = backend.finalize() -if result: - print(result, file=out) -out.close() - -sys.exit(error) +if __name__ == "__main__": + main() From c83b4fd37c391a26665e1d525869e7674a1cbf75 Mon Sep 17 00:00:00 2001 From: Florian Roth Date: Tue, 31 Mar 2020 11:30:47 +0200 Subject: [PATCH 02/94] fix: fixing script install for Windows end systems --- tools/setup.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tools/setup.py b/tools/setup.py index 11d0add3..d7849186 100644 --- a/tools/setup.py +++ b/tools/setup.py @@ -77,11 +77,13 @@ setup( 'config/generic/sysmon.yml', 'config/generic/windows-audit.yml', ])], - scripts=[ - 'sigmac', - 'merge_sigma', - 'sigma2misp', - 'sigma-similarity', - 'sigma-uuid', - ] + entry_points={ + 'console_scripts': [ + 'sigmac = sigmac:main', + 'merge_sigma = merge_sigma:main', + 'sigma2misp = sigma2misp:main', + 'sigma-similarity = sigma-similarity:main', + 'sigma-uuid = sigma-uuid:main', + ], + }, ) From bb50571b1390eb142ba91dcf715158d9eb07f07b Mon Sep 17 00:00:00 2001 From: Florian Roth Date: Tue, 31 Mar 2020 11:35:21 +0200 Subject: [PATCH 03/94] fix: print_verbose scope --- tools/sigma-uuid | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/sigma-uuid b/tools/sigma-uuid index 0fb58329..37531b39 100755 --- a/tools/sigma-uuid +++ b/tools/sigma-uuid @@ -8,8 +8,7 @@ import yaml from sigma.output import SigmaYAMLDumper def print_verbose(*arg, **kwarg): - if args.verbose: - print(*arg, **kwarg) + print(*arg, **kwarg) # Define order-preserving representer from dicts/maps def yaml_preserve_order(self, dict_data): @@ -24,6 +23,9 @@ def main(): argparser.add_argument("inputs", nargs="+", help="Sigma rule files or repository directories") args = argparser.parse_args() + if args.verbose: + print_verbose() + if args.recursive: paths = [ p for pathname in args.inputs for p in Path(pathname).glob("**/*") if p.is_file() ] else: From 23ce69eaaeae7cd50856188875fc0cbc1544f9ce Mon Sep 17 00:00:00 2001 From: Florian Roth Date: Tue, 31 Mar 2020 11:42:16 +0200 Subject: [PATCH 04/94] fix: functions parameters outside of main --- tools/sigmac | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/sigmac b/tools/sigmac index e1aff610..718a9402 100755 --- a/tools/sigmac +++ b/tools/sigmac @@ -115,19 +115,19 @@ def set_argparser(): return argparser -def list_backends(): +def list_backends(debug): for backend in sorted(backends.getBackendList(), key=lambda backend: backend.identifier): - if cmdargs.debug: + if debug: print("{:>15} : {} ({})".format(backend.identifier, backend.__doc__, backend.__name__)) else: print("{:>15} : {}".format(backend.identifier, backend.__doc__)) -def list_configurations(backend=None): +def list_configurations(backend=None, scm=scm): for conf_id, title, backends in sorted(scm.list(), key=lambda config: config[0]): if backend is not None and backend in backends or backend is None or len(backends) == 0: print("{:>30} : {}".format(conf_id, title)) -def list_modifiers(): +def list_modifiers(modifiers): for modifier_id, modifier in modifiers.items(): print("{:>10} : {}".format(modifier_id, modifier.__doc__)) @@ -143,15 +143,15 @@ def main(): if cmdargs.lists: print("Backends:") - list_backends() + list_backends(cmdargs.debug) print() print("Configurations:") - list_configurations(cmdargs.target) + list_configurations(backend=cmdargs.target, scm=scm) print() print("Modifiers:") - list_modifiers() + list_modifiers(modifiers=modifiers) sys.exit(0) elif len(cmdargs.inputs) == 0: print("Nothing to do!") From c82156a3c994b87b0b06fc0a609c293034f33579 Mon Sep 17 00:00:00 2001 From: Florian Roth Date: Tue, 31 Mar 2020 11:46:05 +0200 Subject: [PATCH 05/94] fix: second list_configurations function params --- tools/sigmac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/sigmac b/tools/sigmac index 718a9402..1370213d 100755 --- a/tools/sigmac +++ b/tools/sigmac @@ -177,7 +177,7 @@ def main(): if backend_class.config_required and not cmdargs.shoot_yourself_in_the_foot: print("The backend you want to use usually requires a configuration to generate valid results. Please provide one with --config/-c.", file=sys.stderr) print("Available choices for this backend (get complete list with --lists/-l):") - list_configurations(cmdargs.target) + list_configurations(backend=cmdargs.target, scm=scm) sys.exit(ERR_CONFIG_REQUIRED) if backend_class.default_config is not None: cmdargs.config = backend_class.default_config From 18e505c4586bb889bf279885fe05fa33af4bd7ba Mon Sep 17 00:00:00 2001 From: Florian Roth Date: Tue, 31 Mar 2020 12:42:02 +0200 Subject: [PATCH 06/94] fix: list_configurations default values --- tools/sigmac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/sigmac b/tools/sigmac index 1370213d..275c295d 100755 --- a/tools/sigmac +++ b/tools/sigmac @@ -122,7 +122,7 @@ def list_backends(debug): else: print("{:>15} : {}".format(backend.identifier, backend.__doc__)) -def list_configurations(backend=None, scm=scm): +def list_configurations(backend=None, scm=None): for conf_id, title, backends in sorted(scm.list(), key=lambda config: config[0]): if backend is not None and backend in backends or backend is None or len(backends) == 0: print("{:>30} : {}".format(conf_id, title)) From 4d67dff89af43c8ca90d29e0a5cbdfb1cb8245f9 Mon Sep 17 00:00:00 2001 From: Florian Roth Date: Tue, 31 Mar 2020 14:07:34 +0200 Subject: [PATCH 07/94] fix: renamed tools to allow for console_scripts list entries --- tools/setup.py | 10 +++++----- tools/{sigma-similarity => sigma_similarity} | 0 tools/{sigma-uuid => sigma_uuid} | 0 3 files changed, 5 insertions(+), 5 deletions(-) rename tools/{sigma-similarity => sigma_similarity} (100%) rename tools/{sigma-uuid => sigma_uuid} (100%) diff --git a/tools/setup.py b/tools/setup.py index d7849186..d197ca9f 100644 --- a/tools/setup.py +++ b/tools/setup.py @@ -79,11 +79,11 @@ setup( ])], entry_points={ 'console_scripts': [ - 'sigmac = sigmac:main', - 'merge_sigma = merge_sigma:main', - 'sigma2misp = sigma2misp:main', - 'sigma-similarity = sigma-similarity:main', - 'sigma-uuid = sigma-uuid:main', + 'sigmac = sigmac:main', + 'merge_sigma = merge_sigma:main', + 'sigma2misp = sigma2misp:main', + 'sigma_similarity = sigma_similarity:main', + 'sigma_uuid = sigma-uuid:main', ], }, ) diff --git a/tools/sigma-similarity b/tools/sigma_similarity similarity index 100% rename from tools/sigma-similarity rename to tools/sigma_similarity diff --git a/tools/sigma-uuid b/tools/sigma_uuid similarity index 100% rename from tools/sigma-uuid rename to tools/sigma_uuid From 6aba430de60704a672ed62cc17ce25498b1451b9 Mon Sep 17 00:00:00 2001 From: Florian Roth Date: Tue, 31 Mar 2020 16:29:58 +0200 Subject: [PATCH 08/94] fix: sigma_uuid occurances --- Makefile | 2 +- contrib/filter-uuid-patch | 4 ++-- tools/setup.py | 2 +- tools/sigma_uuid | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 389d7973..ca9b0815 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ finish: test-rules: yamllint rules tests/test_rules.py - tools/sigma-uuid -Ver rules/ + tools/sigma_uuid -Ver rules/ test-sigmac: coverage run -a --include=$(COVSCOPE) tools/sigmac diff --git a/contrib/filter-uuid-patch b/contrib/filter-uuid-patch index 19249598..bcce012e 100755 --- a/contrib/filter-uuid-patch +++ b/contrib/filter-uuid-patch @@ -1,10 +1,10 @@ #!/usr/bin/env python3 # Remove all hunks from a patch that don't add the id attribute to minimize the impact (removed -# comments etc.) of sigma-uuid script. +# comments etc.) of sigma_uuid script. # # Usually used as follows: # 1. Add UUIDs to rules: -# tools/sigma-uuid -er rules +# tools/sigma_uuid -er rules # 2. Generate and filter patch # git diff | contrib/filter-uuid-patch > rule-uuid.diff # 3. Reset to previous state diff --git a/tools/setup.py b/tools/setup.py index d197ca9f..5ac5f0f1 100644 --- a/tools/setup.py +++ b/tools/setup.py @@ -83,7 +83,7 @@ setup( 'merge_sigma = merge_sigma:main', 'sigma2misp = sigma2misp:main', 'sigma_similarity = sigma_similarity:main', - 'sigma_uuid = sigma-uuid:main', + 'sigma_uuid = sigma_uuid:main', ], }, ) diff --git a/tools/sigma_uuid b/tools/sigma_uuid index 37531b39..2a8b003c 100755 --- a/tools/sigma_uuid +++ b/tools/sigma_uuid @@ -81,7 +81,7 @@ def main(): print("* Contained in the 'id' attribute") print("* a valid UUIDv4 (randomly generated)") print("* Unique in this repository") - print("Please generate one with the sigma-uuid tool or here: https://www.uuidgenerator.net/version4") + print("Please generate one with the sigma_uuid tool or here: https://www.uuidgenerator.net/version4") if args.error: exit(10) From 13dbb4cdbd3c4e1ed66ee6e265514102a375226a Mon Sep 17 00:00:00 2001 From: Thomas Patzke Date: Tue, 31 Mar 2020 23:46:58 +0200 Subject: [PATCH 09/94] Moved tools into sigma namespace --- Makefile | 2 +- tools/setup.py | 12 ++++++------ tools/{merge_sigma => sigma/merge_sigma.py} | 0 tools/{sigma2attack => sigma/sigma2attack.py} | 0 .../sigma2genericsigma.py} | 0 tools/{sigma2misp => sigma/sigma2misp.py} | 0 .../{sigma_similarity => sigma/sigma_similarity.py} | 0 tools/{sigma_uuid => sigma/sigma_uuid.py} | 0 tools/{sigmac => sigma/sigmac.py} | 0 9 files changed, 7 insertions(+), 7 deletions(-) rename tools/{merge_sigma => sigma/merge_sigma.py} (100%) rename tools/{sigma2attack => sigma/sigma2attack.py} (100%) rename tools/{sigma2genericsigma => sigma/sigma2genericsigma.py} (100%) rename tools/{sigma2misp => sigma/sigma2misp.py} (100%) rename tools/{sigma_similarity => sigma/sigma_similarity.py} (100%) rename tools/{sigma_uuid => sigma/sigma_uuid.py} (100%) rename tools/{sigmac => sigma/sigmac.py} (100%) diff --git a/Makefile b/Makefile index ca9b0815..c76da3fc 100644 --- a/Makefile +++ b/Makefile @@ -100,7 +100,7 @@ test-backend-es-qs: test-sigma2attack: coverage run -a --include=$(COVSCOPE) tools/sigma2attack -build: tools/sigmac tools/merge_sigma tools/sigma/*.py tools/setup.py tools/setup.cfg +build: tools/sigma/*.py tools/setup.py tools/setup.cfg cd tools && python3 setup.py bdist_wheel sdist upload-test: build diff --git a/tools/setup.py b/tools/setup.py index 5ac5f0f1..7f867142 100644 --- a/tools/setup.py +++ b/tools/setup.py @@ -13,7 +13,7 @@ with open(path.join(here, 'README.md'), encoding='utf-8') as f: setup( name='sigmatools', - version='0.16.0', + version='0.17.0', description='Tools for the Generic Signature Format for SIEM Systems', long_description=long_description, long_description_content_type="text/markdown", @@ -79,11 +79,11 @@ setup( ])], entry_points={ 'console_scripts': [ - 'sigmac = sigmac:main', - 'merge_sigma = merge_sigma:main', - 'sigma2misp = sigma2misp:main', - 'sigma_similarity = sigma_similarity:main', - 'sigma_uuid = sigma_uuid:main', + 'sigmac = sigma.sigmac:main', + 'merge_sigma = sigma.merge_sigma:main', + 'sigma2misp = sigma.sigma2misp:main', + 'sigma_similarity = sigma.sigma_similarity:main', + 'sigma_uuid = sigma.sigma_uuid:main', ], }, ) diff --git a/tools/merge_sigma b/tools/sigma/merge_sigma.py similarity index 100% rename from tools/merge_sigma rename to tools/sigma/merge_sigma.py diff --git a/tools/sigma2attack b/tools/sigma/sigma2attack.py similarity index 100% rename from tools/sigma2attack rename to tools/sigma/sigma2attack.py diff --git a/tools/sigma2genericsigma b/tools/sigma/sigma2genericsigma.py similarity index 100% rename from tools/sigma2genericsigma rename to tools/sigma/sigma2genericsigma.py diff --git a/tools/sigma2misp b/tools/sigma/sigma2misp.py similarity index 100% rename from tools/sigma2misp rename to tools/sigma/sigma2misp.py diff --git a/tools/sigma_similarity b/tools/sigma/sigma_similarity.py similarity index 100% rename from tools/sigma_similarity rename to tools/sigma/sigma_similarity.py diff --git a/tools/sigma_uuid b/tools/sigma/sigma_uuid.py similarity index 100% rename from tools/sigma_uuid rename to tools/sigma/sigma_uuid.py diff --git a/tools/sigmac b/tools/sigma/sigmac.py similarity index 100% rename from tools/sigmac rename to tools/sigma/sigmac.py From 46737cbfd3b696623f22c98475b897ee7603b6d0 Mon Sep 17 00:00:00 2001 From: Wietze Date: Sat, 2 May 2020 14:31:02 +0100 Subject: [PATCH 10/94] Improved Microsoft ATP mapping, using Advanced Hunting Schema See https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/advanced-hunting-schema-reference --- tools/sigma/backends/mdatp.py | 155 ++++++++++++++++++++++------------ 1 file changed, 100 insertions(+), 55 deletions(-) diff --git a/tools/sigma/backends/mdatp.py b/tools/sigma/backends/mdatp.py index 096ee829..7a2590be 100644 --- a/tools/sigma/backends/mdatp.py +++ b/tools/sigma/backends/mdatp.py @@ -18,6 +18,7 @@ import re from .base import SingleTextQueryBackend from .exceptions import NotSupportedError + class WindowsDefenderATPBackend(SingleTextQueryBackend): """Converts Sigma rule into Microsoft Defender ATP Hunting Queries.""" identifier = "mdatp" @@ -46,31 +47,68 @@ class WindowsDefenderATPBackend(SingleTextQueryBackend): """Initialize field mappings""" super().__init__(*args, **kwargs) self.fieldMappings = { # mapping between Sigma and ATP field names - # Supported values: - # (field name mapping, value mapping): distinct mappings for field name and value, may be a string (direct mapping) or function maps name/value to ATP target value - # (mapping function,): receives field name and value as parameter, return list of 2 element tuples (destination field name and value) - # (replacement, ): Replaces field occurrence with static string - "AccountName" : (self.id_mapping, self.default_value_mapping), - "CommandLine" : ("ProcessCommandLine", self.default_value_mapping), - "DeviceName" : (self.id_mapping, self.default_value_mapping), - "DestinationHostname" : ("RemoteUrl", self.default_value_mapping), - "DestinationIp" : ("RemoteIP", self.default_value_mapping), - "DestinationIsIpv6" : ("RemoteIP has \":\"", ), - "DestinationPort" : ("RemotePort", self.default_value_mapping), - "Details" : ("RegistryValueData", self.default_value_mapping), - "EventType" : ("ActionType", self.default_value_mapping), - "Image" : ("FolderPath", self.default_value_mapping), - "ImageLoaded" : ("FolderPath", self.default_value_mapping), - "LogonType" : (self.id_mapping, self.logontype_mapping), - "NewProcessName" : ("FolderPath", self.default_value_mapping), - "ObjectValueName" : ("RegistryValueName", self.default_value_mapping), - "ParentImage" : ("InitiatingProcessFolderPath", self.default_value_mapping), - "SourceImage" : ("InitiatingProcessFolderPath", self.default_value_mapping), - "TargetFilename" : ("FolderPath", self.default_value_mapping), - "TargetImage" : ("FolderPath", self.default_value_mapping), - "TargetObject" : ("RegistryKey", self.default_value_mapping), - "User" : (self.decompose_user, ), - } + # Supported values: + # (field name mapping, value mapping): distinct mappings for field name and value, may be a string (direct mapping) or function maps name/value to ATP target value + # (mapping function,): receives field name and value as parameter, return list of 2 element tuples (destination field name and value) + # (replacement, ): Replaces field occurrence with static string + "DeviceProcessEvents": { + "AccountName": (self.id_mapping, self.default_value_mapping), + "CommandLine": ("ProcessCommandLine", self.default_value_mapping), + "Command": ("ProcessCommandLine", self.default_value_mapping), + "DeviceName": (self.id_mapping, self.default_value_mapping), + "EventType": ("ActionType", self.default_value_mapping), + "Image": ("FolderPath", self.default_value_mapping), + "ImageLoaded": ("FolderPath", self.default_value_mapping), + "LogonType": (self.id_mapping, self.logontype_mapping), + "NewProcessName": ("FolderPath", self.default_value_mapping), + "ParentImage": ("InitiatingProcessFolderPath", self.default_value_mapping), + "SourceImage": ("InitiatingProcessFolderPath", self.default_value_mapping), + "TargetImage": ("FolderPath", self.default_value_mapping), + "TargetObject": ("RegistryKey", self.default_value_mapping), + "User": (self.decompose_user, ), + }, + "DeviceEvents": { + "TargetFilename": ("FolderPath", self.default_value_mapping), + + "Image": ("InitiatingFolderPath", self.default_value_mapping), + "TargetImage": ("InitiatingProcessFolderPath", self.default_value_mapping), + "User": (self.decompose_user, ), + }, + "DeviceRegistryEvents": { + "TargetObject": ("RegistryKey", self.default_value_mapping), + "ObjectValueName": ("RegistryValueName", self.default_value_mapping), + "Details": ("RegistryValueData", self.default_value_mapping), + + "Image": ("InitiatingFolderPath", self.default_value_mapping), + "TargetImage": ("InitiatingProcessFolderPath", self.default_value_mapping), + "User": (self.decompose_user, ), + }, + "DeviceFileEvents": { + "TargetFilename": ("FolderPath", self.default_value_mapping), + "TargetFileName": ("FolderPath", self.default_value_mapping), + + "Image": ("InitiatingProcessFolderPath", self.default_value_mapping), + "User": (self.decompose_user, ), + }, + "DeviceNetworkEvents": { + "Initiated": ("RemotePort", self.default_value_mapping), + "DestinationPort": ("RemotePort", self.default_value_mapping), + "DestinationIp": ("RemoteIP", self.default_value_mapping), + "DestinationIsIpv6": ("RemoteIP has \":\"", ), + "SourcePort": ("LocalPort", self.default_value_mapping), + "SourceIp": ("LocalIP", self.default_value_mapping), + "DestinationHostname": ("RemoteUrl", self.default_value_mapping), + + "Image": ("InitiatingProcessFolderPath", self.default_value_mapping), + "User": (self.decompose_user, ), + }, + "DeviceImageLoadEvents": { + "ImageLoaded": ("FolderPath", self.default_value_mapping), + + "Image": ("InitiatingProcessFolderPath", self.default_value_mapping), + "User": (self.decompose_user, ), + } + } def id_mapping(self, src): """Identity mapping, source == target field name""" @@ -100,16 +138,16 @@ class WindowsDefenderATPBackend(SingleTextQueryBackend): def logontype_mapping(self, src): """Value mapping for logon events to reduced ATP LogonType set""" logontype_mapping = { - 2: "Interactive", - 3: "Network", - 4: "Batch", - 5: "Service", - 7: "Interactive", # unsure - 8: "Network", - 9: "Interactive", # unsure - 10: "Remote interactive (RDP) logons", # really the value? - 11: "Interactive" - } + 2: "Interactive", + 3: "Network", + 4: "Batch", + 5: "Service", + 7: "Interactive", # unsure + 8: "Network", + 9: "Interactive", # unsure + 10: "Remote interactive (RDP) logons", # really the value? + 11: "Interactive" + } try: return logontype_mapping[int(src)] except KeyError: @@ -121,9 +159,9 @@ class WindowsDefenderATPBackend(SingleTextQueryBackend): m = reUser.match(src_value) if m: domain, user = m.groups() - return (("InitiatingProcessAccountDomain", domain), ("InititatingProcessAccountName", user)) + return (("InitiatingProcessAccountDomain", self.default_value_mapping(domain)), ("InititatingProcessAccountName", self.default_value_mapping(user))) else: # assume only user name is given if backslash is missing - return (("InititatingProcessAccountName", src_value),) + return [("InititatingProcessAccountName", self.default_value_mapping(src_value))] def generate(self, sigmaparser): self.table = None @@ -157,54 +195,61 @@ class WindowsDefenderATPBackend(SingleTextQueryBackend): and creates an appropriate table reference. """ key, value = node - if type(value) == list: # handle map items with values list like multiple OR-chained conditions - return self.generateORNode( - [(key, v) for v in value] - ) + # handle map items with values list like multiple OR-chained conditions + if type(value) == list: + return self.generateORNode([(key, v) for v in value]) elif key == "EventID": # EventIDs are not reflected in condition but in table selection if self.product == "windows": if self.service == "sysmon" and value == 1 \ - or self.service == "security" and value == 4688: # Process Execution + or self.service == "security" and value == 4688: # Process Execution self.table = "DeviceProcessEvents" return None - elif self.service == "sysmon" and value == 3: # Network Connection + elif self.service == "sysmon" and value == 3: # Network Connection self.table = "DeviceNetworkEvents" return None - elif self.service == "sysmon" and value == 7: # Image Load + elif self.service == "sysmon" and value == 7: # Image Load self.table = "DeviceImageLoadEvents" return None - elif self.service == "sysmon" and value == 8: # Create Remote Thread + elif self.service == "sysmon" and value == 8: # Create Remote Thread self.table = "DeviceEvents" return "ActionType == \"CreateRemoteThreadApiCall\"" - elif self.service == "sysmon" and value == 11: # File Creation + elif self.service == "sysmon" and value == 11: # File Creation self.table = "DeviceFileEvents" + return "ActionType == \"FileCreated\"" + elif self.service == "sysmon" and value == 23: # File Deletion + self.table = "DeviceFileEvents" + return "ActionType == \"FileDeleted\"" + elif self.service == "sysmon" and value == 12: # Create/Delete Registry Value + self.table = "DeviceRegistryEvents" return None elif self.service == "sysmon" and value == 13 \ - or self.service == "security" and value == 4657: # Set Registry Value + or self.service == "security" and value == 4657: # Set Registry Value self.table = "DeviceRegistryEvents" return "ActionType == \"RegistryValueSet\"" elif self.service == "security" and value == 4624: self.table = "DeviceLogonEvents" return None + else: + if not self.table: + raise NotSupportedError("No sysmon Event ID provided") + else: + raise NotSupportedError("No mapping for Event ID %s" % value) elif type(value) in (str, int): # default value processing try: - mapping = self.fieldMappings[key] + mapping = self.fieldMappings[self.table][key] except KeyError: - raise NotSupportedError("No mapping defined for field '%s'" % key) + raise NotSupportedError("No mapping defined for field '%s' in '%s'" % (key, self.table)) if len(mapping) == 1: mapping = mapping[0] if type(mapping) == str: return mapping elif callable(mapping): conds = mapping(key, value) - return self.generateSubexpressionNode( - self.generateANDNode( - [cond for cond in mapping(key, value)] - ) - ) + return self.andToken.join(["{} {}".format(*cond) for cond in conds]) elif len(mapping) == 2: result = list() - for mapitem, val in zip(mapping, node): # iterate mapping and mapping source value synchronously over key and value + # iterate mapping and mapping source value synchronously over key and value + for mapitem, val in zip(mapping, node): if type(mapitem) == str: result.append(mapitem) elif callable(mapitem): From 661108903bffab238070f286da235b16df9b5882 Mon Sep 17 00:00:00 2001 From: Wietze Date: Sat, 2 May 2020 14:37:37 +0100 Subject: [PATCH 11/94] Minor consistency fix --- tools/sigma/backends/mdatp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/sigma/backends/mdatp.py b/tools/sigma/backends/mdatp.py index 7a2590be..11d6f7f1 100644 --- a/tools/sigma/backends/mdatp.py +++ b/tools/sigma/backends/mdatp.py @@ -161,7 +161,7 @@ class WindowsDefenderATPBackend(SingleTextQueryBackend): domain, user = m.groups() return (("InitiatingProcessAccountDomain", self.default_value_mapping(domain)), ("InititatingProcessAccountName", self.default_value_mapping(user))) else: # assume only user name is given if backslash is missing - return [("InititatingProcessAccountName", self.default_value_mapping(src_value))] + return (("InititatingProcessAccountName", self.default_value_mapping(src_value))) def generate(self, sigmaparser): self.table = None From 5abf4cbea9c2a48605250687c0f6e1bd6da5c4ef Mon Sep 17 00:00:00 2001 From: Wietze Date: Sat, 2 May 2020 14:46:55 +0100 Subject: [PATCH 12/94] Reordered fields --- tools/sigma/backends/mdatp.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tools/sigma/backends/mdatp.py b/tools/sigma/backends/mdatp.py index 11d6f7f1..d8c38a5a 100644 --- a/tools/sigma/backends/mdatp.py +++ b/tools/sigma/backends/mdatp.py @@ -64,14 +64,13 @@ class WindowsDefenderATPBackend(SingleTextQueryBackend): "ParentImage": ("InitiatingProcessFolderPath", self.default_value_mapping), "SourceImage": ("InitiatingProcessFolderPath", self.default_value_mapping), "TargetImage": ("FolderPath", self.default_value_mapping), - "TargetObject": ("RegistryKey", self.default_value_mapping), "User": (self.decompose_user, ), }, "DeviceEvents": { "TargetFilename": ("FolderPath", self.default_value_mapping), + "TargetImage": ("FolderPath", self.default_value_mapping), - "Image": ("InitiatingFolderPath", self.default_value_mapping), - "TargetImage": ("InitiatingProcessFolderPath", self.default_value_mapping), + "Image": ("InitiatingProcessFolderPath", self.default_value_mapping), "User": (self.decompose_user, ), }, "DeviceRegistryEvents": { @@ -79,8 +78,7 @@ class WindowsDefenderATPBackend(SingleTextQueryBackend): "ObjectValueName": ("RegistryValueName", self.default_value_mapping), "Details": ("RegistryValueData", self.default_value_mapping), - "Image": ("InitiatingFolderPath", self.default_value_mapping), - "TargetImage": ("InitiatingProcessFolderPath", self.default_value_mapping), + "Image": ("InitiatingProcessFolderPath", self.default_value_mapping), "User": (self.decompose_user, ), }, "DeviceFileEvents": { From e5574e07f211fcd1fd4b87c10a95b232120830e2 Mon Sep 17 00:00:00 2001 From: Wietze Date: Sat, 2 May 2020 16:21:56 +0100 Subject: [PATCH 13/94] Disabled FileDelete event (Sysmon 11 - no rules available yet) --- tools/sigma/backends/mdatp.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/sigma/backends/mdatp.py b/tools/sigma/backends/mdatp.py index d8c38a5a..9da3f0ed 100644 --- a/tools/sigma/backends/mdatp.py +++ b/tools/sigma/backends/mdatp.py @@ -214,9 +214,9 @@ class WindowsDefenderATPBackend(SingleTextQueryBackend): elif self.service == "sysmon" and value == 11: # File Creation self.table = "DeviceFileEvents" return "ActionType == \"FileCreated\"" - elif self.service == "sysmon" and value == 23: # File Deletion - self.table = "DeviceFileEvents" - return "ActionType == \"FileDeleted\"" + # elif self.service == "sysmon" and value == 23: # File Deletion + # self.table = "DeviceFileEvents" + # return "ActionType == \"FileDeleted\"" elif self.service == "sysmon" and value == 12: # Create/Delete Registry Value self.table = "DeviceRegistryEvents" return None From 2b3828730c2c241f8d9fd522d3c2def4a4eb82ad Mon Sep 17 00:00:00 2001 From: Wietze Date: Sat, 2 May 2020 17:31:50 +0100 Subject: [PATCH 14/94] Reversed disabling FileDelete --- tools/sigma/backends/mdatp.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/sigma/backends/mdatp.py b/tools/sigma/backends/mdatp.py index 9da3f0ed..d8c38a5a 100644 --- a/tools/sigma/backends/mdatp.py +++ b/tools/sigma/backends/mdatp.py @@ -214,9 +214,9 @@ class WindowsDefenderATPBackend(SingleTextQueryBackend): elif self.service == "sysmon" and value == 11: # File Creation self.table = "DeviceFileEvents" return "ActionType == \"FileCreated\"" - # elif self.service == "sysmon" and value == 23: # File Deletion - # self.table = "DeviceFileEvents" - # return "ActionType == \"FileDeleted\"" + elif self.service == "sysmon" and value == 23: # File Deletion + self.table = "DeviceFileEvents" + return "ActionType == \"FileDeleted\"" elif self.service == "sysmon" and value == 12: # Create/Delete Registry Value self.table = "DeviceRegistryEvents" return None From 1a598282f4033e51e060b1014600970fdc64f72a Mon Sep 17 00:00:00 2001 From: zaphod <18658828+zaphodef@users.noreply.github.com> Date: Wed, 13 May 2020 11:57:10 +0200 Subject: [PATCH 15/94] Add 'Add-Content' to powershell_ntfs_ads_access --- rules/windows/powershell/powershell_ntfs_ads_access.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/rules/windows/powershell/powershell_ntfs_ads_access.yml b/rules/windows/powershell/powershell_ntfs_ads_access.yml index 422ed4ea..e2c531b7 100644 --- a/rules/windows/powershell/powershell_ntfs_ads_access.yml +++ b/rules/windows/powershell/powershell_ntfs_ads_access.yml @@ -16,6 +16,7 @@ logsource: detection: keyword1: - "set-content" + - "add-content" keyword2: - "-stream" condition: keyword1 and keyword2 From f970d28f10b1e7906593265055bb6a804142ee4e Mon Sep 17 00:00:00 2001 From: ecco Date: Sat, 23 May 2020 15:06:15 -0400 Subject: [PATCH 16/94] add more false positives --- rules/windows/sysmon/sysmon_wmi_module_load.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rules/windows/sysmon/sysmon_wmi_module_load.yml b/rules/windows/sysmon/sysmon_wmi_module_load.yml index 5b3eca68..2c302532 100644 --- a/rules/windows/sysmon/sysmon_wmi_module_load.yml +++ b/rules/windows/sysmon/sysmon_wmi_module_load.yml @@ -32,6 +32,8 @@ detection: - '\WmiAPsrv.exe' - '\svchost.exe' - '\DeviceCensus.exe' + - '\CompatTelRunner.exe' + - '\sdiagnhost.exe' condition: selection and not filter fields: - ComputerName From 7037e77569e062b85f335ef3c9d04b2d392b5214 Mon Sep 17 00:00:00 2001 From: ecco Date: Mon, 25 May 2020 04:50:22 -0400 Subject: [PATCH 17/94] add more FP --- rules/windows/sysmon/sysmon_wmi_module_load.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/rules/windows/sysmon/sysmon_wmi_module_load.yml b/rules/windows/sysmon/sysmon_wmi_module_load.yml index 2c302532..8c660f19 100644 --- a/rules/windows/sysmon/sysmon_wmi_module_load.yml +++ b/rules/windows/sysmon/sysmon_wmi_module_load.yml @@ -34,6 +34,7 @@ detection: - '\DeviceCensus.exe' - '\CompatTelRunner.exe' - '\sdiagnhost.exe' + - '\SIHClient.exe' condition: selection and not filter fields: - ComputerName From dedfb65d635f544011e30cf6ab303db7d782e092 Mon Sep 17 00:00:00 2001 From: Jonas Hagg Date: Mon, 25 May 2020 10:44:14 +0200 Subject: [PATCH 18/94] Implemented Aggregation for SQL, Added SQLite FullTextSearch --- tools/sigma/backends/sql.py | 124 +++++++++-- tools/sigma/backends/sqlite.py | 125 +++++++++++ tools/tests/test_backend_sql.py | 320 +++++++++++++++++++++++++++++ tools/tests/test_backend_sqlite.py | 133 ++++++++++++ 4 files changed, 688 insertions(+), 14 deletions(-) create mode 100644 tools/sigma/backends/sqlite.py create mode 100644 tools/tests/test_backend_sql.py create mode 100644 tools/tests/test_backend_sqlite.py diff --git a/tools/sigma/backends/sql.py b/tools/sigma/backends/sql.py index b3149c01..72f7cc29 100644 --- a/tools/sigma/backends/sql.py +++ b/tools/sigma/backends/sql.py @@ -16,7 +16,9 @@ import re import sigma -from .base import SingleTextQueryBackend +from sigma.backends.base import SingleTextQueryBackend +from sigma.parser.condition import SigmaAggregationParser, NodeSubexpression, ConditionAND, ConditionOR, ConditionNOT +from sigma.parser.exceptions import SigmaParseError class SQLBackend(SingleTextQueryBackend): """Converts Sigma rule into SQL query""" @@ -34,12 +36,16 @@ class SQLBackend(SingleTextQueryBackend): notNullExpression = "%s=*" # Expression of queries for not null values. %s is field name mapExpression = "%s = %s" # Syntax for field/value conditions. First %s is fieldname, second is value mapMulti = "%s IN %s" # Syntax for field/value conditions. First %s is fieldname, second is value - mapWildcard = "%s LIKE %s" # Syntax for swapping wildcard conditions. + mapWildcard = "%s LIKE %s escape \'\\\'"# Syntax for swapping wildcard conditions: Adding \ as escape character mapSource = "%s=%s" # Syntax for sourcetype mapListsSpecialHandling = False # Same handling for map items with list values as for normal values (strings, integers) if True, generateMapItemListNode method is called with node mapListValueExpression = "%s OR %s" # Syntax for field/value condititons where map value is a list mapLength = "(%s %s)" + def __init__(self, sigmaconfig, table): + super().__init__(sigmaconfig) + self.table = table + def generateANDNode(self, node): generated = [ self.generateNode(val) for val in node ] filtered = [ g for g in generated if g is not None ] @@ -78,29 +84,32 @@ class SQLBackend(SingleTextQueryBackend): def generateMapItemNode(self, node): fieldname, value = node transformed_fieldname = self.fieldNameMapping(fieldname, value) - if "," in self.generateNode(value) and "%" not in self.generateNode(value): + + has_wildcard = re.search(r"((\\(\*|\?|\\))|\*|\?|_|%)", self.generateNode(value)) + + if "," in self.generateNode(value) and not has_wildcard: return self.mapMulti % (transformed_fieldname, self.generateNode(value)) elif "LENGTH" in transformed_fieldname: return self.mapLength % (transformed_fieldname, value) elif type(value) == list: return self.generateMapItemListNode(transformed_fieldname, value) - elif self.mapListsSpecialHandling == False and type(value) in (str, int, list) or self.mapListsSpecialHandling == True and type(value) in (str, int): - if "%" in self.generateNode(value): + elif self.mapListsSpecialHandling == False and type(value) in (str, int, list) or self.mapListsSpecialHandling == True and type(value) in (str, int): + if has_wildcard: return self.mapWildcard % (transformed_fieldname, self.generateNode(value)) else: return self.mapExpression % (transformed_fieldname, self.generateNode(value)) elif "sourcetype" in transformed_fieldname: return self.mapSource % (transformed_fieldname, self.generateNode(value)) - elif "*" in str(value): + elif has_wildcard: return self.mapWildcard % (transformed_fieldname, self.generateNode(value)) else: raise TypeError("Backend does not support map values of type " + str(type(value))) def generateMapItemListNode(self, key, value): - return "(" + (" OR ".join(['%s LIKE %s' % (key, self.generateValueNode(item)) for item in value])) + ")" + return "(" + (" OR ".join([self.mapWildcard % (key, self.generateValueNode(item)) for item in value])) + ")" def generateValueNode(self, node): - return self.valueExpression % (self.cleanValue(str(node))) + return self.valueExpression % (self.cleanValue(str(node))) def generateNULLValueNode(self, node): return self.nullExpression % (node.item) @@ -117,10 +126,97 @@ class SQLBackend(SingleTextQueryBackend): return fieldname def cleanValue(self, val): - if "*" == val: - pass - elif "*.*.*" in val: - val = val.replace("*.*.*", "%") - elif re.search(r'\*', val): - val = re.sub(r'\*', '%', val) + if not isinstance(val, str): + return str(val) + + #Single backlashes which are not in front of * or ? are doulbed + val = re.sub(r"(? full text search + #False: no subexpression found, where a full text search is needed + + def _evaluateCondition(condition): + #Helper function to evaulate condtions + if type(condition) not in [ConditionAND, ConditionOR, ConditionNOT]: + raise NotImplementedError("Error in recursive Search logic") + + results = [] + for elem in condition.items: + if isinstance(elem, NodeSubexpression): + results.append(self._recursiveFtsSearch(elem)) + if isinstance(elem, ConditionNOT): + results.append(_evaluateCondition(elem)) + if isinstance(elem, tuple): + results.append(False) + if type(elem) in (str, int, list): + return True + return any(results) + + if type(subexpression) in [str, int, list]: + return True + elif type(subexpression) in [tuple]: + return False + + if not isinstance(subexpression, NodeSubexpression): + raise NotImplementedError("Error in recursive Search logic") + + if isinstance(subexpression.items, NodeSubexpression): + return self._recursiveFtsSearch(subexpression.items) + elif type(subexpression.items) in [ConditionAND, ConditionOR, ConditionNOT]: + return _evaluateCondition(subexpression.items) \ No newline at end of file diff --git a/tools/sigma/backends/sqlite.py b/tools/sigma/backends/sqlite.py new file mode 100644 index 00000000..c4e2651e --- /dev/null +++ b/tools/sigma/backends/sqlite.py @@ -0,0 +1,125 @@ + +from sigma.backends.sql import SQLBackend +from sigma.parser.condition import NodeSubexpression, ConditionAND, ConditionOR, ConditionNOT +import re + + +class SQLiteBackend(SQLBackend): + """SQLiteBackend provides FullTextSearch functionality""" + identifier = "sqlite" + active = True + + mapFullTextSearch = "%s MATCH ('\"%s\"')" + + def __init__(self, sigmaconfig, table): + super().__init__(sigmaconfig, table) + self.mappingItem = False + + def requireFTS(self, node): + return (not self.mappingItem and + (type(node) in (int, str) or all(isinstance(val, str) for val in node) or all(isinstance(val, int) for val in node))) + + def generateFTS(self, value): + if re.search(r"((\\(\*|\?|\\))|\*|\?|_|%)", value): + raise NotImplementedError( + "Wildcards in SQlite Full Text Search not implemented") + self.countFTS += 1 + return self.mapFullTextSearch % (self.table, value) + + def generateANDNode(self, node): + + if self.requireFTS(node): + fts = str('"' + self.andToken + '"').join(self.cleanValue(val) + for val in node) + return self.generateFTS(fts) + + generated = [self.generateNode(val) for val in node] + filtered = [g for g in generated if g is not None] + if filtered: + return self.andToken.join(filtered) + else: + return None + + def generateORNode(self, node): + + if self.requireFTS(node): + fts = str('"' + self.orToken + '"').join(self.cleanValue(val) + for val in node) + return self.generateFTS(fts) + + generated = [self.generateNode(val) for val in node] + filtered = [g for g in generated if g is not None] + if filtered: + return self.orToken.join(filtered) + else: + return None + + def generateMapItemNode(self, node): + try: + self.mappingItem = True + fieldname, value = node + transformed_fieldname = self.fieldNameMapping(fieldname, value) + + has_wildcard = re.search( + r"((\\(\*|\?|\\))|\*|\?|_|%)", self.generateNode(value)) + + if "," in self.generateNode(value) and not has_wildcard: + return self.mapMulti % (transformed_fieldname, self.generateNode(value)) + elif "LENGTH" in transformed_fieldname: + return self.mapLength % (transformed_fieldname, value) + elif type(value) == list: + return self.generateMapItemListNode(transformed_fieldname, value) + elif self.mapListsSpecialHandling == False and type(value) in (str, int, list) or self.mapListsSpecialHandling == True and type(value) in (str, int): + + if has_wildcard: + return self.mapWildcard % (transformed_fieldname, self.generateNode(value)) + else: + return self.mapExpression % (transformed_fieldname, self.generateNode(value)) + + elif "sourcetype" in transformed_fieldname: + return self.mapSource % (transformed_fieldname, self.generateNode(value)) + elif has_wildcard: + return self.mapWildcard % (transformed_fieldname, self.generateNode(value)) + else: + raise TypeError( + "Backend does not support map values of type " + str(type(value))) + finally: + self.mappingItem = False + + def generateValueNode(self, node): + if self.mappingItem: + return self.valueExpression % (self.cleanValue(str(node))) + else: + return self.generateFTS(self.cleanValue(str(node))) + + def generateQuery(self, parsed): + self.countFTS = 0 + result = self.generateNode(parsed.parsedSearch) + if self.countFTS > 1: + raise NotImplementedError( + "Match operator ({}) is allowed only once in SQLite, parse rule in a different way:\n{}".format(self.countFTS, result)) + self.countFTS = 0 + + if parsed.parsedAgg: + # Handle aggregation + fro, whe = self.generateAggregation(parsed.parsedAgg, result) + return "SELECT * FROM {} WHERE {}".format(fro, whe) + + return "SELECT * FROM {} WHERE {}".format(self.table, result) + + def generateFullTextQuery(self, search, parsed): + + search = search.replace('"', '') + search = '" OR "'.join(search.split(" OR ")) + search = '" AND "'.join(search.split(" AND ")) + search = '"{}"'.format(search) + search = search.replace('%', '') + search = search.replace('_', '') + search = '{} MATCH (\'{}\')'.format(self.table, search) + + if parsed.parsedAgg: + # Handle aggregation + fro, whe = self.generateAggregation(parsed.parsedAgg, search) + return "SELECT * FROM {} WHERE {}".format(fro, whe) + + return 'SELECT * FROM {} WHERE {}'.format(self.table, search) \ No newline at end of file diff --git a/tools/tests/test_backend_sql.py b/tools/tests/test_backend_sql.py new file mode 100644 index 00000000..c1a9b38b --- /dev/null +++ b/tools/tests/test_backend_sql.py @@ -0,0 +1,320 @@ +import unittest +from unittest.mock import patch + +from sigma.backends.sql import SQLBackend + +from sigma.parser.collection import SigmaCollectionParser +from sigma.config.mapping import FieldMapping +from sigma.configuration import SigmaConfiguration + +class TestGenerateQuery(unittest.TestCase): + + def setUp(self): + self.basic_rule = {"title": "Test", "level": "testing"} + self.table = "eventlog" + + def test_regular_queries(self): + # Test regular queries + detection = {"selection": {"fieldname": "test1"}, + "condition": "selection"} + expected_result = 'select * from {} where fieldname = "test1"'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": 4}, "condition": "selection"} + expected_result = 'select * from {} where fieldname = "4"'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": [ + "test1", "test2"]}, "condition": "selection"} + expected_result = 'select * from {} where fieldname in ("test1", "test2")'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": { + "fieldname": [3, 4]}, "condition": "selection"} + expected_result = 'select * from {} where fieldname in ("3", "4")'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname1": "test1", "fieldname2": [ + "test2", "test3"]}, "condition": "selection"} + expected_result = 'select * from {} where (fieldname1 = "test1" and fieldname2 in ("test2", "test3"))'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": "test1"}, "filter": { + "fieldname2": "whatever"}, "condition": "selection and filter"} + expected_result = 'select * from {} where (fieldname = "test1" and fieldname2 = "whatever")'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": "test1"}, "filter": { + "fieldname2": "whatever"}, "condition": "selection or filter"} + expected_result = 'select * from {} where (fieldname = "test1" or fieldname2 = "whatever")'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": "test1"}, "filter": { + "fieldname2": "whatever"}, "condition": "selection and not filter"} + expected_result = 'select * from {} where (fieldname = "test1" and not (fieldname2 = "whatever"))'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname1": "test1"}, "filter": { + "fieldname2": "test2"}, "condition": "1 of them"} + expected_result = 'select * from {} where (fieldname1 = "test1" or fieldname2 = "test2")'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname1": "test1"}, "filter": { + "fieldname2": "test2"}, "condition": "all of them"} + expected_result = 'select * from {} where (fieldname1 = "test1" and fieldname2 = "test2")'.format( + self.table) + self.validate(detection, expected_result) + + def test_modifiers(self): + + # contains + detection = {"selection": {"fieldname|contains": "test"}, + "condition": "selection"} + expected_result = 'select * from {} where fieldname like "%test%" escape \'\\\''.format( + self.table) + self.validate(detection, expected_result) + + # all + detection = {"selection": {"fieldname|all": [ + "test1", "test2"]}, "condition": "selection"} + expected_result = 'select * from {} where (fieldname = "test1" and fieldname = "test2")'.format( + self.table) + self.validate(detection, expected_result) + + # endswith + detection = {"selection": {"fieldname|endswith": "test"}, + "condition": "selection"} + expected_result = 'select * from {} where fieldname like "%test" escape \'\\\''.format( + self.table) + self.validate(detection, expected_result) + + # startswith + detection = {"selection": {"fieldname|startswith": "test"}, + "condition": "selection"} + expected_result = 'select * from {} where fieldname like "test%" escape \'\\\''.format( + self.table) + self.validate(detection, expected_result) + + def test_aggregations(self): + + # count + detection = {"selection": {"fieldname": "test"}, + "condition": "selection | count() > 5"} + inner_query = 'select count(*) as agg from {} where fieldname = "test"'.format( + self.table) + expected_result = 'select * from ({}) where agg > 5'.format(inner_query) + self.validate(detection, expected_result) + + # min + detection = {"selection": {"fieldname1": "test"}, + "condition": "selection | min(fieldname2) > 5"} + inner_query = 'select min(fieldname2) as agg from {} where fieldname1 = "test"'.format( + self.table) + expected_result = 'select * from ({}) where agg > 5'.format(inner_query) + self.validate(detection, expected_result) + + # max + detection = {"selection": {"fieldname1": "test"}, + "condition": "selection | max(fieldname2) > 5"} + inner_query = 'select max(fieldname2) as agg from {} where fieldname1 = "test"'.format( + self.table) + expected_result = 'select * from ({}) where agg > 5'.format(inner_query) + self.validate(detection, expected_result) + + # avg + detection = {"selection": {"fieldname1": "test"}, + "condition": "selection | avg(fieldname2) > 5"} + inner_query = 'select avg(fieldname2) as agg from {} where fieldname1 = "test"'.format( + self.table) + expected_result = 'select * from ({}) where agg > 5'.format(inner_query) + self.validate(detection, expected_result) + + # sum + detection = {"selection": {"fieldname1": "test"}, + "condition": "selection | sum(fieldname2) > 5"} + inner_query = 'select sum(fieldname2) as agg from {} where fieldname1 = "test"'.format( + self.table) + expected_result = 'select * from ({}) where agg > 5'.format(inner_query) + self.validate(detection, expected_result) + + # < + detection = {"selection": {"fieldname1": "test"}, + "condition": "selection | sum(fieldname2) < 5"} + inner_query = 'select sum(fieldname2) as agg from {} where fieldname1 = "test"'.format( + self.table) + expected_result = 'select * from ({}) where agg < 5'.format(inner_query) + self.validate(detection, expected_result) + + # == + detection = {"selection": {"fieldname1": "test"}, + "condition": "selection | sum(fieldname2) == 5"} + inner_query = 'select sum(fieldname2) as agg from {} where fieldname1 = "test"'.format( + self.table) + expected_result = 'select * from ({}) where agg == 5'.format(inner_query) + self.validate(detection, expected_result) + + # group by + detection = {"selection": {"fieldname1": "test"}, + "condition": "selection | sum(fieldname2) by fieldname3 == 5"} + inner_query = 'select sum(fieldname2) as agg from {} where fieldname1 = "test" group by fieldname3'.format( + self.table) + expected_result = 'select * from ({}) where agg == 5'.format(inner_query) + self.validate(detection, expected_result) + + # multiple conditions + detection = {"selection": {"fieldname1": "test"}, "filter": { + "fieldname2": "tessst"}, "condition": "selection or filter | sum(fieldname2) == 5"} + inner_query = 'select sum(fieldname2) as agg from {} where (fieldname1 = "test" or fieldname2 = "tessst")'.format( + self.table) + expected_result = 'select * from ({}) where agg == 5'.format(inner_query) + self.validate(detection, expected_result) + + def test_wildcards(self): + + # wildcard: * + detection = {"selection": {"fieldname": "test*"}, + "condition": "selection"} + expected_result = 'select * from {} where fieldname like '.format( + self.table) + r'"test%"' + r" escape '\'" + self.validate(detection, expected_result) + + # wildcard: ? + detection = {"selection": {"fieldname": "test?"}, + "condition": "selection"} + expected_result = 'select * from {} where fieldname like '.format( + self.table) + r'"test_"' + r" escape '\'" + self.validate(detection, expected_result) + + # escaping: + detection = {"selection": {"fieldname": r"test\?"}, + "condition": "selection"} + expected_result = 'select * from {} where fieldname like '.format( + self.table) + r'"test\?"' + r" escape '\'" + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": r"test\\*"}, + "condition": "selection"} + expected_result = 'select * from {} where fieldname like '.format( + self.table) + r'"test\\%"' + r" escape '\'" + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": r"test\*"}, + "condition": "selection"} + expected_result = 'select * from {} where fieldname like '.format( + self.table) + r'"test\*"' + r" escape '\'" + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": r"test\\"}, + "condition": "selection"} + expected_result = 'select * from {} where fieldname like '.format( + self.table) + r'"test\\"' + r" escape '\'" + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": r"test\abc"}, + "condition": "selection"} + expected_result = 'select * from {} where fieldname like '.format( + self.table) + r'"test\\abc"' + r" escape '\'" + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": r"test%"}, + "condition": "selection"} + expected_result = 'select * from {} where fieldname like '.format( + self.table) + r'"test\%"' + r" escape '\'" + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": r"test_"}, + "condition": "selection"} + expected_result = 'select * from {} where fieldname like '.format( + self.table) + r'"test\_"' + r" escape '\'" + self.validate(detection, expected_result) + + # multiple options + detection = {"selection": {"fieldname": [ + "test*", "*test"]}, "condition": "selection"} + opt1 = 'fieldname like ' + r'"test%"' + r" escape '\'" + opt2 = 'fieldname like ' + r'"%test"' + r" escape '\'" + expected_result = 'select * from {} where ({} or {})'.format( + self.table, opt1, opt2) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname|all": [ + "test*", "*test"]}, "condition": "selection"} + opt1 = 'fieldname like ' + r'"test%"' + r" escape '\'" + opt2 = 'fieldname like ' + r'"%test"' + r" escape '\'" + expected_result = 'select * from {} where ({} and {})'.format( + self.table, opt1, opt2) + self.validate(detection, expected_result) + + def test_fieldname_mapping(self): + detection = {"selection": {"fieldname": "test1"}, + "condition": "selection"} + expected_result = 'select * from {} where mapped_fieldname = "test1"'.format( + self.table) + + # configure mapping + config = SigmaConfiguration() + config.fieldmappings["fieldname"] = FieldMapping( + "fieldname", "mapped_fieldname") + + self.basic_rule["detection"] = detection + + with patch("yaml.safe_load_all", return_value=[self.basic_rule]): + parser = SigmaCollectionParser("any sigma io", config, None) + backend = SQLBackend(config, self.table) + + assert len(parser.parsers) == 1 + + for p in parser.parsers: + self.assertEqual(expected_result.lower(), + backend.generate(p).lower()) + + def test_not_implemented(self): + # near aggregation not implemented + detection = {"selection": {"fieldname": "test"}, "filter": { + "fieldname": "test2"}, "condition": "selection | near selection and filter"} + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + # re modifier is not implemented + detection = {"selection": {"fieldname|re": "test"}, + "condition": "selection"} + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + #Full Text Search is not implemented + detection = {"selection": ["test1"], "condition": "selection"} + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + + def validate(self, detection, expectation): + + config = SigmaConfiguration() + + self.basic_rule["detection"] = detection + + with patch("yaml.safe_load_all", return_value=[self.basic_rule]): + parser = SigmaCollectionParser("any sigma io", config, None) + backend = SQLBackend(config, self.table) + + assert len(parser.parsers) == 1 + + for p in parser.parsers: + if isinstance(expectation, str): + self.assertEqual(expectation.lower(), + backend.generate(p).lower()) + elif isinstance(expectation, Exception): + self.assertRaises(type(expectation), backend.generate, p) + + +if __name__ == '__main__': + unittest.main() diff --git a/tools/tests/test_backend_sqlite.py b/tools/tests/test_backend_sqlite.py new file mode 100644 index 00000000..3c6a7a71 --- /dev/null +++ b/tools/tests/test_backend_sqlite.py @@ -0,0 +1,133 @@ +import unittest +from unittest.mock import patch + +from sigma.backends.sqlite import SQLiteBackend + +from sigma.parser.collection import SigmaCollectionParser +from sigma.config.mapping import FieldMapping +from sigma.configuration import SigmaConfiguration + +class TestFullTextSearch(unittest.TestCase): + + def setUp(self): + self.basic_rule = {"title": "Test", "level": "testing"} + self.table = "eventlog" + + def test_full_text_search(self): + detection = {"selection": ["test1"], "condition": "selection"} + expected_result = 'select * from {0} where {0} match (\'"test1"\')'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": [5], "condition": "selection"} + expected_result = 'select * from {0} where {0} match (\'"5"\')'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": ["test1", "test2"], "condition": "selection"} + expected_result = 'select * from {0} where ({0} match (\'"test1" OR "test2"\'))'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": ["test1"], "filter":["test2"], "condition": "selection and filter"} + expected_result = 'select * from {0} where ({0} match (\'"test1" and "test2"\'))'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": [5, 6], "condition": "selection"} + expected_result = 'select * from {0} where ({0} match (\'"5" OR "6"\'))'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": ["test1"], "filter": [ + "test2"], "condition": "selection or filter"} + expected_result = 'select * from {0} where ({0} match (\'"test1" OR "test2"\'))'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": ["test1"], "filter": [ + "test2"], "condition": "selection and filter"} + expected_result = 'select * from {0} where ({0} match (\'"test1" and "test2"\'))'.format( + self.table) + self.validate(detection, expected_result) + + def test_full_text_search_aggregation(self): + # aggregation with fts + detection = {"selection": ["test"], + "condition": "selection | count() > 5"} + inner_query = 'select count(*) as agg from {0} where {0} match (\'"test"\')'.format( + self.table) + expected_result = 'select * from ({}) where agg > 5'.format(inner_query) + self.validate(detection, expected_result) + + detection = {"selection": ["test1", "test2"], + "condition": "selection | count() > 5"} + inner_query = 'select count(*) as agg from {0} where ({0} match (\'"test1" or "test2"\'))'.format( + self.table) + expected_result = 'select * from ({}) where agg > 5'.format(inner_query) + self.validate(detection, expected_result) + + # aggregation + group by + fts + detection = {"selection": ["test1", "test2"], + "condition": "selection | count() by fieldname > 5"} + inner_query = 'select count(*) as agg from {0} where ({0} match (\'"test1" or "test2"\')) group by fieldname'.format( + self.table) + expected_result = 'select * from ({}) where agg > 5'.format(inner_query) + self.validate(detection, expected_result) + + def test_not_implemented(self): + # fts not implemented with wildcards + detection = {"selection": ["test*"], "condition": "selection"} + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + detection = {"selection": ["test?"], "condition": "selection"} + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + detection = {"selection": ["test\\"], "condition": "selection"} + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + + # fts is not implemented for nested condtions + detection = {"selection": ["test"], "filter": [ + "test2"], "condition": "selection and filter"} # this is ok + detection = {"selection": ["test"], "filter": [ + "test2"], "condition": "selection or filter"} # this is ok + detection = {"selection": ["test"], "filter": [ + "test2"], "condition": "selection and not filter"} # this is already nested + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + detection = {"selection": ["test"], "filter": [ + "test2"], "condition": "selection and filter and filter"} # this is nested + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + detection = {"selection": ["test"], "filter": [ + "test2"], "condition": "selection and filter or filter"} # this is nested + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + def validate(self, detection, expectation): + + config = SigmaConfiguration() + + self.basic_rule["detection"] = detection + + with patch("yaml.safe_load_all", return_value=[self.basic_rule]): + parser = SigmaCollectionParser("any sigma io", config, None) + backend = SQLiteBackend(config, self.table) + + assert len(parser.parsers) == 1 + + for p in parser.parsers: + if isinstance(expectation, str): + self.assertEqual(expectation.lower(), + backend.generate(p).lower()) + elif isinstance(expectation, Exception): + self.assertRaises(type(expectation), backend.generate, p) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file From abf1a2c6d7eb6a031fcb60dd003fccf62bd7af33 Mon Sep 17 00:00:00 2001 From: Jonas Hagg Date: Mon, 25 May 2020 10:54:16 +0200 Subject: [PATCH 19/94] Adjusted Makefile --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 1d36cd90..79eba11e 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,7 @@ test-sigmac: $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t humio -O rulecomment -c tools/config/humio.yml rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t crowdstrike -O rulecomment -c tools/config/crowdstrike.yml rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t sql -c sysmon rules/ > /dev/null + $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t sqlite -c sysmon rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t logiq -c sysmon rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t splunk -c tools/config/splunk-windows-index.yml -f 'level>=high,level<=critical,status=stable,logsource=windows,tag=attack.execution' rules/ > /dev/null ! $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t splunk -c tools/config/splunk-windows-index.yml -f 'level>=high,level<=critical,status=xstable,logsource=windows' rules/ > /dev/null From 48c5f2ed094ead20bd7b94786530e0583e0d5323 Mon Sep 17 00:00:00 2001 From: Remco Hofman Date: Tue, 26 May 2020 11:20:21 +0200 Subject: [PATCH 20/94] Update to sysmon_cve-2020-1048 Added .com executables to detection Second TargetObject should have been Details --- rules/windows/sysmon/sysmon_cve-2020-1048.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rules/windows/sysmon/sysmon_cve-2020-1048.yml b/rules/windows/sysmon/sysmon_cve-2020-1048.yml index 866b7775..9c671ad3 100644 --- a/rules/windows/sysmon/sysmon_cve-2020-1048.yml +++ b/rules/windows/sysmon/sysmon_cve-2020-1048.yml @@ -2,9 +2,9 @@ title: Suspicious New Printer Ports in Registry (CVE-2020-1048) id: 7ec912f2-5175-4868-b811-ec13ad0f8567 status: experimental description: Detects a new and suspicious printer port creation in Registry that could be an attempt to exploit CVE-2020-1048 -author: EagleEye Team, Florian Roth +author: EagleEye Team, Florian Roth, NVISO date: 2020/05/13 -modified: 2020/05/23 +modified: 2020/05/26 references: - https://windows-internals.com/printdemon-cve-2020-1048/ tags: @@ -23,10 +23,11 @@ detection: - SetValue - DeleteValue - CreateValue - TargetObject|contains: + Details|contains: - '.dll' - '.exe' - '.bat' + - '.com' - 'C:' condition: selection falsepositives: From a241792e1077be912087c0f22a735e427d9d43ab Mon Sep 17 00:00:00 2001 From: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Tue, 26 May 2020 12:58:15 +0200 Subject: [PATCH 21/94] Reduce FP of legitime processes A lot of Windows apps does not have any file characteristics. Some examples: - Gamebar: C:\\Program Files\\WindowsApps\\Microsoft.XboxGamingOverlay_3.38.25003.0_x64__8wekyb3d8bbwe\\GameBarFT.exe - YourPhone: C:\\Program Files\\WindowsApps\\Microsoft.YourPhone_1.20022.82.0_x64__8wekyb3d8bbwe\\YourPhoneServer/YourPhoneServer.exe All C:\Windows\System32\OpenSSH (scp, sftp, ssh etc) does not have a description and company. Python 2.7, 3.3 and 3.7 does not have any file characteristics. So I don't think it is possible to whitelist all options, maybe it is worthwhile to check the \Downloads\ folder otherwise it would be better to just delete the rule. All other suspicious folders are covered by /rules/windows/process_creation/win_susp_exec_folder.yml --- .../win_susp_file_characteristics.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/rules/windows/process_creation/win_susp_file_characteristics.yml b/rules/windows/process_creation/win_susp_file_characteristics.yml index 083ccf70..cfe3b7e3 100644 --- a/rules/windows/process_creation/win_susp_file_characteristics.yml +++ b/rules/windows/process_creation/win_susp_file_characteristics.yml @@ -1,13 +1,13 @@ -title: Suspicious File Characteristics Due to Missing Fields +title: Suspicious File Characteristics Due to Missing Fields in Downloads folder id: 9637e8a5-7131-4f7f-bdc7-2b05d8670c43 -description: Detects Executables without FileVersion,Description,Product,Company likely created with py2exe +description: Detects Executables in the Downloads folder without FileVersion,Description,Product,Company likely created with py2exe status: experimental references: - https://securelist.com/muddywater/88059/ - https://www.virustotal.com/#/file/276a765a10f98cda1a38d3a31e7483585ca3722ecad19d784441293acf1b7beb/detection -author: Markus Neis +author: Markus Neis, Sander Wiebing date: 2018/11/22 -modified: 2019/11/09 +modified: 2020/05/26 tags: - attack.defense_evasion - attack.execution @@ -25,7 +25,9 @@ detection: selection3: Description: '\?' Company: '\?' - condition: 1 of them + folder: + Image: '*\Downloads\\*' + condition: (selection1 or selection2 or selection3) and folder fields: - CommandLine - ParentCommandLine From f9f814f3b3d927a31a9e7703f03e4bd6e28f8e05 Mon Sep 17 00:00:00 2001 From: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Tue, 26 May 2020 13:06:27 +0200 Subject: [PATCH 22/94] Shortened title --- .../windows/process_creation/win_susp_file_characteristics.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/windows/process_creation/win_susp_file_characteristics.yml b/rules/windows/process_creation/win_susp_file_characteristics.yml index cfe3b7e3..8243fe88 100644 --- a/rules/windows/process_creation/win_susp_file_characteristics.yml +++ b/rules/windows/process_creation/win_susp_file_characteristics.yml @@ -1,4 +1,4 @@ -title: Suspicious File Characteristics Due to Missing Fields in Downloads folder +title: Suspicious File Characteristics Due to Missing Fields id: 9637e8a5-7131-4f7f-bdc7-2b05d8670c43 description: Detects Executables in the Downloads folder without FileVersion,Description,Product,Company likely created with py2exe status: experimental From 3681b8cb56144248ed57afdb31ce748d01190a0b Mon Sep 17 00:00:00 2001 From: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Tue, 26 May 2020 13:56:51 +0200 Subject: [PATCH 23/94] Extended Windows processes --- rules/windows/process_creation/win_system_exe_anomaly.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rules/windows/process_creation/win_system_exe_anomaly.yml b/rules/windows/process_creation/win_system_exe_anomaly.yml index da242270..809970e8 100644 --- a/rules/windows/process_creation/win_system_exe_anomaly.yml +++ b/rules/windows/process_creation/win_system_exe_anomaly.yml @@ -30,6 +30,13 @@ detection: - '*\winlogon.exe' - '*\explorer.exe' - '*\taskhost.exe' + - '*\Taskmgr.exe' + - '*\sihost.exe' + - '*\RuntimeBroker.exe' + - '*\smartscreen.exe' + - '*\dllhost.exe' + - '*\audiodg.exe' + - '*\wlanext.exe' filter: Image: - 'C:\Windows\System32\\*' From f6ec724d51b9feb83ce903c6c6398f9c143b9bd4 Mon Sep 17 00:00:00 2001 From: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Tue, 26 May 2020 18:53:54 +0200 Subject: [PATCH 24/94] Rule: sysmon_creation_system_file --- .../sysmon/sysmon_creation_system_file | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 rules/windows/sysmon/sysmon_creation_system_file diff --git a/rules/windows/sysmon/sysmon_creation_system_file b/rules/windows/sysmon/sysmon_creation_system_file new file mode 100644 index 00000000..3744a10a --- /dev/null +++ b/rules/windows/sysmon/sysmon_creation_system_file @@ -0,0 +1,57 @@ +title: File Created with System Process Name +id: d5866ddf-ce8f-4aea-b28e-d96485a20d3d +status: experimental +description: Detects the creation of a executable with a sytem process name in a suspicious folder +references: + - https://attack.mitre.org/techniques/T1036/ +author: Sander Wiebing +date: 2020/05/26 +tags: + - attack.defense_evasion + - attack.t1036 +logsource: + product: windows + service: sysmon +detection: + selection: + EventID: 11 + Image: + - '*\svchost.exe' + - '*\rundll32.exe' + - '*\services.exe' + - '*\powershell.exe' + - '*\regsvr32.exe' + - '*\spoolsv.exe' + - '*\lsass.exe' + - '*\smss.exe' + - '*\csrss.exe' + - '*\conhost.exe' + - '*\wininit.exe' + - '*\lsm.exe' + - '*\winlogon.exe' + - '*\explorer.exe' + - '*\taskhost.exe' + - '*\Taskmgr.exe' + - '*\taskmgr.exe' + - '*\sihost.exe' + - '*\RuntimeBroker.exe' + - '*\runtimebroker.exe' + - '*\smartscreen.exe' + - '*\dllhost.exe' + - '*\audiodg.exe' + - '*\wlanext.exe' + filter: + Image: + - 'C:\Windows\System32\\*' + - 'C:\Windows\system32\\*' + - 'C:\Windows\SysWow64\\*' + - 'C:\Windows\SysWOW64\\*' + - 'C:\Windows\winsxs\\*' + - 'C:\Windows\WinSxS\\*' + - '\SystemRoot\System32\\*' + condition: selection and not filter +fields: + - Image +falsepositives: + - System processes copied outside the default folder +level: high From d44fc43c5452e4e62b5dcf990139a4e166dda706 Mon Sep 17 00:00:00 2001 From: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Tue, 26 May 2020 19:10:11 +0200 Subject: [PATCH 25/94] Add extension --- ...ysmon_creation_system_file => sysmon_creation_system_file.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename rules/windows/sysmon/{sysmon_creation_system_file => sysmon_creation_system_file.yml} (100%) diff --git a/rules/windows/sysmon/sysmon_creation_system_file b/rules/windows/sysmon/sysmon_creation_system_file.yml similarity index 100% rename from rules/windows/sysmon/sysmon_creation_system_file rename to rules/windows/sysmon/sysmon_creation_system_file.yml From 5a489348224307685cf63bb0cdd7d8b7288d5fc7 Mon Sep 17 00:00:00 2001 From: gamma37 Date: Thu, 28 May 2020 10:52:17 +0200 Subject: [PATCH 26/94] Edit Clear Command History I suggest a new point of view to detect that bash_history has been cleared : Instead of trying to detect all the commands that can do that, we could monitor the size of the file and log whenever it has less than 1 line. --- rules/linux/lnx_shell_clear_cmd_history.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/rules/linux/lnx_shell_clear_cmd_history.yml b/rules/linux/lnx_shell_clear_cmd_history.yml index 9ee72f09..d48bc425 100644 --- a/rules/linux/lnx_shell_clear_cmd_history.yml +++ b/rules/linux/lnx_shell_clear_cmd_history.yml @@ -2,12 +2,20 @@ title: Clear Command History id: fdc88d25-96fb-4b7c-9633-c0e417fdbd4e status: experimental description: Clear command history in linux which is used for defense evasion. + # Example config for this one (place it in .bash_profile): + # (is_empty=false; inotifywait -m .bash_history | while read file; do if [ $(wc -l <.bash_history) -lt 1 ]; then if [ "$is_empty" = false ]; then logger -i -p local5.info -t empty_bash_history "$USER : ~/.bash_history is empty "; is_empty=true; fi; else is_empty=false; fi; done ) & + # It monitors the size of .bash_history and log the words "empty_bash_history" whenever a previously not empty bash_history becomes empty + # We define an empty file as a document with 0 or 1 lines (it can be a line with only one space character for example) + # It has two advantages over the version suggested by Patrick Bareiss : + # - it is not relative to the exact command used to clear .bash_history : for instance Caldera uses "> .bash_history" to clear the history and this is not one the commands listed here. We can't be exhaustive for all the possibilities ! + # - the method suggested by Patrick Bareiss logs all the commands entered directly in a bash shell. therefore it may miss some events (for instance it doesn't log the commands launched from a Caldera agent). Here if .bash_history is cleared, it will always be detected references: - https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1146/T1146.yaml - https://attack.mitre.org/techniques/T1146/ - https://www.hackers-arise.com/single-post/2016/06/20/Covering-your-BASH-Shell-Tracks-AntiForensics author: Patrick Bareiss date: 2019/03/24 +modified : 2020/05/28 logsource: product: linux detection: @@ -22,6 +30,7 @@ detection: - 'history -c' - 'history -w' - 'shred *bash_history' + - 'empty_bash_history' condition: keywords falsepositives: - Unknown From 537bda4417ef90f5af9c754d3b0d965c79103cb0 Mon Sep 17 00:00:00 2001 From: gamma37 Date: Thu, 28 May 2020 10:56:35 +0200 Subject: [PATCH 27/94] Update lnx_shell_clear_cmd_history.yml --- rules/linux/lnx_shell_clear_cmd_history.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/linux/lnx_shell_clear_cmd_history.yml b/rules/linux/lnx_shell_clear_cmd_history.yml index d48bc425..97379f6a 100644 --- a/rules/linux/lnx_shell_clear_cmd_history.yml +++ b/rules/linux/lnx_shell_clear_cmd_history.yml @@ -15,7 +15,7 @@ references: - https://www.hackers-arise.com/single-post/2016/06/20/Covering-your-BASH-Shell-Tracks-AntiForensics author: Patrick Bareiss date: 2019/03/24 -modified : 2020/05/28 +modified: 2020/05/28 logsource: product: linux detection: From 38afd8b5def24191616ff0f0c0324cfbb7f0d6d0 Mon Sep 17 00:00:00 2001 From: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Thu, 28 May 2020 21:52:17 +0200 Subject: [PATCH 28/94] Fixed wrong field --- rules/windows/sysmon/sysmon_creation_system_file.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/windows/sysmon/sysmon_creation_system_file.yml b/rules/windows/sysmon/sysmon_creation_system_file.yml index 3744a10a..f322669c 100644 --- a/rules/windows/sysmon/sysmon_creation_system_file.yml +++ b/rules/windows/sysmon/sysmon_creation_system_file.yml @@ -15,7 +15,7 @@ logsource: detection: selection: EventID: 11 - Image: + TargetFilename: - '*\svchost.exe' - '*\rundll32.exe' - '*\services.exe' @@ -41,7 +41,7 @@ detection: - '*\audiodg.exe' - '*\wlanext.exe' filter: - Image: + TargetFilename: - 'C:\Windows\System32\\*' - 'C:\Windows\system32\\*' - 'C:\Windows\SysWow64\\*' From a00f7f19a14b58ab9ca98f6a4215a3ca9eb1932a Mon Sep 17 00:00:00 2001 From: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Fri, 29 May 2020 16:25:54 +0200 Subject: [PATCH 29/94] Add tagg Endswith Prevent the trigger of {}.exe.log --- rules/windows/sysmon/sysmon_creation_system_file.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/windows/sysmon/sysmon_creation_system_file.yml b/rules/windows/sysmon/sysmon_creation_system_file.yml index f322669c..9f8143c8 100644 --- a/rules/windows/sysmon/sysmon_creation_system_file.yml +++ b/rules/windows/sysmon/sysmon_creation_system_file.yml @@ -15,7 +15,7 @@ logsource: detection: selection: EventID: 11 - TargetFilename: + TargetFilename|endswith: - '*\svchost.exe' - '*\rundll32.exe' - '*\services.exe' From 70935d26ce214b566b34c4555531e0510a619a99 Mon Sep 17 00:00:00 2001 From: Jonas Plum Date: Fri, 29 May 2020 23:56:05 +0200 Subject: [PATCH 30/94] Add license header --- Makefile | 5 +- tools/sigma/backends/sql.py | 23 ++--- tools/sigma/backends/sqlite.py | 15 ++++ tools/tests/test_backend_sql.py | 138 ++++++++++++++++------------- tools/tests/test_backend_sqlite.py | 47 ++++++---- 5 files changed, 138 insertions(+), 90 deletions(-) diff --git a/Makefile b/Makefile index 79eba11e..2766a7e7 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ TMPOUT = $(shell tempfile||mktemp) COVSCOPE = tools/sigma/*.py,tools/sigma/backends/*.py,tools/sigmac,tools/merge_sigma,tools/sigma2attack export COVERAGE = coverage -test: clearcov test-rules test-sigmac test-merge test-sigma2attack build finish +test: clearcov test-rules test-sigmac test-merge test-backend-sql test-sigma2attack build finish clearcov: rm -f .coverage @@ -108,6 +108,9 @@ test-merge: test-backend-es-qs: tests/test-backend-es-qs.py +test-backend-sql: + pytest tests/test_backend_sql.py tests/test_backend_sqlite.py + test-sigma2attack: $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigma2attack diff --git a/tools/sigma/backends/sql.py b/tools/sigma/backends/sql.py index 72f7cc29..7ea27c76 100644 --- a/tools/sigma/backends/sql.py +++ b/tools/sigma/backends/sql.py @@ -1,5 +1,6 @@ # Output backends for sigmac # Copyright 2019 Jayden Zheng +# Copyright 2020 Jonas Hagg # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by @@ -36,7 +37,7 @@ class SQLBackend(SingleTextQueryBackend): notNullExpression = "%s=*" # Expression of queries for not null values. %s is field name mapExpression = "%s = %s" # Syntax for field/value conditions. First %s is fieldname, second is value mapMulti = "%s IN %s" # Syntax for field/value conditions. First %s is fieldname, second is value - mapWildcard = "%s LIKE %s escape \'\\\'"# Syntax for swapping wildcard conditions: Adding \ as escape character + mapWildcard = "%s LIKE %s ESCAPE \'\\\'"# Syntax for swapping wildcard conditions: Adding \ as escape character mapSource = "%s=%s" # Syntax for sourcetype mapListsSpecialHandling = False # Same handling for map items with list values as for normal values (strings, integers) if True, generateMapItemListNode method is called with node mapListValueExpression = "%s OR %s" # Syntax for field/value condititons where map value is a list @@ -87,13 +88,13 @@ class SQLBackend(SingleTextQueryBackend): has_wildcard = re.search(r"((\\(\*|\?|\\))|\*|\?|_|%)", self.generateNode(value)) - if "," in self.generateNode(value) and not has_wildcard: + if "," in self.generateNode(value) and not has_wildcard: return self.mapMulti % (transformed_fieldname, self.generateNode(value)) elif "LENGTH" in transformed_fieldname: return self.mapLength % (transformed_fieldname, value) elif type(value) == list: return self.generateMapItemListNode(transformed_fieldname, value) - elif self.mapListsSpecialHandling == False and type(value) in (str, int, list) or self.mapListsSpecialHandling == True and type(value) in (str, int): + elif self.mapListsSpecialHandling == False and type(value) in (str, int, list) or self.mapListsSpecialHandling == True and type(value) in (str, int): if has_wildcard: return self.mapWildcard % (transformed_fieldname, self.generateNode(value)) else: @@ -107,7 +108,7 @@ class SQLBackend(SingleTextQueryBackend): def generateMapItemListNode(self, key, value): return "(" + (" OR ".join([self.mapWildcard % (key, self.generateValueNode(item)) for item in value])) + ")" - + def generateValueNode(self, node): return self.valueExpression % (self.cleanValue(str(node))) @@ -144,11 +145,11 @@ class SQLBackend(SingleTextQueryBackend): #Replace ? with _, if even number of backsashes (or zero) in front of ? val = re.sub(r"(?. from sigma.backends.sql import SQLBackend from sigma.parser.condition import NodeSubexpression, ConditionAND, ConditionOR, ConditionNOT diff --git a/tools/tests/test_backend_sql.py b/tools/tests/test_backend_sql.py index c1a9b38b..b4bd8202 100644 --- a/tools/tests/test_backend_sql.py +++ b/tools/tests/test_backend_sql.py @@ -1,3 +1,19 @@ +# Test output backends for sigmac +# Copyright 2020 Jonas Hagg + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + import unittest from unittest.mock import patch @@ -17,60 +33,60 @@ class TestGenerateQuery(unittest.TestCase): # Test regular queries detection = {"selection": {"fieldname": "test1"}, "condition": "selection"} - expected_result = 'select * from {} where fieldname = "test1"'.format( + expected_result = 'SELECT * FROM {} WHERE fieldname = "test1"'.format( self.table) self.validate(detection, expected_result) detection = {"selection": {"fieldname": 4}, "condition": "selection"} - expected_result = 'select * from {} where fieldname = "4"'.format( + expected_result = 'SELECT * FROM {} WHERE fieldname = "4"'.format( self.table) self.validate(detection, expected_result) detection = {"selection": {"fieldname": [ "test1", "test2"]}, "condition": "selection"} - expected_result = 'select * from {} where fieldname in ("test1", "test2")'.format( + expected_result = 'SELECT * FROM {} WHERE fieldname IN ("test1", "test2")'.format( self.table) self.validate(detection, expected_result) detection = {"selection": { "fieldname": [3, 4]}, "condition": "selection"} - expected_result = 'select * from {} where fieldname in ("3", "4")'.format( + expected_result = 'SELECT * FROM {} WHERE fieldname IN ("3", "4")'.format( self.table) self.validate(detection, expected_result) detection = {"selection": {"fieldname1": "test1", "fieldname2": [ "test2", "test3"]}, "condition": "selection"} - expected_result = 'select * from {} where (fieldname1 = "test1" and fieldname2 in ("test2", "test3"))'.format( + expected_result = 'SELECT * FROM {} WHERE (fieldname1 = "test1" AND fieldname2 IN ("test2", "test3"))'.format( self.table) self.validate(detection, expected_result) detection = {"selection": {"fieldname": "test1"}, "filter": { "fieldname2": "whatever"}, "condition": "selection and filter"} - expected_result = 'select * from {} where (fieldname = "test1" and fieldname2 = "whatever")'.format( + expected_result = 'SELECT * FROM {} WHERE (fieldname = "test1" AND fieldname2 = "whatever")'.format( self.table) self.validate(detection, expected_result) detection = {"selection": {"fieldname": "test1"}, "filter": { "fieldname2": "whatever"}, "condition": "selection or filter"} - expected_result = 'select * from {} where (fieldname = "test1" or fieldname2 = "whatever")'.format( + expected_result = 'SELECT * FROM {} WHERE (fieldname = "test1" OR fieldname2 = "whatever")'.format( self.table) self.validate(detection, expected_result) detection = {"selection": {"fieldname": "test1"}, "filter": { "fieldname2": "whatever"}, "condition": "selection and not filter"} - expected_result = 'select * from {} where (fieldname = "test1" and not (fieldname2 = "whatever"))'.format( + expected_result = 'SELECT * FROM {} WHERE (fieldname = "test1" AND NOT (fieldname2 = "whatever"))'.format( self.table) self.validate(detection, expected_result) detection = {"selection": {"fieldname1": "test1"}, "filter": { "fieldname2": "test2"}, "condition": "1 of them"} - expected_result = 'select * from {} where (fieldname1 = "test1" or fieldname2 = "test2")'.format( + expected_result = 'SELECT * FROM {} WHERE (fieldname1 = "test1" OR fieldname2 = "test2")'.format( self.table) self.validate(detection, expected_result) detection = {"selection": {"fieldname1": "test1"}, "filter": { "fieldname2": "test2"}, "condition": "all of them"} - expected_result = 'select * from {} where (fieldname1 = "test1" and fieldname2 = "test2")'.format( + expected_result = 'SELECT * FROM {} WHERE (fieldname1 = "test1" AND fieldname2 = "test2")'.format( self.table) self.validate(detection, expected_result) @@ -79,28 +95,28 @@ class TestGenerateQuery(unittest.TestCase): # contains detection = {"selection": {"fieldname|contains": "test"}, "condition": "selection"} - expected_result = 'select * from {} where fieldname like "%test%" escape \'\\\''.format( + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE "%test%" ESCAPE \'\\\''.format( self.table) self.validate(detection, expected_result) # all detection = {"selection": {"fieldname|all": [ "test1", "test2"]}, "condition": "selection"} - expected_result = 'select * from {} where (fieldname = "test1" and fieldname = "test2")'.format( + expected_result = 'SELECT * FROM {} WHERE (fieldname = "test1" AND fieldname = "test2")'.format( self.table) self.validate(detection, expected_result) # endswith detection = {"selection": {"fieldname|endswith": "test"}, "condition": "selection"} - expected_result = 'select * from {} where fieldname like "%test" escape \'\\\''.format( + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE "%test" ESCAPE \'\\\''.format( self.table) self.validate(detection, expected_result) # startswith detection = {"selection": {"fieldname|startswith": "test"}, "condition": "selection"} - expected_result = 'select * from {} where fieldname like "test%" escape \'\\\''.format( + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE "test%" ESCAPE \'\\\''.format( self.table) self.validate(detection, expected_result) @@ -109,73 +125,73 @@ class TestGenerateQuery(unittest.TestCase): # count detection = {"selection": {"fieldname": "test"}, "condition": "selection | count() > 5"} - inner_query = 'select count(*) as agg from {} where fieldname = "test"'.format( + inner_query = 'SELECT count(*) AS agg FROM {} WHERE fieldname = "test"'.format( self.table) - expected_result = 'select * from ({}) where agg > 5'.format(inner_query) + expected_result = 'SELECT * FROM ({}) WHERE agg > 5'.format(inner_query) self.validate(detection, expected_result) # min detection = {"selection": {"fieldname1": "test"}, "condition": "selection | min(fieldname2) > 5"} - inner_query = 'select min(fieldname2) as agg from {} where fieldname1 = "test"'.format( + inner_query = 'SELECT min(fieldname2) AS agg FROM {} WHERE fieldname1 = "test"'.format( self.table) - expected_result = 'select * from ({}) where agg > 5'.format(inner_query) + expected_result = 'SELECT * FROM ({}) WHERE agg > 5'.format(inner_query) self.validate(detection, expected_result) # max detection = {"selection": {"fieldname1": "test"}, "condition": "selection | max(fieldname2) > 5"} - inner_query = 'select max(fieldname2) as agg from {} where fieldname1 = "test"'.format( + inner_query = 'SELECT max(fieldname2) AS agg FROM {} WHERE fieldname1 = "test"'.format( self.table) - expected_result = 'select * from ({}) where agg > 5'.format(inner_query) + expected_result = 'SELECT * FROM ({}) WHERE agg > 5'.format(inner_query) self.validate(detection, expected_result) # avg detection = {"selection": {"fieldname1": "test"}, "condition": "selection | avg(fieldname2) > 5"} - inner_query = 'select avg(fieldname2) as agg from {} where fieldname1 = "test"'.format( + inner_query = 'SELECT avg(fieldname2) AS agg FROM {} WHERE fieldname1 = "test"'.format( self.table) - expected_result = 'select * from ({}) where agg > 5'.format(inner_query) + expected_result = 'SELECT * FROM ({}) WHERE agg > 5'.format(inner_query) self.validate(detection, expected_result) # sum detection = {"selection": {"fieldname1": "test"}, "condition": "selection | sum(fieldname2) > 5"} - inner_query = 'select sum(fieldname2) as agg from {} where fieldname1 = "test"'.format( + inner_query = 'SELECT sum(fieldname2) AS agg FROM {} WHERE fieldname1 = "test"'.format( self.table) - expected_result = 'select * from ({}) where agg > 5'.format(inner_query) + expected_result = 'SELECT * FROM ({}) WHERE agg > 5'.format(inner_query) self.validate(detection, expected_result) # < detection = {"selection": {"fieldname1": "test"}, "condition": "selection | sum(fieldname2) < 5"} - inner_query = 'select sum(fieldname2) as agg from {} where fieldname1 = "test"'.format( + inner_query = 'SELECT sum(fieldname2) AS agg FROM {} WHERE fieldname1 = "test"'.format( self.table) - expected_result = 'select * from ({}) where agg < 5'.format(inner_query) + expected_result = 'SELECT * FROM ({}) WHERE agg < 5'.format(inner_query) self.validate(detection, expected_result) # == detection = {"selection": {"fieldname1": "test"}, "condition": "selection | sum(fieldname2) == 5"} - inner_query = 'select sum(fieldname2) as agg from {} where fieldname1 = "test"'.format( + inner_query = 'SELECT sum(fieldname2) AS agg FROM {} WHERE fieldname1 = "test"'.format( self.table) - expected_result = 'select * from ({}) where agg == 5'.format(inner_query) + expected_result = 'SELECT * FROM ({}) WHERE agg == 5'.format(inner_query) self.validate(detection, expected_result) # group by detection = {"selection": {"fieldname1": "test"}, "condition": "selection | sum(fieldname2) by fieldname3 == 5"} - inner_query = 'select sum(fieldname2) as agg from {} where fieldname1 = "test" group by fieldname3'.format( + inner_query = 'SELECT sum(fieldname2) AS agg FROM {} WHERE fieldname1 = "test" GROUP BY fieldname3'.format( self.table) - expected_result = 'select * from ({}) where agg == 5'.format(inner_query) + expected_result = 'SELECT * FROM ({}) WHERE agg == 5'.format(inner_query) self.validate(detection, expected_result) # multiple conditions detection = {"selection": {"fieldname1": "test"}, "filter": { - "fieldname2": "tessst"}, "condition": "selection or filter | sum(fieldname2) == 5"} - inner_query = 'select sum(fieldname2) as agg from {} where (fieldname1 = "test" or fieldname2 = "tessst")'.format( + "fieldname2": "tessst"}, "condition": "selection OR filter | sum(fieldname2) == 5"} + inner_query = 'SELECT sum(fieldname2) AS agg FROM {} WHERE (fieldname1 = "test" OR fieldname2 = "tessst")'.format( self.table) - expected_result = 'select * from ({}) where agg == 5'.format(inner_query) + expected_result = 'SELECT * FROM ({}) WHERE agg == 5'.format(inner_query) self.validate(detection, expected_result) def test_wildcards(self): @@ -183,81 +199,81 @@ class TestGenerateQuery(unittest.TestCase): # wildcard: * detection = {"selection": {"fieldname": "test*"}, "condition": "selection"} - expected_result = 'select * from {} where fieldname like '.format( - self.table) + r'"test%"' + r" escape '\'" + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test%"' + r" ESCAPE '\'" self.validate(detection, expected_result) # wildcard: ? detection = {"selection": {"fieldname": "test?"}, "condition": "selection"} - expected_result = 'select * from {} where fieldname like '.format( - self.table) + r'"test_"' + r" escape '\'" + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test_"' + r" ESCAPE '\'" self.validate(detection, expected_result) # escaping: detection = {"selection": {"fieldname": r"test\?"}, "condition": "selection"} - expected_result = 'select * from {} where fieldname like '.format( - self.table) + r'"test\?"' + r" escape '\'" + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test\?"' + r" ESCAPE '\'" self.validate(detection, expected_result) detection = {"selection": {"fieldname": r"test\\*"}, "condition": "selection"} - expected_result = 'select * from {} where fieldname like '.format( - self.table) + r'"test\\%"' + r" escape '\'" + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test\\%"' + r" ESCAPE '\'" self.validate(detection, expected_result) detection = {"selection": {"fieldname": r"test\*"}, "condition": "selection"} - expected_result = 'select * from {} where fieldname like '.format( - self.table) + r'"test\*"' + r" escape '\'" + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test\*"' + r" ESCAPE '\'" self.validate(detection, expected_result) detection = {"selection": {"fieldname": r"test\\"}, "condition": "selection"} - expected_result = 'select * from {} where fieldname like '.format( - self.table) + r'"test\\"' + r" escape '\'" + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test\\"' + r" ESCAPE '\'" self.validate(detection, expected_result) detection = {"selection": {"fieldname": r"test\abc"}, "condition": "selection"} - expected_result = 'select * from {} where fieldname like '.format( - self.table) + r'"test\\abc"' + r" escape '\'" + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test\\abc"' + r" ESCAPE '\'" self.validate(detection, expected_result) detection = {"selection": {"fieldname": r"test%"}, "condition": "selection"} - expected_result = 'select * from {} where fieldname like '.format( - self.table) + r'"test\%"' + r" escape '\'" + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test\%"' + r" ESCAPE '\'" self.validate(detection, expected_result) detection = {"selection": {"fieldname": r"test_"}, "condition": "selection"} - expected_result = 'select * from {} where fieldname like '.format( - self.table) + r'"test\_"' + r" escape '\'" + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test\_"' + r" ESCAPE '\'" self.validate(detection, expected_result) # multiple options detection = {"selection": {"fieldname": [ "test*", "*test"]}, "condition": "selection"} - opt1 = 'fieldname like ' + r'"test%"' + r" escape '\'" - opt2 = 'fieldname like ' + r'"%test"' + r" escape '\'" - expected_result = 'select * from {} where ({} or {})'.format( + opt1 = 'fieldname LIKE ' + r'"test%"' + r" ESCAPE '\'" + opt2 = 'fieldname LIKE ' + r'"%test"' + r" ESCAPE '\'" + expected_result = 'SELECT * FROM {} WHERE ({} OR {})'.format( self.table, opt1, opt2) self.validate(detection, expected_result) detection = {"selection": {"fieldname|all": [ "test*", "*test"]}, "condition": "selection"} - opt1 = 'fieldname like ' + r'"test%"' + r" escape '\'" - opt2 = 'fieldname like ' + r'"%test"' + r" escape '\'" - expected_result = 'select * from {} where ({} and {})'.format( + opt1 = 'fieldname LIKE ' + r'"test%"' + r" ESCAPE '\'" + opt2 = 'fieldname LIKE ' + r'"%test"' + r" ESCAPE '\'" + expected_result = 'SELECT * FROM {} WHERE ({} AND {})'.format( self.table, opt1, opt2) self.validate(detection, expected_result) def test_fieldname_mapping(self): detection = {"selection": {"fieldname": "test1"}, "condition": "selection"} - expected_result = 'select * from {} where mapped_fieldname = "test1"'.format( + expected_result = 'SELECT * FROM {} WHERE mapped_fieldname = "test1"'.format( self.table) # configure mapping @@ -274,8 +290,7 @@ class TestGenerateQuery(unittest.TestCase): assert len(parser.parsers) == 1 for p in parser.parsers: - self.assertEqual(expected_result.lower(), - backend.generate(p).lower()) + self.assertEqual(expected_result, backend.generate(p)) def test_not_implemented(self): # near aggregation not implemented @@ -310,8 +325,7 @@ class TestGenerateQuery(unittest.TestCase): for p in parser.parsers: if isinstance(expectation, str): - self.assertEqual(expectation.lower(), - backend.generate(p).lower()) + self.assertEqual(expectation, backend.generate(p)) elif isinstance(expectation, Exception): self.assertRaises(type(expectation), backend.generate, p) diff --git a/tools/tests/test_backend_sqlite.py b/tools/tests/test_backend_sqlite.py index 3c6a7a71..66fc6812 100644 --- a/tools/tests/test_backend_sqlite.py +++ b/tools/tests/test_backend_sqlite.py @@ -1,3 +1,19 @@ +# Test output backends for sigmac +# Copyright 2020 Jonas Hagg + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + import unittest from unittest.mock import patch @@ -15,39 +31,39 @@ class TestFullTextSearch(unittest.TestCase): def test_full_text_search(self): detection = {"selection": ["test1"], "condition": "selection"} - expected_result = 'select * from {0} where {0} match (\'"test1"\')'.format( + expected_result = 'SELECT * FROM {0} WHERE {0} MATCH (\'"test1"\')'.format( self.table) self.validate(detection, expected_result) detection = {"selection": [5], "condition": "selection"} - expected_result = 'select * from {0} where {0} match (\'"5"\')'.format( + expected_result = 'SELECT * FROM {0} WHERE {0} MATCH (\'"5"\')'.format( self.table) self.validate(detection, expected_result) detection = {"selection": ["test1", "test2"], "condition": "selection"} - expected_result = 'select * from {0} where ({0} match (\'"test1" OR "test2"\'))'.format( + expected_result = 'SELECT * FROM {0} WHERE ({0} MATCH (\'"test1" OR "test2"\'))'.format( self.table) self.validate(detection, expected_result) detection = {"selection": ["test1"], "filter":["test2"], "condition": "selection and filter"} - expected_result = 'select * from {0} where ({0} match (\'"test1" and "test2"\'))'.format( + expected_result = 'SELECT * FROM {0} WHERE ({0} MATCH (\'"test1" AND "test2"\'))'.format( self.table) self.validate(detection, expected_result) detection = {"selection": [5, 6], "condition": "selection"} - expected_result = 'select * from {0} where ({0} match (\'"5" OR "6"\'))'.format( + expected_result = 'SELECT * FROM {0} WHERE ({0} MATCH (\'"5" OR "6"\'))'.format( self.table) self.validate(detection, expected_result) detection = {"selection": ["test1"], "filter": [ "test2"], "condition": "selection or filter"} - expected_result = 'select * from {0} where ({0} match (\'"test1" OR "test2"\'))'.format( + expected_result = 'SELECT * FROM {0} WHERE ({0} MATCH (\'"test1" OR "test2"\'))'.format( self.table) self.validate(detection, expected_result) detection = {"selection": ["test1"], "filter": [ "test2"], "condition": "selection and filter"} - expected_result = 'select * from {0} where ({0} match (\'"test1" and "test2"\'))'.format( + expected_result = 'SELECT * FROM {0} WHERE ({0} MATCH (\'"test1" AND "test2"\'))'.format( self.table) self.validate(detection, expected_result) @@ -55,26 +71,26 @@ class TestFullTextSearch(unittest.TestCase): # aggregation with fts detection = {"selection": ["test"], "condition": "selection | count() > 5"} - inner_query = 'select count(*) as agg from {0} where {0} match (\'"test"\')'.format( + inner_query = 'SELECT count(*) AS agg FROM {0} WHERE {0} MATCH (\'"test"\')'.format( self.table) - expected_result = 'select * from ({}) where agg > 5'.format(inner_query) + expected_result = 'SELECT * FROM ({}) WHERE agg > 5'.format(inner_query) self.validate(detection, expected_result) detection = {"selection": ["test1", "test2"], "condition": "selection | count() > 5"} - inner_query = 'select count(*) as agg from {0} where ({0} match (\'"test1" or "test2"\'))'.format( + inner_query = 'SELECT count(*) AS agg FROM {0} WHERE ({0} MATCH (\'"test1" OR "test2"\'))'.format( self.table) - expected_result = 'select * from ({}) where agg > 5'.format(inner_query) + expected_result = 'SELECT * FROM ({}) WHERE agg > 5'.format(inner_query) self.validate(detection, expected_result) # aggregation + group by + fts detection = {"selection": ["test1", "test2"], "condition": "selection | count() by fieldname > 5"} - inner_query = 'select count(*) as agg from {0} where ({0} match (\'"test1" or "test2"\')) group by fieldname'.format( + inner_query = 'SELECT count(*) AS agg FROM {0} WHERE ({0} MATCH (\'"test1" OR "test2"\')) GROUP BY fieldname'.format( self.table) - expected_result = 'select * from ({}) where agg > 5'.format(inner_query) + expected_result = 'SELECT * FROM ({}) WHERE agg > 5'.format(inner_query) self.validate(detection, expected_result) - + def test_not_implemented(self): # fts not implemented with wildcards detection = {"selection": ["test*"], "condition": "selection"} @@ -124,8 +140,7 @@ class TestFullTextSearch(unittest.TestCase): for p in parser.parsers: if isinstance(expectation, str): - self.assertEqual(expectation.lower(), - backend.generate(p).lower()) + self.assertEqual(expectation, backend.generate(p)) elif isinstance(expectation, Exception): self.assertRaises(type(expectation), backend.generate, p) From 4a8ab88adecc4035aedb8b8780c29a76a31eca04 Mon Sep 17 00:00:00 2001 From: Jonas Plum Date: Sat, 30 May 2020 00:15:38 +0200 Subject: [PATCH 31/94] Fix test path --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2766a7e7..30e2fb99 100644 --- a/Makefile +++ b/Makefile @@ -109,7 +109,7 @@ test-backend-es-qs: tests/test-backend-es-qs.py test-backend-sql: - pytest tests/test_backend_sql.py tests/test_backend_sqlite.py + pytest tools/tests/test_backend_sql.py tools/tests/test_backend_sqlite.py test-sigma2attack: $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigma2attack From 5cc82d0f05b4a0ea6640f6bdc4fc0fe719945108 Mon Sep 17 00:00:00 2001 From: Jonas Plum Date: Sat, 30 May 2020 00:56:06 +0200 Subject: [PATCH 32/94] Move testcase --- .github/workflows/sigma-test.yml | 3 +++ Makefile | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sigma-test.yml b/.github/workflows/sigma-test.yml index b6e10159..ee0c317a 100644 --- a/.github/workflows/sigma-test.yml +++ b/.github/workflows/sigma-test.yml @@ -35,3 +35,6 @@ jobs: - name: Test Generated Elasticsearch Query Strings run: | make test-backend-es-qs + - name: Test SQL(ite) Backend + run: | + make test-backend-sql diff --git a/Makefile b/Makefile index 30e2fb99..5b2c7f17 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ TMPOUT = $(shell tempfile||mktemp) COVSCOPE = tools/sigma/*.py,tools/sigma/backends/*.py,tools/sigmac,tools/merge_sigma,tools/sigma2attack export COVERAGE = coverage -test: clearcov test-rules test-sigmac test-merge test-backend-sql test-sigma2attack build finish +test: clearcov test-rules test-sigmac test-merge test-sigma2attack build finish clearcov: rm -f .coverage @@ -109,7 +109,8 @@ test-backend-es-qs: tests/test-backend-es-qs.py test-backend-sql: - pytest tools/tests/test_backend_sql.py tools/tests/test_backend_sqlite.py + cd tools && python3 setup.py install + cd tools && python3 -m pytest tests/test_backend_sql.py tests/test_backend_sqlite.py test-sigma2attack: $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigma2attack From 3a6ac5bd5c711848b9e85b94741b210740cdada9 Mon Sep 17 00:00:00 2001 From: Jonas Plum Date: Sat, 30 May 2020 01:57:06 +0200 Subject: [PATCH 33/94] Remove unused function --- Makefile | 2 +- tools/sigma/backends/sql.py | 2 +- tools/sigma/backends/sqlite.py | 19 +------------------ 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index 5b2c7f17..e4968975 100644 --- a/Makefile +++ b/Makefile @@ -110,7 +110,7 @@ test-backend-es-qs: test-backend-sql: cd tools && python3 setup.py install - cd tools && python3 -m pytest tests/test_backend_sql.py tests/test_backend_sqlite.py + cd tools && $(COVERAGE) run -m pytest tests/test_backend_sql.py tests/test_backend_sqlite.py test-sigma2attack: $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigma2attack diff --git a/tools/sigma/backends/sql.py b/tools/sigma/backends/sql.py index 7ea27c76..5b446a6f 100644 --- a/tools/sigma/backends/sql.py +++ b/tools/sigma/backends/sql.py @@ -178,7 +178,7 @@ class SQLBackend(SingleTextQueryBackend): def generateQuery(self, parsed): if self._recursiveFtsSearch(parsed.parsedSearch): - raise NotImplementedError("FullTextSearch not implemented for SQL Backend, use SQLite Backend.") + raise NotImplementedError("FullTextSearch not implemented for SQL Backend.") result = self.generateNode(parsed.parsedSearch) if parsed.parsedAgg: diff --git a/tools/sigma/backends/sqlite.py b/tools/sigma/backends/sqlite.py index f29b0eb2..8eec13ea 100644 --- a/tools/sigma/backends/sqlite.py +++ b/tools/sigma/backends/sqlite.py @@ -20,7 +20,7 @@ import re class SQLiteBackend(SQLBackend): - """SQLiteBackend provides FullTextSearch functionality""" + """Converts Sigma rule into SQL query for SQLite""" identifier = "sqlite" active = True @@ -121,20 +121,3 @@ class SQLiteBackend(SQLBackend): return "SELECT * FROM {} WHERE {}".format(fro, whe) return "SELECT * FROM {} WHERE {}".format(self.table, result) - - def generateFullTextQuery(self, search, parsed): - - search = search.replace('"', '') - search = '" OR "'.join(search.split(" OR ")) - search = '" AND "'.join(search.split(" AND ")) - search = '"{}"'.format(search) - search = search.replace('%', '') - search = search.replace('_', '') - search = '{} MATCH (\'{}\')'.format(self.table, search) - - if parsed.parsedAgg: - # Handle aggregation - fro, whe = self.generateAggregation(parsed.parsedAgg, search) - return "SELECT * FROM {} WHERE {}".format(fro, whe) - - return 'SELECT * FROM {} WHERE {}'.format(self.table, search) \ No newline at end of file From b1c11cc345a37cba633f7bd4a15a659d90d2d466 Mon Sep 17 00:00:00 2001 From: ecco Date: Mon, 1 Jun 2020 03:30:27 -0400 Subject: [PATCH 34/94] add WMI module load false positive --- rules/windows/sysmon/sysmon_wmi_module_load.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rules/windows/sysmon/sysmon_wmi_module_load.yml b/rules/windows/sysmon/sysmon_wmi_module_load.yml index 8c660f19..3b6561ec 100644 --- a/rules/windows/sysmon/sysmon_wmi_module_load.yml +++ b/rules/windows/sysmon/sysmon_wmi_module_load.yml @@ -35,6 +35,8 @@ detection: - '\CompatTelRunner.exe' - '\sdiagnhost.exe' - '\SIHClient.exe' + - '\msfeedssync.exe' + - '\mmc.exe' condition: selection and not filter fields: - ComputerName From 4ed512011aff89a9398bffeffdd80341b0cf2904 Mon Sep 17 00:00:00 2001 From: Sven Scharmentke Date: Wed, 3 Jun 2020 09:00:59 +0200 Subject: [PATCH 35/94] All Rules use 'TargetFilename' instead of 'TargetFileName'. This commit fixes the incorrect spelling. --- other/godmode_sigma_rule.yml | 2 +- rules-unsupported/sysmon_process_reimaging.yml | 4 ++-- rules/windows/process_creation/win_hktl_createminidump.yml | 2 +- .../windows/sysmon/sysmon_lsass_memory_dump_file_creation.yml | 2 +- rules/windows/sysmon/sysmon_tsclient_filewrite_startup.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/other/godmode_sigma_rule.yml b/other/godmode_sigma_rule.yml index 218e0484..67969b7b 100644 --- a/other/godmode_sigma_rule.yml +++ b/other/godmode_sigma_rule.yml @@ -104,7 +104,7 @@ logsource: detection: selection_file_creation: EventID: 11 - TargetFileName|contains: + TargetFilename|contains: - '.dmp' # dump process memory - 'Desktop\how' # Ransomware - 'Desktop\decrypt' # Ransomware diff --git a/rules-unsupported/sysmon_process_reimaging.yml b/rules-unsupported/sysmon_process_reimaging.yml index 9d557b06..3da02214 100644 --- a/rules-unsupported/sysmon_process_reimaging.yml +++ b/rules-unsupported/sysmon_process_reimaging.yml @@ -5,7 +5,7 @@ description: Detects process reimaging defense evasion technique # where # selection1: ImageFileName != selection1: OriginalFileName # selection1: ParentProcessGuid = selection2: ProcessGuid -# selection1: Image = selection2: TargetFileName +# selection1: Image = selection2: TargetFilename # and new field ImageFileName is coming from enrichment # selection1: Image = ^.+\\$ # Rule must trigger if selection1 and selection2 both occurs in timeframe of 120 sec. @@ -45,4 +45,4 @@ detection: EventID: 11 fields: - ProcessGuid - - TargetFileName + - TargetFilename diff --git a/rules/windows/process_creation/win_hktl_createminidump.yml b/rules/windows/process_creation/win_hktl_createminidump.yml index a0e556d8..6129c97a 100644 --- a/rules/windows/process_creation/win_hktl_createminidump.yml +++ b/rules/windows/process_creation/win_hktl_createminidump.yml @@ -29,5 +29,5 @@ logsource: detection: selection: EventID: 11 - TargetFileName|contains: '*\lsass.dmp' + TargetFilename|contains: '*\lsass.dmp' condition: 1 of them diff --git a/rules/windows/sysmon/sysmon_lsass_memory_dump_file_creation.yml b/rules/windows/sysmon/sysmon_lsass_memory_dump_file_creation.yml index 0f6036df..54f7e04f 100644 --- a/rules/windows/sysmon/sysmon_lsass_memory_dump_file_creation.yml +++ b/rules/windows/sysmon/sysmon_lsass_memory_dump_file_creation.yml @@ -20,7 +20,7 @@ detection: condition: selection fields: - ComputerName - - TargetFileName + - TargetFilename falsepositives: - Dumping lsass memory for forensic investigation purposes by legitimate incident responder or forensic invetigator level: medium diff --git a/rules/windows/sysmon/sysmon_tsclient_filewrite_startup.yml b/rules/windows/sysmon/sysmon_tsclient_filewrite_startup.yml index c26821f2..efb359ac 100644 --- a/rules/windows/sysmon/sysmon_tsclient_filewrite_startup.yml +++ b/rules/windows/sysmon/sysmon_tsclient_filewrite_startup.yml @@ -11,7 +11,7 @@ detection: selection: EventID: 11 Image: '*\mstsc.exe' - TargetFileName: '*\Microsoft\Windows\Start Menu\Programs\Startup\\*' + TargetFilename: '*\Microsoft\Windows\Start Menu\Programs\Startup\\*' condition: selection falsepositives: - unknown From 84dd8c39c46d0f667104228390ccc923aa6abe33 Mon Sep 17 00:00:00 2001 From: William Bruneau Date: Tue, 5 May 2020 09:04:47 +0200 Subject: [PATCH 36/94] Move null values out from list in rules --- rules/windows/sysmon/sysmon_ads_executable.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rules/windows/sysmon/sysmon_ads_executable.yml b/rules/windows/sysmon/sysmon_ads_executable.yml index 7e111015..dbb055ad 100644 --- a/rules/windows/sysmon/sysmon_ads_executable.yml +++ b/rules/windows/sysmon/sysmon_ads_executable.yml @@ -17,11 +17,11 @@ logsource: detection: selection: EventID: 15 - filter: - Imphash: - - '00000000000000000000000000000000' - - null - condition: selection and not filter + filter1: + Imphash: '00000000000000000000000000000000' + filter2: + Imphash: null + condition: selection and not 1 of filter* fields: - TargetFilename - Image From a2ca199e7d0e0063bccdbf5732b428aaf2bedb28 Mon Sep 17 00:00:00 2001 From: Trent Liffick Date: Wed, 3 Jun 2020 17:38:03 -0400 Subject: [PATCH 37/94] added rules for Lazaurs and hhsgov --- .../win_apt_lazarus_session_highjack.yml | 27 +++++++++++++++++++ .../process_creation/win_susp_findstr_lnk.yml | 27 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 rules/windows/process_creation/win_apt_lazarus_session_highjack.yml create mode 100644 rules/windows/process_creation/win_susp_findstr_lnk.yml diff --git a/rules/windows/process_creation/win_apt_lazarus_session_highjack.yml b/rules/windows/process_creation/win_apt_lazarus_session_highjack.yml new file mode 100644 index 00000000..a9fc5185 --- /dev/null +++ b/rules/windows/process_creation/win_apt_lazarus_session_highjack.yml @@ -0,0 +1,27 @@ +title: Lazarus Session Highjacker +id: 3f7f5b0b-5b16-476c-a85f-ab477f6dd24b +description: Detects executables launched outside their default directories as used by Lazarus Group (Bluenoroff) +status: experimental +references: + - https://media.kasperskycontenthub.com/wp-content/uploads/sites/43/2018/03/07180244/Lazarus_Under_The_Hood_PDF_final.pdf +tags: + - attack.defense_evasion + - attack.t1036 +author: Trent Liffick (@tliffick) +date: 2020/06/03 +logsource: + category: process_creation + product: windows +detection: + selection: + Image: + - '*\mstdc.exe' + - '*\gpvc.exe' + filter: + Image: + - 'C:\Windows\System32\\*' + - 'C:\Windows\SysWOW64\\*' + condition: selection and not filter +falsepositives: + - unknown +level: high diff --git a/rules/windows/process_creation/win_susp_findstr_lnk.yml b/rules/windows/process_creation/win_susp_findstr_lnk.yml new file mode 100644 index 00000000..07fb7d3b --- /dev/null +++ b/rules/windows/process_creation/win_susp_findstr_lnk.yml @@ -0,0 +1,27 @@ +title: Findstr Launching .lnk File +id: 33339be3-148b-4e16-af56-ad16ec6c7e7b +description: Detects usage of findstr to identify and execute a lnk file as seen within the HHS redirect attack +status: experimental +references: + - https://www.bleepingcomputer.com/news/security/hhsgov-open-redirect-used-by-coronavirus-phishing-to-spread-malware/ +tags: + - attack.execution + - attack.t1202 + - attack.1034 +author: Trent Liffick +date: 2020/05/01 +logsource: + category: process_creation + product: windows +detection: + selection: + Image: '*\findstr.exe' + CommandLine: '*.lnk' + condition: selection +fields: + - Image + - CommandLine + - ParentCommandLine +falsepositives: + - unknown +level: medium From 2af501c9f51fb22e7dcf5c643f276d81ee162955 Mon Sep 17 00:00:00 2001 From: Trent Liffick Date: Wed, 3 Jun 2020 17:40:05 -0400 Subject: [PATCH 38/94] added rule for zLoader & Office detects changes to Office macro settings & ZLoader malware --- .../sysmon/mal_zloader_reg_changes.yml | 29 ++++++++++++++++++ .../sysmon/sysmon_reg_office_security.yml | 30 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 rules/windows/sysmon/mal_zloader_reg_changes.yml create mode 100644 rules/windows/sysmon/sysmon_reg_office_security.yml diff --git a/rules/windows/sysmon/mal_zloader_reg_changes.yml b/rules/windows/sysmon/mal_zloader_reg_changes.yml new file mode 100644 index 00000000..1c85697b --- /dev/null +++ b/rules/windows/sysmon/mal_zloader_reg_changes.yml @@ -0,0 +1,29 @@ +title: zLoader Registry Changes +id: 916ae9c5-a21a-4e34-b2ea-deccd16fba01 +description: Detects the registry changes made by zLoader malware +status: experimental +references: + - https://clickallthethings.wordpress.com/2020/05/13/zloader-and-xlm-4-0-making-evasion-great-again/ +author: Trent Liffick +date: 2020/05/13 +tags: + - attack.execution + - attack.t1112 +logsource: + product: windows + service: sysmon +detection: + selection: + EventID: + - 12 + - 13 + TargetObject: + - '*SOFTWARE\Microsoft\Office\\*\Word\Security' + condition: selection +fields: + - Image + - TargetObject + - TargetDetails +falsepositives: + - unknown +level: low diff --git a/rules/windows/sysmon/sysmon_reg_office_security.yml b/rules/windows/sysmon/sysmon_reg_office_security.yml new file mode 100644 index 00000000..e9f00dda --- /dev/null +++ b/rules/windows/sysmon/sysmon_reg_office_security.yml @@ -0,0 +1,30 @@ +title: Office Security Settings Changed +id: a166f74e-bf44-409d-b9ba-ea4b2dd8b3cd +status: experimental +description: Detects registry changes to Office macro settings +author: Trent Liffick (@tliffick) +date: 2020/05/22 +references: +tags: + - attack.defense_evasion + - attack.t1112 +falsepositives: + - Valid Macros and/or internal documents +level: high +logsource: + service: sysmon + product: windows +detection: + sec_settings: + EventID: + - 12 + - 13 + TargetObject|endswith: + - '*\Security\Trusted Documents\TrustRecords' + - '*\Security\AccessVBOM' + - '*\Security\VBAWarnings' + EventType: + - SetValue + - DeleteValue + - CreateValue + condition: sec_settings From 3c89f46899bd7671af0de68b43c101e121bae0d0 Mon Sep 17 00:00:00 2001 From: Trent Liffick Date: Wed, 3 Jun 2020 17:43:12 -0400 Subject: [PATCH 39/94] removed unwanted file --- .../sysmon/mal_zloader_reg_changes.yml | 29 ------------------- 1 file changed, 29 deletions(-) delete mode 100644 rules/windows/sysmon/mal_zloader_reg_changes.yml diff --git a/rules/windows/sysmon/mal_zloader_reg_changes.yml b/rules/windows/sysmon/mal_zloader_reg_changes.yml deleted file mode 100644 index 1c85697b..00000000 --- a/rules/windows/sysmon/mal_zloader_reg_changes.yml +++ /dev/null @@ -1,29 +0,0 @@ -title: zLoader Registry Changes -id: 916ae9c5-a21a-4e34-b2ea-deccd16fba01 -description: Detects the registry changes made by zLoader malware -status: experimental -references: - - https://clickallthethings.wordpress.com/2020/05/13/zloader-and-xlm-4-0-making-evasion-great-again/ -author: Trent Liffick -date: 2020/05/13 -tags: - - attack.execution - - attack.t1112 -logsource: - product: windows - service: sysmon -detection: - selection: - EventID: - - 12 - - 13 - TargetObject: - - '*SOFTWARE\Microsoft\Office\\*\Word\Security' - condition: selection -fields: - - Image - - TargetObject - - TargetDetails -falsepositives: - - unknown -level: low From 6c8c0cd85dc3c12ed5bfe5ba52c50aca41c2c927 Mon Sep 17 00:00:00 2001 From: Trent Liffick Date: Wed, 3 Jun 2020 17:51:57 -0400 Subject: [PATCH 40/94] Removed incorrect technique --- rules/windows/process_creation/win_susp_findstr_lnk.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rules/windows/process_creation/win_susp_findstr_lnk.yml b/rules/windows/process_creation/win_susp_findstr_lnk.yml index 07fb7d3b..657d47ff 100644 --- a/rules/windows/process_creation/win_susp_findstr_lnk.yml +++ b/rules/windows/process_creation/win_susp_findstr_lnk.yml @@ -5,9 +5,8 @@ status: experimental references: - https://www.bleepingcomputer.com/news/security/hhsgov-open-redirect-used-by-coronavirus-phishing-to-spread-malware/ tags: - - attack.execution + - attack.defense_evasion - attack.t1202 - - attack.1034 author: Trent Liffick date: 2020/05/01 logsource: From 09afae1e66393f5c534a7dd8c9a6d96419f35bd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Furkan=20=C3=87ALI=C5=9EKAN?= Date: Thu, 4 Jun 2020 14:27:19 +0300 Subject: [PATCH 41/94] Create sysmon_apt_muddywater_dnstunnel.yml Detecting DNS tunnel activity from MuddyWater as in https://www.virustotal.com/gui/file/5ad401c3a568bd87dd13f8a9ddc4e450ece61cd9ce4d1b23f68ce0b1f3c190b7/ --- .../sysmon_apt_muddywater_dnstunnel.yml | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml diff --git a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml new file mode 100644 index 00000000..38a29292 --- /dev/null +++ b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml @@ -0,0 +1,26 @@ +title: "Muddywater DNS tunnel method detection" +description: "Detecting DNS tunnel activity from Muddywater" +author: Furkan Caliskan +status: "testing" +references: +- https://www.virustotal.com/gui/file/5ad401c3a568bd87dd13f8a9ddc4e450ece61cd9ce4d1b23f68ce0b1f3c190b7/ +- https://www.vmray.com/analyses/5ad401c3a568/report/overview.html +tags: +- attack.command_and_control +- attack.t1071 +logsource: + product: "windows" + service: "sysmon" +detection: + selection: + EventID: 1 + Image|endswith: + - '\powershell.exe' + ParentImage|endswith: + - '\excel.exe' + CommandLine|contains: + - 'DataExchange.dll' + condition: selection +falsepositives: +- Unkown +level: medium From bafd6bde5f69f7d519426ac1273de9260b7bf517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Furkan=20=C3=87ALI=C5=9EKAN?= Date: Thu, 4 Jun 2020 14:45:10 +0300 Subject: [PATCH 42/94] Convert to process_creation Convert to process_creation --- rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml index 38a29292..2c39917a 100644 --- a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml +++ b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml @@ -1,4 +1,4 @@ -title: "Muddywater DNS tunnel method detection" +title: "Muddywater DNS tunnel detection" description: "Detecting DNS tunnel activity from Muddywater" author: Furkan Caliskan status: "testing" @@ -9,8 +9,8 @@ tags: - attack.command_and_control - attack.t1071 logsource: - product: "windows" - service: "sysmon" + category: process_creation + product: windows detection: selection: EventID: 1 From 1c677aa172fbdc42dd2b07fbca4d3cfb33e33815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Furkan=20=C3=87ALI=C5=9EKAN?= Date: Thu, 4 Jun 2020 18:13:32 +0300 Subject: [PATCH 43/94] Fix title as in guideline Fix title error as in guideline and other cosmetic changes --- rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml index 2c39917a..13ee8b63 100644 --- a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml +++ b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml @@ -1,7 +1,7 @@ -title: "Muddywater DNS tunnel detection" -description: "Detecting DNS tunnel activity from Muddywater" +title: Muddywater DNS tunnel activity +description: Detecting DNS tunnel activity for Muddywater actor author: Furkan Caliskan -status: "testing" +status: testing references: - https://www.virustotal.com/gui/file/5ad401c3a568bd87dd13f8a9ddc4e450ece61cd9ce4d1b23f68ce0b1f3c190b7/ - https://www.vmray.com/analyses/5ad401c3a568/report/overview.html From 0744107fbb3fcf2444d00a8d3539dd1a2ce6bbd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Furkan=20=C3=87ALI=C5=9EKAN?= Date: Thu, 4 Jun 2020 18:19:08 +0300 Subject: [PATCH 44/94] Deleted EventID part --- rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml index 13ee8b63..87b6a254 100644 --- a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml +++ b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml @@ -13,7 +13,6 @@ logsource: product: windows detection: selection: - EventID: 1 Image|endswith: - '\powershell.exe' ParentImage|endswith: From 5e373153ebf64c2d1d4a47e9cbc2a14c356f4ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Furkan=20=C3=87ALI=C5=9EKAN?= Date: Thu, 4 Jun 2020 18:28:37 +0300 Subject: [PATCH 45/94] Title fix --- rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml index 87b6a254..b77e33e3 100644 --- a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml +++ b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml @@ -1,4 +1,4 @@ -title: Muddywater DNS tunnel activity +title: DNS Tunnel Technique from MuddyWater description: Detecting DNS tunnel activity for Muddywater actor author: Furkan Caliskan status: testing From e958a6a9398d0dc32eeb78eccfeeb2dfc0081fe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Furkan=20=C3=87ALI=C5=9EKAN?= Date: Thu, 4 Jun 2020 18:34:44 +0300 Subject: [PATCH 46/94] Date added --- rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml index b77e33e3..e13e7fca 100644 --- a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml +++ b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml @@ -1,7 +1,8 @@ title: DNS Tunnel Technique from MuddyWater description: Detecting DNS tunnel activity for Muddywater actor -author: Furkan Caliskan -status: testing +author: '@caliskanfurkan_' +status: experimental +date: 2020/06/04 references: - https://www.virustotal.com/gui/file/5ad401c3a568bd87dd13f8a9ddc4e450ece61cd9ce4d1b23f68ce0b1f3c190b7/ - https://www.vmray.com/analyses/5ad401c3a568/report/overview.html From 082696ee84e00d2c1367267f156d31bfb52c415a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Furkan=20=C3=87ALI=C5=9EKAN?= Date: Thu, 4 Jun 2020 18:38:42 +0300 Subject: [PATCH 47/94] Added UUID --- rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml index e13e7fca..32004f6e 100644 --- a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml +++ b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml @@ -1,4 +1,5 @@ title: DNS Tunnel Technique from MuddyWater +id: 36222790-0d43-4fe8-86e4-674b27809543 description: Detecting DNS tunnel activity for Muddywater actor author: '@caliskanfurkan_' status: experimental From 55beecac28ac1679f23771eef77e8c56dbfa7646 Mon Sep 17 00:00:00 2001 From: Nate Guagenti Date: Fri, 5 Jun 2020 13:18:03 -0400 Subject: [PATCH 48/94] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit d97d2ced8274bd2972b5d10ff8a56fc6c2c0242f Merge: 022d73f8 84dd8c39 Author: Florian Roth Date: Wed Jun 3 15:53:55 2020 +0200 Merge pull request #725 from WilliamBruneau/fix_null_list Move null values out from list in rules commit 84dd8c39c46d0f667104228390ccc923aa6abe33 Author: William Bruneau Date: Tue May 5 09:04:47 2020 +0200 Move null values out from list in rules commit 022d73f842c403a1859a558b8f443c1cc2f5ab0a Merge: 0cbc099d 4ed51201 Author: Florian Roth Date: Wed Jun 3 10:48:05 2020 +0200 Merge pull request #811 from svnscha/fix/field-TargetFileName-to-TargetFilename All Rules use 'TargetFilename' instead of 'TargetFileName'. commit 4ed512011aff89a9398bffeffdd80341b0cf2904 Author: Sven Scharmentke Date: Wed Jun 3 09:00:59 2020 +0200 All Rules use 'TargetFilename' instead of 'TargetFileName'. This commit fixes the incorrect spelling. commit 0cbc099def5b79ff2d01164e035c743972f6fe66 Merge: 74e16fdc 3a6ac5bd Author: Florian Roth Date: Sat May 30 09:31:45 2020 +0200 Merge pull request #807 from forensicanalysis/master Add sqlite backend commit 3a6ac5bd5c711848b9e85b94741b210740cdada9 Author: Jonas Plum Date: Sat May 30 01:57:06 2020 +0200 Remove unused function commit 5cc82d0f05b4a0ea6640f6bdc4fc0fe719945108 Author: Jonas Plum Date: Sat May 30 00:56:06 2020 +0200 Move testcase commit 4a8ab88adecc4035aedb8b8780c29a76a31eca04 Author: Jonas Plum Date: Sat May 30 00:15:38 2020 +0200 Fix test path commit 70935d26ce214b566b34c4555531e0510a619a99 Author: Jonas Plum Date: Fri May 29 23:56:05 2020 +0200 Add license header commit 74e16fdccddf604943ab74d27cdd3a4bb38bd957 Merge: e20b58c4 537bda44 Author: Florian Roth Date: Fri May 29 17:32:43 2020 +0200 Merge pull request #803 from gamma37/clear_cmd_history Edit Clear Command History commit e20b58c421194d1125c8c81a88818fc8058ede31 Merge: 7f2fa05e a00f7f19 Author: Florian Roth Date: Fri May 29 17:32:27 2020 +0200 Merge pull request #806 from SanWieb/sysmon_creation_system_file Fixed wrong field & Improve rule commit a00f7f19a14b58ab9ca98f6a4215a3ca9eb1932a Author: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Fri May 29 16:25:54 2020 +0200 Add tagg Endswith Prevent the trigger of {}.exe.log commit 38afd8b5def24191616ff0f0c0324cfbb7f0d6d0 Author: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Thu May 28 21:52:17 2020 +0200 Fixed wrong field commit 7f2fa05ed300ee42b83677897f326cf81a6d61d8 Merge: ec313b6c 39b41b55 Author: Florian Roth Date: Thu May 28 11:16:44 2020 +0200 Merge pull request #802 from Neo23x0/rule-devel ComRAT and KazuarRAT commit 537bda4417ef90f5af9c754d3b0d965c79103cb0 Author: gamma37 Date: Thu May 28 10:56:35 2020 +0200 Update lnx_shell_clear_cmd_history.yml commit 5a489348224307685cf63bb0cdd7d8b7288d5fc7 Author: gamma37 Date: Thu May 28 10:52:17 2020 +0200 Edit Clear Command History I suggest a new point of view to detect that bash_history has been cleared : Instead of trying to detect all the commands that can do that, we could monitor the size of the file and log whenever it has less than 1 line. commit 39b41b5582ac76ddd8fe694ce31dc6288d60b631 Author: Florian Roth Date: Thu May 28 10:13:38 2020 +0200 rule: moved DebugView rule to process creation category commit 76dcc1a16fff440951c2d5d15307b8337ae6f792 Author: Florian Roth Date: Thu May 28 09:22:25 2020 +0200 rule: renamed debugview commit ec313b6c8ae02e17e9fa4da82cf766d24a3298ba Merge: 5bb6770f d44fc43c Author: Florian Roth Date: Wed May 27 08:49:20 2020 +0200 Merge pull request #801 from SanWieb/sysmon_creation_system_file Rule: sysmon_creation_system_file commit d44fc43c5452e4e62b5dcf990139a4e166dda706 Author: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Tue May 26 19:10:11 2020 +0200 Add extension commit f6ec724d51b9feb83ce903c6c6398f9c143b9bd4 Author: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Tue May 26 18:53:54 2020 +0200 Rule: sysmon_creation_system_file commit 5bb6770f5305cf2e1401191a39f392e6d04722d6 Merge: 0b398c5b 3681b8cb Author: Florian Roth Date: Tue May 26 14:28:47 2020 +0200 Merge pull request #800 from SanWieb/win_system_exe_anomaly Extended Windows processes: win_system_exe_anomaly commit 4ca81b896d044e6ff9ffb9798a7b503029a52259 Author: Florian Roth Date: Tue May 26 14:19:22 2020 +0200 rule: Turla ComRAT report commit 3681b8cb56144248ed57afdb31ce748d01190a0b Author: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Tue May 26 13:56:51 2020 +0200 Extended Windows processes commit 0b398c5bf0d186653e41bb407caf182042f6ce87 Merge: c1f47875 b648998f Author: Florian Roth Date: Tue May 26 13:31:57 2020 +0200 Merge pull request #798 from Neo23x0/rule-devel rule: confluence exploit CVE-2019-3398 & Turla ComRAT commit c1f4787566fb522ce784487148cec52e92f698ae Merge: ce1f4634 48c5f2ed Author: Florian Roth Date: Tue May 26 13:21:04 2020 +0200 Merge pull request #797 from NVISO-BE/sysmon_cve-2020-1048 Changes to sysmon_cve-2020-1048 commit ce1f46346fe948b3494ec55acc19079e98a6a90c Merge: e131f347 1a598282 Author: Florian Roth Date: Tue May 26 13:20:40 2020 +0200 Merge pull request #751 from zaphodef/fix/powershell_ntfs_ads_access Add 'Add-Content' to powershell_ntfs_ads_access commit e131f3476e4601b7fd2e0458f3b46be953408eb9 Merge: 30861b55 7037e775 Author: Florian Roth Date: Tue May 26 13:20:23 2020 +0200 Merge pull request #796 from EccoTheFlintstone/fp add more false positives commit 30861b558ce294d75e7bba40605ac7d962fd4a69 Merge: a962bd1b f9f814f3 Author: Florian Roth Date: Tue May 26 13:20:07 2020 +0200 Merge pull request #799 from SanWieb/susp_file_characteristics Susp file characteristics: Reduce FP of legitime processes commit b648998fd0e7100f6a39d7323be0cc1941e49d5e Author: Florian Roth Date: Tue May 26 13:18:50 2020 +0200 rule: Turla ComRAT commit f9f814f3b3d927a31a9e7703f03e4bd6e28f8e05 Author: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Tue May 26 13:06:27 2020 +0200 Shortened title commit a241792e1077be912087c0f22a735e427d9d43ab Author: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Tue May 26 12:58:15 2020 +0200 Reduce FP of legitime processes A lot of Windows apps does not have any file characteristics. Some examples: - Gamebar: C:\\Program Files\\WindowsApps\\Microsoft.XboxGamingOverlay_3.38.25003.0_x64__8wekyb3d8bbwe\\GameBarFT.exe - YourPhone: C:\\Program Files\\WindowsApps\\Microsoft.YourPhone_1.20022.82.0_x64__8wekyb3d8bbwe\\YourPhoneServer/YourPhoneServer.exe All C:\Windows\System32\OpenSSH (scp, sftp, ssh etc) does not have a description and company. Python 2.7, 3.3 and 3.7 does not have any file characteristics. So I don't think it is possible to whitelist all options, maybe it is worthwhile to check the \Downloads\ folder otherwise it would be better to just delete the rule. All other suspicious folders are covered by /rules/windows/process_creation/win_susp_exec_folder.yml commit cdf1ade6254533f55b1802d081b33fdfac6a9077 Author: Florian Roth Date: Tue May 26 12:27:16 2020 +0200 fix: typo in selection commit 91b4ee8d5611b481896a7b7034826d86b435e815 Merge: 4cd7c39e a962bd1b Author: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Tue May 26 12:24:21 2020 +0200 Merge pull request #2 from Neo23x0/master Update repository commit 828484d7c6384d85d74ace3ab577fd6b60d22f2a Author: Florian Roth Date: Tue May 26 12:09:41 2020 +0200 rule: confluence exploit CVE-2019-3398 commit 48c5f2ed094ead20bd7b94786530e0583e0d5323 Author: Remco Hofman Date: Tue May 26 11:20:21 2020 +0200 Update to sysmon_cve-2020-1048 Added .com executables to detection Second TargetObject should have been Details commit abf1a2c6d7eb6a031fcb60dd003fccf62bd7af33 Author: Jonas Hagg Date: Mon May 25 10:54:16 2020 +0200 Adjusted Makefile commit dedfb65d635f544011e30cf6ab303db7d782e092 Author: Jonas Hagg Date: Mon May 25 10:44:14 2020 +0200 Implemented Aggregation for SQL, Added SQLite FullTextSearch commit 7037e77569e062b85f335ef3c9d04b2d392b5214 Author: ecco Date: Mon May 25 04:50:22 2020 -0400 add more FP commit a962bd1bc19d96a415d99322a6df5144011b2ffd Merge: 0afe0623 d510e1aa Author: Florian Roth Date: Mon May 25 10:48:36 2020 +0200 Merge pull request #747 from zaphodef/fix/win_susp_backup_delete_source Fix 'source' value for win_susp_backup_delete commit 0afe0623afd2fbe9cd46074142643536ae5c5cfd Merge: 92d0aa86 beb62dc1 Author: Florian Roth Date: Mon May 25 10:47:23 2020 +0200 Merge pull request #757 from tliffick/master added rule for Blue Mockingbird (cryptominer) commit 92d0aa86549ba8371fa0856dfb364354ef5409bd Merge: 0dda757c 6fcf3f9e Author: Florian Roth Date: Mon May 25 10:46:39 2020 +0200 Merge pull request #795 from SanWieb/Rule-improvement-Netsh-program-allowed Rule improvement: netsh Application or Port allowed commit 6fcf3f9ebf3ae66ee9bb7853f823dfe11f62d2c1 Author: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Mon May 25 10:13:26 2020 +0200 Update win_netsh_fw_add.yml commit 28652e4648fca1cbc48149163c001f209275c7dd Author: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Mon May 25 10:02:13 2020 +0200 Add Windows Server 2008 and Windows Vista support It did not support the command `netsh advfirewall firewall add` commit 2678cd1d3e104bd916262f8a242c28006704a457 Author: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Mon May 25 09:50:47 2020 +0200 Create win_netsh_fw_add_susp_image.yml More critical version of the rule windows/process_creation/win_netsh_fw_add.yml with the suspicious image location check. Combined the following rules for the suspicious locations: https://github.com/Neo23x0/sigma//blob/master/rules/windows/sysmon/sysmon_susp_download_run_key.yml https://github.com/Neo23x0/sigma/blob/master/rules/windows/sysmon/sysmon_susp_run_key_img_folder.yml https://github.com/Neo23x0/sigma/blob/master/rules/windows/process_creation/win_susp_run_locations.yml commit 4cd7c39e9d17182018af175692d5c98c6bb9894e Merge: 6fbfa9df 0dda757c Author: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Mon May 25 08:48:16 2020 +0200 Merge pull request #1 from Neo23x0/master Update repository commit 0dda757ca59b5f80da0e537932e73e8a2be5540d Merge: 40f0beb5 daf7ab5f Author: Thomas Patzke Date: Sun May 24 22:58:58 2020 +0200 Merge branch 'socprime-master' commit daf7ab5ff71c48aec9fab29a70c62a3fec310768 Author: Thomas Patzke Date: Sun May 24 22:41:38 2020 +0200 Cleanup: removal of corelight_* backends commit d45f8e19fef854a1779973d9a8ae51714d38257d Author: Thomas Patzke Date: Sun May 24 21:46:55 2020 +0200 Fixes commit 32e4998c4967d7d09762d994e69cca4ccc143f3c Author: Thomas Patzke Date: Sun May 24 21:45:37 2020 +0200 Removed dead code from ALA backend. commit 24b08bbf30f51e07226a0debd9039763bae3d511 Merge: 96fae4be e8b956f5 Author: Thomas Patzke Date: Sun May 24 17:06:32 2020 +0200 Merge branch 'master' of https://github.com/socprime/sigma into socprime-master commit 40f0beb58da299e648df1eebf2480e3393ab0cc3 Merge: 6fbfa9df b8ee736f Author: Florian Roth Date: Sun May 24 16:30:10 2020 +0200 Merge pull request #794 from SanWieb/update_susp_run_key Remove AppData folder as suspicious folder commit b8ee736f4484ec86e23a5016bd9c634c909b8e33 Author: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Sun May 24 15:16:07 2020 +0200 Remove AppData folder as suspicious folder A lot of software is using the AppData folder for startup keys. Some examples: - Microsoft Teams (\AppData\Local\Microsoft\Teams) - Resilio (\AppData\Roaming\Resilio Sync\) - Discord ( (\AppData\Local\Discord\) - Spotify ( (\AppData\Roaming\Spotify\) Too many to whitelist them all commit 6fbfa9dfdd82372120470ddc87e43410401f6fca Merge: d0da2810 3028a270 Author: Florian Roth Date: Sat May 23 23:47:12 2020 +0200 Merge pull request #793 from Neo23x0/rule-devel Esentutl rule and StrongPity Loader UA commit f970d28f10b1e7906593265055bb6a804142ee4e Author: ecco Date: Sat May 23 15:06:15 2020 -0400 add more false positives commit 3028a27055b5ed7a1104cfa8389b7e5005fb0f83 Author: Florian Roth Date: Sat May 23 18:32:02 2020 +0200 fix: buggy rule commit df715386b6abaa5a1208dc611d4e1e3e7cf91d3a Author: Florian Roth Date: Sat May 23 18:27:36 2020 +0200 rule: suspicious esentutl use commit d0da2810c1180efd7e170e73c4e52fd2c21a94c0 Merge: 8321cc7e 67faf4bd Author: Florian Roth Date: Sat May 23 18:13:16 2020 +0200 Merge pull request #792 from EccoTheFlintstone/fff fix FP + remove powershell rule redundant with sysmon_in_memory_power… commit 8321cc7ee1af886b2672abac5edb148cd1040231 Merge: 9cd9a301 e1a05dfc Author: Florian Roth Date: Sat May 23 18:11:32 2020 +0200 Merge pull request #772 from gamma37/suspicious_activities Create a rule for "suspicious activities" commit d1a5471d2131b9f14787db3ae7e56eb8428bb560 Author: Florian Roth Date: Sat May 23 17:38:10 2020 +0200 rule: Strong Pity loader UA commit 67faf4bd41c8ccf27d71a6c3d28a5868c95274d2 Author: ecco Date: Sat May 23 10:56:23 2020 -0400 fix FP + remove powershell rule redundant with sysmon_in_memory_powershell.yml commit 9cd9a301c21320fe4da002184a4e2fdcea640396 Merge: ee1ca77f d310805e Author: Florian Roth Date: Sat May 23 16:50:31 2020 +0200 Merge pull request #791 from SanWieb/master added rule for Netsh RDP port opening commit e1a05dfc1cfdb5b0925932a66c43706102ffbccb Author: Florian Roth Date: Sat May 23 16:49:03 2020 +0200 Update lnx_auditd_susp_C2_commands.yml commit ee1ca77fad7ebb649ed49190a0c228145ac72834 Merge: 895c8470 cbf06b1e Author: Florian Roth Date: Sat May 23 16:47:46 2020 +0200 Merge pull request #771 from gamma37/new_rules Create a new rule to detect "Create Account" commit 895c84703fb60c3ffc3edce06492de1914dab536 Merge: 12e1aeaf 327a53c1 Author: Florian Roth Date: Sat May 23 16:47:01 2020 +0200 Merge pull request #790 from EccoTheFlintstone/fp_fix fix false positive matching on every powershell process not run by SY… commit 327a53c120674588b3f1e439c373a45cda73c543 Author: ecco Date: Sat May 23 10:25:37 2020 -0400 add new test for sysmon rules without eventid commit 10ca3006f51b6debb18a2e1067629d260d9cf416 Author: ecco Date: Sat May 23 10:07:55 2020 -0400 move rule where needed commit 2b89e5605469f89c9b51e59ba1e245dcffdba18d Author: ecco Date: Sat May 23 10:03:13 2020 -0400 fix test commit d9bc09c38c32333f39512614ceb1f380cc3fa44a Author: ecco Date: Sat May 23 10:02:58 2020 -0400 fix test commit 78a7852a4392464f12618c903da1aa82346a19b9 Author: ecco Date: Sat May 23 09:16:40 2020 -0400 renamed dbghelp rule with new ID and comment and removed a false positive commit d310805ed9e5783c94f0cb48b7cea1d3b20e7458 Author: Sander Wiebing <45387038+SanWieb@users.noreply.github.com> Date: Sat May 23 14:19:52 2020 +0200 rule: Netsh RDP port opening commit 75ba5f989cd7c223059222151a3e321e85c9860c Author: ecco Date: Sat May 23 07:44:45 2020 -0400 add 1 more FP to wmi load commit 9a7f462d795ffa68345179c4c2e33b1044756600 Author: ecco Date: Sat May 23 07:17:56 2020 -0400 move renamed bnaries rule to process creation (they made a lot of false positives in sysmon as there was no event id specified in the rule) commit cfde0625f53ef2af49ce6cf81c80c8715cbf7fe8 Author: ecco Date: Sat May 23 07:05:09 2020 -0400 fix false positive matching on every powershell process not run by SYSTEM account commit 12e1aeaf9f3ca20c173f71159054e1da67c96eb4 Merge: 46f3a70a 34006d07 Author: Florian Roth Date: Sat May 23 09:54:43 2020 +0200 Merge pull request #788 from Neo23x0/rule-devel refactor: split up rule for CVE-2020-1048 into 2 rules commit 46f3a70a7dde70c524abdf99380c675c225847ab Merge: 96fae4be ec17c2ab Author: Florian Roth Date: Sat May 23 09:54:28 2020 +0200 Merge pull request #786 from EccoTheFlintstone/perf_fix various rules cleaning (slight perf improvements) commit 34006d079431ec5d5892174bf4a1a4f0a30fd1f9 Author: Florian Roth Date: Sat May 23 09:16:19 2020 +0200 refactor: simplified and extended expression in CVE-2020-1048 rule commit 57c8e63acd8a44d79f509142c67d71326d849ef7 Author: Florian Roth Date: Sat May 23 09:09:58 2020 +0200 refactore: split up rule for CVE-2020-1048 into 2 rules commit ec17c2ab56ac12477c80e7ac8c2e66a7f8dedd99 Author: ecco Date: Fri May 22 10:37:00 2020 -0400 filter on createkey only when needed commit 96fae4be68faa1bad2c8cfa92b1e5a500e72d765 Author: Thomas Patzke Date: Fri May 22 00:50:37 2020 +0200 Added CrachMapExec rules commit 64e0e7ca7226be813bfd87f197bc99187e0f7edd Merge: bbf78374 91c4c4ec Author: Florian Roth Date: Thu May 21 14:19:09 2020 +0200 Merge pull request #784 from Neo23x0/rule-devel refactor: slightly improved Greenbug rule commit 91c4c4ecc51de7a7ac5e2fb3e11dd45f4ddfbb2a Author: Florian Roth Date: Thu May 21 13:38:11 2020 +0200 refactor: slightly improved Greenbug rule commit bbf78374b68ace06386410028d2424386f36339e Merge: 8d9b706d 9a3b6c1c Author: Florian Roth Date: Thu May 21 09:55:46 2020 +0200 Merge pull request #783 from Neo23x0/rule-devel Greenbug Rule commit 9a3b6c1c7712279691e0c177a7d8e282fca8847b Author: Florian Roth Date: Thu May 21 09:44:11 2020 +0200 docs: added MITRE ATT&CK group tag commit 344eb713c5a8e5defc98ee9010cdbc25872adb52 Author: Florian Roth Date: Thu May 21 09:39:57 2020 +0200 rule: Greenbug campaign commit 8d9b706d6a224358eaaf20c4b6360982bbe75d78 Merge: e7980bb4 06abd6e7 Author: Thomas Patzke Date: Wed May 20 19:11:56 2020 +0200 Merge pull request #727 from 3CORESec/master Override Features commit e7980bb434ed21c23208f86b85307a97ea18cffb Merge: af92a5bd 8963c0a6 Author: Florian Roth Date: Wed May 20 12:55:41 2020 +0200 Merge pull request #782 from ZikyHD/patch-1 Remove duplicate 'CommandLine' in fields commit af92a5bd2c74c55f06304af5967b9d705f6e86c5 Merge: 04dfe6c5 9ab65cd1 Author: Florian Roth Date: Wed May 20 12:55:29 2020 +0200 Merge pull request #780 from tatsu-i/master Null field check to eliminate false positives commit 8963c0a65e19f7202fe5daf467d1d4d33abd3d0a Author: ZikyHD Date: Wed May 20 11:54:47 2020 +0200 Remove duplicate 'CommandLine' in fields commit e8b956f575c0af942d20ee3a6b951f52c04d3baa Author: vh Date: Wed May 20 12:35:00 2020 +0300 Updated config commit 9ab65cd1c73a9225a2090f81d07064761df487c1 Author: Florian Roth Date: Tue May 19 14:50:22 2020 +0200 Update win_alert_ad_user_backdoors.yml commit 04dfe6c5fc44a6a9e4b8bde35c2693d78be306e7 Merge: df75bdd3 9e272d37 Author: Thomas Patzke Date: Tue May 19 13:18:40 2020 +0200 Merge pull request #778 from neu5ron/sigmacs SIGMACs: Winlogbeat & Zeek commit df75bdd3b67afecca06714e2f38a39bf5319cb7b Merge: 4446c4cd 7c3dea22 Author: Florian Roth Date: Tue May 19 13:10:56 2020 +0200 Merge pull request #779 from neu5ron/rules Rules: Zeek commit 7c3dea22b8702d7cc8e6796fd383d5a62096fffa Author: neu5ron <> Date: Tue May 19 05:13:48 2020 -0400 small T, big T commit dd382848b4b1f693a35c1a89313b492d6293859d Merge: 602c8917 e975d3fd Author: neu5ron <> Date: Tue May 19 05:09:05 2020 -0400 Merge remote-tracking branch 'neu5ron-sigma/rules' into rules commit 602c8917ef7de1aca12ef7641e86bcee57fddd4a Author: neu5ron <> Date: Tue May 19 04:41:08 2020 -0400 domain user enumeration via zeek rpc (dce_rpc) log. commit c815773b1abf32ef2ba94f333b8421a389362875 Author: Tatsuya Ito Date: Tue May 19 18:05:51 2020 +0900 enhancement rule commit 49f68a327a88bf7c6d527e12885941c894670619 Author: Tatsuya Ito Date: Tue May 19 18:00:50 2020 +0900 enhancement rule commit e975d3fd14f2a241c536b0b0773639694a985b5c Author: neu5ron <> Date: Tue May 19 04:41:08 2020 -0400 domain user enumeration via zeek rpc (dce_rpc) log. commit effb2a833713afba2902c5a03dc316207b2e6b25 Author: neu5ron <> Date: Tue May 19 04:41:00 2020 -0400 add exe webdav download commit 858ebcd3d3d1fa7b3c019797cf9624e8820bbf82 Author: neu5ron <> Date: Tue May 19 04:35:47 2020 -0400 author typo update commit 2fc8d513d6bab5e194271a20e544b42f3d921878 Author: neu5ron <> Date: Tue May 19 04:35:30 2020 -0400 zeek, swap `path` and `name` commit 0dd089db47e4f7a86f3573a481a67eabb2a234de Author: ecco Date: Mon May 18 20:29:53 2020 -0400 various rules cleaning commit 71c507d8a95b43e45d435c1e70a51f964655f12c Author: gamma37 Date: Mon May 18 11:34:53 2020 +0200 remove space bedore colon commit 55eec46932d99c18baf8c0aed86d4bf470ef1f6e Author: gamma37 Date: Mon May 18 11:25:18 2020 +0200 Create a rule for "suspicious activities" commit cbf06b1e43dc523885c3107fb35ffcc88c20e735 Author: gamma37 Date: Mon May 18 10:11:32 2020 +0200 lowercased tag commit 904716771a98e7c68d20e1b642073788309c17f2 Author: gamma37 Date: Mon May 18 10:03:34 2020 +0200 Create a new rule to detect "Create Account" commit beb62dc163ee995a9fbe362807c132bf8edd1e09 Author: Florian Roth Date: Fri May 15 12:06:34 2020 +0200 fix: condition location commit 28dc2a22672e5959e3920a08fa5c17f35a0351f5 Author: Florian Roth Date: Fri May 15 11:33:36 2020 +0200 Minor changes hints: - contains doesn't require wildcards in the strings - we can use 'endswith' instead of wildcard at the beginning of the string (it's the new way to describe it, we have to change all old rules that contain these wildcards some day) - we can use "1 of them" to say that 1 of the conditions has to match commit 40ab1b7247e52be5ff01429a0d6b9b80656aedb2 Author: Trent Liffick Date: Thu May 14 23:33:08 2020 -0400 added 'action: global' commit 56a2747a7062e2205f729f19ef34535f80c24c9d Author: Trent Liffick Date: Thu May 14 23:18:33 2020 -0400 Corrected missing condition learning! fail fast & forward commit fb1d8d7a76c45451ac1d14829d812ae5961493fe Author: Trent Liffick Date: Thu May 14 23:04:14 2020 -0400 Corrected typo commit 8aff6b412e39de70da551c9c9854ea97a8a8b16c Author: Trent Liffick Date: Thu May 14 22:58:23 2020 -0400 added rule for Blue Mockingbird (cryptominer) commit 06abd6e76a0487ac0bbe414ecae9ce021bce4106 Author: Tiago Faria Date: Thu May 14 14:03:23 2020 +0100 added ci tests for ecs-cloudtrail commit 2893becf8cc6e9c581050b4c35dc381f1aba13e1 Merge: 31ad8187 133319c4 Author: Tiago Faria Date: Thu May 14 14:02:20 2020 +0100 Merge remote-tracking branch 'upstream/master' commit 1a598282f4033e51e060b1014600970fdc64f72a Author: zaphod <18658828+zaphodef@users.noreply.github.com> Date: Wed May 13 11:57:10 2020 +0200 Add 'Add-Content' to powershell_ntfs_ads_access commit d510e1aad45908a0b73c66fce6d349d09cace3b4 Author: zaphod <18658828+zaphodef@users.noreply.github.com> Date: Mon May 11 18:31:59 2020 +0200 Fix 'source' value for win_susp_backup_delete commit fb9c5841f4fde53437bc01b764060fdf63bf52ea Author: vh Date: Fri May 8 13:41:52 2020 +0300 Added Humio, Crowdstrike, Corelight commit 31ad81874fee378ea3f951d81d088aac9fb1e737 Author: pdr9rc Date: Tue May 5 11:32:18 2020 +0100 capitalized titles corrected capitalization of titles and removed literals from config commit aa175a7d5bbfd8b9e6526cfa36256dac5514bff4 Author: pdr9rc Date: Mon May 4 18:02:27 2020 +0100 wip wip commit dd9e128a15d5f9ad08ea744cde0f18b49a4a1204 Author: pdr9rc Date: Mon May 4 17:35:12 2020 +0100 kibana target update kibana target now compatible with overrides commit b32093e734395841bcef94414a575bdf3a3a98ac Merge: b3194e66 d298bb57 Author: pdr9rc Date: Mon May 4 17:26:51 2020 +0100 Merge remote-tracking branch 'upstream/master' Keeping up with the sigmas. commit b3194e66c4f1def35c11f407d6c7e47867eb8053 Author: pdr9rc Date: Mon May 4 16:37:36 2020 +0100 Update base.py commit dd85467a271d79ec30079e0e4b6391e1a465cd0a Author: Tiago Faria Date: Sat May 2 00:13:55 2020 +0100 Update aws_ec2_vm_export_failure.yml commit bc0a2c7ab932cf967869cc31237b18b1cef0e09e Author: pdr9rc Date: Fri May 1 19:20:05 2020 +0100 wip wip commit 98391f985a17f7a1a694857468ad3b66a2515025 Author: pdr9rc Date: Thu Apr 30 15:19:38 2020 +0100 wip wip commit adcc3766e3f20e74b9c5ed651ad44e9e1e52b8a9 Merge: 81422444 dfdb5b95 Author: pdr9rc Date: Thu Apr 30 15:08:25 2020 +0100 Merge branch 'master' of https://github.com/3CORESec/sigma commit 8142244449efd6c62953a8f05e5d8256910ab358 Author: pdr9rc Date: Thu Apr 30 15:08:20 2020 +0100 wip wip commit dfdb5b9550794f0df4bf6015d901226671586be5 Author: Tiago Faria Date: Wed Apr 29 23:59:26 2020 +0100 better description and event.outcome commit ac4a2b1f26df3071af13030731bb384290bf2422 Author: pdr9rc Date: Wed Apr 29 22:55:46 2020 +0100 wip wip commit 9ce84a38e592f6d2163ca5aac90533bca4853981 Author: pdr9rc Date: Wed Apr 29 20:36:45 2020 +0100 overrides section support + one example rule + cloudtrail config ditto --- .github/workflows/sigma-test.yml | 3 + .gitignore | 1 + Makefile | 12 + other/godmode_sigma_rule.yml | 2 +- .../sysmon_process_reimaging.yml | 4 +- rules/cloud/aws_ec2_vm_export_failure.yml | 28 + .../auditd/lnx_auditd_create_account.yml | 22 + .../auditd/lnx_auditd_susp_C2_commands.yml | 21 + rules/linux/lnx_shell_clear_cmd_history.yml | 9 + .../zeek-dce_rpc_domain_user_enumeration.yml | 35 + .../zeek_dce_rpc_mitre_bzar_execution.yml | 2 +- .../zeek_dce_rpc_mitre_bzar_persistence.yml | 2 +- ...k_http_executable_download_from_webdav.yml | 26 + .../zeek_smb_converted_win_atsvc_task.yml | 4 +- ..._smb_converted_win_impacket_secretdump.yml | 4 +- .../zeek_smb_converted_win_lm_namedpipe.yml | 6 +- .../zeek_smb_converted_win_susp_psexec.yml | 4 +- ...verted_win_susp_raccess_sensitive_fext.yml | 2 +- ...ransferring_files_with_credential_data.yml | 2 +- rules/proxy/proxy_turla_comrat.yml | 19 + rules/proxy/proxy_ua_apt.yml | 1 + rules/web/web_cve_2019_3398_confluence.yml | 27 + .../builtin/win_alert_ad_user_backdoors.yml | 8 +- .../builtin/win_susp_add_sid_history.yml | 4 +- .../builtin/win_susp_backup_delete.yml | 2 +- .../deprecated/win_susp_esentutl_activity.yml | 29 + .../malware/win_mal_blue_mockingbird.yml | 45 + .../powershell/powershell_ntfs_ads_access.yml | 1 + .../win_apt_greenbug_may20.yml | 47 + .../win_apt_turla_comrat_may20.yml | 33 + .../win_exploit_cve_2020_1048.yml | 31 + .../win_hktl_createminidump.yml | 2 +- .../win_netsh_allow_port_rdp.yml | 31 + .../process_creation/win_netsh_fw_add.yml | 13 +- .../win_netsh_fw_add_susp_image.yml | 54 + .../win_renamed_jusched.yml} | 0 .../win_renamed_powershell.yml} | 2 +- .../win_renamed_procdump.yml} | 2 +- .../win_renamed_psexec.yml} | 2 +- .../win_susp_crackmapexec_execution.yml | 37 + ...sp_crackmapexec_powershell_obfuscation.yml | 37 + .../win_susp_file_characteristics.yml} | 12 +- .../win_susp_renamed_debugview.yml | 23 + .../win_system_exe_anomaly.yml | 7 + .../win_task_folder_evasion.yml | 1 - .../windows/sysmon/sysmon_ads_executable.yml | 10 +- ..._alternate_powershell_hosts_moduleload.yml | 26 - ...sysmon_alternate_powershell_hosts_pipe.yml | 4 +- .../windows/sysmon/sysmon_cmstp_execution.yml | 1 + .../sysmon/sysmon_creation_system_file.yml | 57 + rules/windows/sysmon/sysmon_cve-2020-1048.yml | 33 +- ...y_events_logging_adding_reg_key_minint.yml | 1 + .../sysmon/sysmon_in_memory_powershell.yml | 3 +- ...sysmon_lsass_memory_dump_file_creation.yml | 2 +- ...ysmon_registry_persistence_key_linking.yml | 1 + ...n_susp_office_dotnet_assembly_dll_load.yml | 10 +- ...sysmon_susp_office_dotnet_gac_dll_load.yml | 10 +- .../sysmon_susp_office_kerberos_dll_load.yml | 10 +- .../sysmon/sysmon_susp_run_key_img_folder.yml | 13 +- .../sysmon_susp_winword_vbadll_load.yml | 14 +- ...ysmon_suspicious_dbghelp_dbgcore_load.yml} | 14 +- ...sysmon_svchost_dll_search_order_hijack.yml | 5 +- .../sysmon_tsclient_filewrite_startup.yml | 2 +- .../windows/sysmon/sysmon_wmi_module_load.yml | 5 +- tests/test_rules.py | 21 +- tools/config/ala.yml | 101 ++ tools/config/arcsight-zeek.yml | 119 +- tools/config/arcsight.yml | 130 +- tools/config/crowdstrike.yml | 19 + tools/config/ecs-cloudtrail.yml | 60 + tools/config/ecs-dns.yml | 69 + tools/config/ecs-proxy.yml | 210 ++- tools/config/ecs-zeek-corelight.yml | 313 ++++- tools/config/elk-defaultindex-filebeat.yml | 2 + tools/config/elk-defaultindex-logstash.yml | 2 + tools/config/elk-defaultindex.yml | 3 + tools/config/elk-linux.yml | 15 + tools/config/elk-windows.yml | 30 + tools/config/elk-winlogbeat-sp.yml | 95 ++ tools/config/elk-winlogbeat.yml | 94 ++ tools/config/filebeat-zeek-ecs.yml | 468 +++++++ tools/config/humio.yml | 625 +++++++++ tools/config/logstash-zeek-default-json.yml | 109 +- tools/config/powershell-windows-all.yml | 62 + tools/config/qradar.yml | 140 +- tools/config/splunk-zeek.yml | 125 +- tools/config/winlogbeat-modules-enabled.yml | 5 +- tools/config/winlogbeat-old.yml | 4 +- tools/config/winlogbeat.yml | 6 +- tools/sigma/backends/ala.py | 270 ++-- tools/sigma/backends/arcsight.py | 2 +- tools/sigma/backends/base.py | 42 +- tools/sigma/backends/carbonblack.py | 7 +- tools/sigma/backends/discovery.py | 2 +- tools/sigma/backends/elasticsearch.py | 83 +- tools/sigma/backends/humio.py | 160 +++ tools/sigma/backends/limacharlie.py | 1218 ++++++++--------- tools/sigma/backends/mdatp.py | 28 + tools/sigma/backends/splunk.py | 38 + tools/sigma/backends/sql.py | 125 +- tools/sigma/backends/sqlite.py | 123 ++ tools/tests/test_backend_sql.py | 334 +++++ tools/tests/test_backend_sqlite.py | 148 ++ 103 files changed, 5285 insertions(+), 1002 deletions(-) create mode 100644 rules/cloud/aws_ec2_vm_export_failure.yml create mode 100644 rules/linux/auditd/lnx_auditd_create_account.yml create mode 100644 rules/linux/auditd/lnx_auditd_susp_C2_commands.yml create mode 100644 rules/network/zeek/zeek-dce_rpc_domain_user_enumeration.yml create mode 100644 rules/network/zeek/zeek_http_executable_download_from_webdav.yml create mode 100644 rules/proxy/proxy_turla_comrat.yml create mode 100644 rules/web/web_cve_2019_3398_confluence.yml create mode 100644 rules/windows/deprecated/win_susp_esentutl_activity.yml create mode 100644 rules/windows/malware/win_mal_blue_mockingbird.yml create mode 100644 rules/windows/process_creation/win_apt_greenbug_may20.yml create mode 100644 rules/windows/process_creation/win_apt_turla_comrat_may20.yml create mode 100644 rules/windows/process_creation/win_exploit_cve_2020_1048.yml create mode 100644 rules/windows/process_creation/win_netsh_allow_port_rdp.yml create mode 100644 rules/windows/process_creation/win_netsh_fw_add_susp_image.yml rename rules/windows/{sysmon/sysmon_renamed_jusched.yml => process_creation/win_renamed_jusched.yml} (100%) rename rules/windows/{sysmon/sysmon_renamed_powershell.yml => process_creation/win_renamed_powershell.yml} (95%) rename rules/windows/{sysmon/sysmon_renamed_procdump.yml => process_creation/win_renamed_procdump.yml} (95%) rename rules/windows/{sysmon/sysmon_renamed_psexec.yml => process_creation/win_renamed_psexec.yml} (96%) create mode 100644 rules/windows/process_creation/win_susp_crackmapexec_execution.yml create mode 100644 rules/windows/process_creation/win_susp_crackmapexec_powershell_obfuscation.yml rename rules/windows/{sysmon/sysmon_susp_file_characteristics.yml => process_creation/win_susp_file_characteristics.yml} (68%) create mode 100644 rules/windows/process_creation/win_susp_renamed_debugview.yml delete mode 100644 rules/windows/sysmon/sysmon_alternate_powershell_hosts_moduleload.yml create mode 100644 rules/windows/sysmon/sysmon_creation_system_file.yml rename rules/windows/sysmon/{sysmon_minidumwritedump_lsass.yml => sysmon_suspicious_dbghelp_dbgcore_load.yml} (79%) create mode 100644 tools/config/ala.yml create mode 100644 tools/config/crowdstrike.yml create mode 100644 tools/config/ecs-cloudtrail.yml create mode 100644 tools/config/ecs-dns.yml create mode 100644 tools/config/elk-defaultindex-filebeat.yml create mode 100644 tools/config/elk-defaultindex-logstash.yml create mode 100644 tools/config/elk-defaultindex.yml create mode 100644 tools/config/elk-linux.yml create mode 100644 tools/config/elk-windows.yml create mode 100644 tools/config/elk-winlogbeat-sp.yml create mode 100644 tools/config/elk-winlogbeat.yml create mode 100644 tools/config/filebeat-zeek-ecs.yml create mode 100644 tools/config/humio.yml create mode 100644 tools/config/powershell-windows-all.yml create mode 100644 tools/sigma/backends/humio.py create mode 100644 tools/sigma/backends/sqlite.py create mode 100644 tools/tests/test_backend_sql.py create mode 100644 tools/tests/test_backend_sqlite.py diff --git a/.github/workflows/sigma-test.yml b/.github/workflows/sigma-test.yml index b6e10159..ee0c317a 100644 --- a/.github/workflows/sigma-test.yml +++ b/.github/workflows/sigma-test.yml @@ -35,3 +35,6 @@ jobs: - name: Test Generated Elasticsearch Query Strings run: | make test-backend-es-qs + - name: Test SQL(ite) Backend + run: | + make test-backend-sql diff --git a/.gitignore b/.gitignore index bf7103a4..13186372 100644 --- a/.gitignore +++ b/.gitignore @@ -94,3 +94,4 @@ settings.json # VisualStudio .vs/ +.vscode/launch.json diff --git a/Makefile b/Makefile index 1ad71351..e4968975 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,11 @@ test-sigmac: $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t elastalert -c tools/config/winlogbeat.yml -O alert_methods=http_post,email -O emails=test@test.invalid -O http_post_url=http://test.invalid rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t elastalert-dsl -c tools/config/winlogbeat.yml -O alert_methods=http_post,email -O emails=test@test.invalid -O http_post_url=http://test.invalid rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t ee-outliers -c tools/config/winlogbeat.yml rules/ > /dev/null + $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t es-qs -c tools/config/ecs-cloudtrail.yml rules/ > /dev/null + $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t es-rule -c tools/config/ecs-cloudtrail.yml rules/ > /dev/null + $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t kibana -c tools/config/ecs-cloudtrail.yml rules/ > /dev/null + $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t xpack-watcher -c tools/config/ecs-cloudtrail.yml rules/ > /dev/null + $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t elastalert -c tools/config/ecs-cloudtrail.yml rules/ > /dev/null ! $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t splunk rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t splunk -c tools/config/splunk-windows-index.yml rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t splunkxml -c tools/config/splunk-windows.yml rules/ > /dev/null @@ -50,7 +55,10 @@ test-sigmac: $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t qualys -c tools/config/qualys.yml rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t netwitness -c tools/config/netwitness.yml rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t sumologic -O rulecomment -c tools/config/sumologic.yml rules/ > /dev/null + $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t humio -O rulecomment -c tools/config/humio.yml rules/ > /dev/null + $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t crowdstrike -O rulecomment -c tools/config/crowdstrike.yml rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t sql -c sysmon rules/ > /dev/null + $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t sqlite -c sysmon rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t logiq -c sysmon rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t splunk -c tools/config/splunk-windows-index.yml -f 'level>=high,level<=critical,status=stable,logsource=windows,tag=attack.execution' rules/ > /dev/null ! $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t splunk -c tools/config/splunk-windows-index.yml -f 'level>=high,level<=critical,status=xstable,logsource=windows' rules/ > /dev/null @@ -100,6 +108,10 @@ test-merge: test-backend-es-qs: tests/test-backend-es-qs.py +test-backend-sql: + cd tools && python3 setup.py install + cd tools && $(COVERAGE) run -m pytest tests/test_backend_sql.py tests/test_backend_sqlite.py + test-sigma2attack: $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigma2attack diff --git a/other/godmode_sigma_rule.yml b/other/godmode_sigma_rule.yml index 218e0484..67969b7b 100644 --- a/other/godmode_sigma_rule.yml +++ b/other/godmode_sigma_rule.yml @@ -104,7 +104,7 @@ logsource: detection: selection_file_creation: EventID: 11 - TargetFileName|contains: + TargetFilename|contains: - '.dmp' # dump process memory - 'Desktop\how' # Ransomware - 'Desktop\decrypt' # Ransomware diff --git a/rules-unsupported/sysmon_process_reimaging.yml b/rules-unsupported/sysmon_process_reimaging.yml index 9d557b06..3da02214 100644 --- a/rules-unsupported/sysmon_process_reimaging.yml +++ b/rules-unsupported/sysmon_process_reimaging.yml @@ -5,7 +5,7 @@ description: Detects process reimaging defense evasion technique # where # selection1: ImageFileName != selection1: OriginalFileName # selection1: ParentProcessGuid = selection2: ProcessGuid -# selection1: Image = selection2: TargetFileName +# selection1: Image = selection2: TargetFilename # and new field ImageFileName is coming from enrichment # selection1: Image = ^.+\\$ # Rule must trigger if selection1 and selection2 both occurs in timeframe of 120 sec. @@ -45,4 +45,4 @@ detection: EventID: 11 fields: - ProcessGuid - - TargetFileName + - TargetFilename diff --git a/rules/cloud/aws_ec2_vm_export_failure.yml b/rules/cloud/aws_ec2_vm_export_failure.yml new file mode 100644 index 00000000..a6db628c --- /dev/null +++ b/rules/cloud/aws_ec2_vm_export_failure.yml @@ -0,0 +1,28 @@ +title: AWS EC2 VM Export Failure +id: 54b9a76a-3c71-4673-b4b3-2edb4566ea7b +status: experimental +description: An attempt to export an AWS EC2 instance has been detected. A VM Export might indicate an attempt to extract information from an instance. +references: + - https://docs.aws.amazon.com/vm-import/latest/userguide/vmexport.html#export-instance +author: Diogo Braz +date: 2020/04/16 +tags: + - attack.collection + - attack.t1005 + - attack.exfiltration + - attack.t1537 +level: low +logsource: + service: cloudtrail +detection: + selection: + eventName: 'CreateInstanceExportTask' + eventSource: 'ec2.amazonaws.com' + filter1: + errorMessage: '*' + filter2: + errorCode: '*' + filter3: + eventName: 'ConsoleLogin' + responseElements: '*Failure*' + condition: selection and (filter1 or filter2 or filter3) diff --git a/rules/linux/auditd/lnx_auditd_create_account.yml b/rules/linux/auditd/lnx_auditd_create_account.yml new file mode 100644 index 00000000..14be30c0 --- /dev/null +++ b/rules/linux/auditd/lnx_auditd_create_account.yml @@ -0,0 +1,22 @@ +title: Creation Of An User Account +id: 759d0d51-bc99-4b5e-9add-8f5b2c8e7512 +status: experimental +description: Detects the creation of a new user account. According to MITRE ATT&CK, "such accounts may be used for persistence that do not require persistent remote access tools to be deployed on the system" +references: + - 'MITRE Attack technique T1136; Create Account ' +date: 2020/05/18 +tags: + - attack.t1136 + - attack.persistence +author: Marie Euler +logsource: + product: linux + service: auditd +detection: + selection: + type: 'SYSCALL' + exe: '*/useradd' + condition: selection +falsepositives: + - Admin activity +level: medium diff --git a/rules/linux/auditd/lnx_auditd_susp_C2_commands.yml b/rules/linux/auditd/lnx_auditd_susp_C2_commands.yml new file mode 100644 index 00000000..77971d06 --- /dev/null +++ b/rules/linux/auditd/lnx_auditd_susp_C2_commands.yml @@ -0,0 +1,21 @@ +title: Suspicious C2 Activities +id: f7158a64-6204-4d6d-868a-6e6378b467e0 +status: experimental +description: Detects suspicious activities as declared by Florian Roth in its 'Best Practice Auditd Configuration'. This includes the detection of the following commands; wget, curl, base64, nc, netcat, ncat, ssh, socat, wireshark, rawshark, rdesktop, nmap. These commands match a few techniques from the tactics "Command and Control", including not exhaustively the following; Application Layer Protocol (T1071), Non-Application Layer Protocol (T1095), Data Encoding (T1132) +references: + - 'https://github.com/Neo23x0/auditd' +date: 2020/05/18 +tags: + - attack.command_and_control +author: Marie Euler +logsource: + product: linux + service: auditd +detection: + selection: + key: + - 'susp_activity' + condition: selection +falsepositives: + - Admin or User activity +level: medium diff --git a/rules/linux/lnx_shell_clear_cmd_history.yml b/rules/linux/lnx_shell_clear_cmd_history.yml index 9ee72f09..97379f6a 100644 --- a/rules/linux/lnx_shell_clear_cmd_history.yml +++ b/rules/linux/lnx_shell_clear_cmd_history.yml @@ -2,12 +2,20 @@ title: Clear Command History id: fdc88d25-96fb-4b7c-9633-c0e417fdbd4e status: experimental description: Clear command history in linux which is used for defense evasion. + # Example config for this one (place it in .bash_profile): + # (is_empty=false; inotifywait -m .bash_history | while read file; do if [ $(wc -l <.bash_history) -lt 1 ]; then if [ "$is_empty" = false ]; then logger -i -p local5.info -t empty_bash_history "$USER : ~/.bash_history is empty "; is_empty=true; fi; else is_empty=false; fi; done ) & + # It monitors the size of .bash_history and log the words "empty_bash_history" whenever a previously not empty bash_history becomes empty + # We define an empty file as a document with 0 or 1 lines (it can be a line with only one space character for example) + # It has two advantages over the version suggested by Patrick Bareiss : + # - it is not relative to the exact command used to clear .bash_history : for instance Caldera uses "> .bash_history" to clear the history and this is not one the commands listed here. We can't be exhaustive for all the possibilities ! + # - the method suggested by Patrick Bareiss logs all the commands entered directly in a bash shell. therefore it may miss some events (for instance it doesn't log the commands launched from a Caldera agent). Here if .bash_history is cleared, it will always be detected references: - https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1146/T1146.yaml - https://attack.mitre.org/techniques/T1146/ - https://www.hackers-arise.com/single-post/2016/06/20/Covering-your-BASH-Shell-Tracks-AntiForensics author: Patrick Bareiss date: 2019/03/24 +modified: 2020/05/28 logsource: product: linux detection: @@ -22,6 +30,7 @@ detection: - 'history -c' - 'history -w' - 'shred *bash_history' + - 'empty_bash_history' condition: keywords falsepositives: - Unknown diff --git a/rules/network/zeek/zeek-dce_rpc_domain_user_enumeration.yml b/rules/network/zeek/zeek-dce_rpc_domain_user_enumeration.yml new file mode 100644 index 00000000..bfaa398f --- /dev/null +++ b/rules/network/zeek/zeek-dce_rpc_domain_user_enumeration.yml @@ -0,0 +1,35 @@ +title: Domain User Enumeration Network Recon 01 +description: Domain user and group enumeration via network reconnaissance. Seen in APT 29 and other common tactics and actors. Detects a set of RPC (remote procedure calls) used to enumerate a domain controller. The rule was created based off the datasets and hackathon from https://github.com/OTRF/detection-hackathon-apt29 +id: 66a0bdc6-ee04-441a-9125-99d2eb547942 +references: + - "https://github.com/OTRF/detection-hackathon-apt29" + - "https://github.com/OTRF/detection-hackathon-apt29/issues/37" +author: 'Nate Guagenti (@neu5ron), Open Threat Research (OTR)' +date: 2020/05/03 +modified: 2020/05/03 +tags: + - attack.discovery + - attack.t1087 + - attack.t1082 +logsource: + product: zeek + service: dce_rpc +detection: + selection: + operation: + #- LsarEnumerateTrustedDomains #potentially too many FPs, removing. caused by netlogon + #- SamrEnumerateDomainsInSamServer #potentially too many FPs, removing. #method obtains a listing of all domains hosted by the server side of this protocol. This value is a cookie that the server can use to continue an enumeration on a subsequent call + - LsarLookupNames3 #method translates a batch of security principal names to their SID form + - LsarLookupSids3 #translates a batch of security principal SIDs to their name forms + - SamrGetGroupsForUser #obtains a listing of groups that a user is a member of + - SamrLookupIdsInDomain #method translates a set of RIDs into account names + - SamrLookupNamesInDomain #method translates a set of account names into a set of RIDs + - SamrQuerySecurityObject #method queries the access control on a server, domain, user, group, or alias object + - SamrQueryInformationGroup #obtains attributes from a group object + timeframe: 30s + condition: selection | count(operation) by src_ip > 4 +falsepositives: + - Devices that may do authentication like a VPN or a firewall that looksup IPs to username + - False positives depend on scripts and administrative tools used in the monitored environment +level: medium +status: experimental \ No newline at end of file diff --git a/rules/network/zeek/zeek_dce_rpc_mitre_bzar_execution.yml b/rules/network/zeek/zeek_dce_rpc_mitre_bzar_execution.yml index a4494f03..4e79ed02 100644 --- a/rules/network/zeek/zeek_dce_rpc_mitre_bzar_execution.yml +++ b/rules/network/zeek/zeek_dce_rpc_mitre_bzar_execution.yml @@ -1,7 +1,7 @@ title: MITRE BZAR Indicators for ATT&CK Execution id: b640c0b8-87f8-4daa-aef8-95a24261dd1d description: 'Windows DCE-RPC functions which indicate an ATT&CK-like Execution techniques on the remote system. All credit for the Zeek mapping of the suspicious endpoint/operation field goes to MITRE.' -author: '@neu5ron, @SOC_Prime' +author: '@neu5ron, SOC Prime' date: 2020/03/19 references: - https://github.com/mitre-attack/bzar#indicators-for-attck-execution diff --git a/rules/network/zeek/zeek_dce_rpc_mitre_bzar_persistence.yml b/rules/network/zeek/zeek_dce_rpc_mitre_bzar_persistence.yml index cfeffe91..3cce80d4 100644 --- a/rules/network/zeek/zeek_dce_rpc_mitre_bzar_persistence.yml +++ b/rules/network/zeek/zeek_dce_rpc_mitre_bzar_persistence.yml @@ -1,7 +1,7 @@ title: MITRE BZAR Indicators for ATT&CK Persistence id: 53389db6-ba46-48e3-a94c-e0f2cefe1583 description: 'Windows DCE-RPC functions which indicate an ATT&CK-like Persistence techniques on the remote system. All credit for the Zeek mapping of the suspicious endpoint/operation field goes to MITRE.' -author: '@neu5ron, @SOC_Prime' +author: '@neu5ron, SOC Prime' date: 2020/03/19 references: - https://github.com/mitre-attack/bzar#indicators-for-attck-persistence diff --git a/rules/network/zeek/zeek_http_executable_download_from_webdav.yml b/rules/network/zeek/zeek_http_executable_download_from_webdav.yml new file mode 100644 index 00000000..47cfdcbf --- /dev/null +++ b/rules/network/zeek/zeek_http_executable_download_from_webdav.yml @@ -0,0 +1,26 @@ +title: Executable from Webdav +description: "Detects executable access via webdav6. Can be seen in APT 29 such as from the emulated APT 29 hackathon https://github.com/OTRF/detection-hackathon-apt29/" +id: aac2fd97-bcba-491b-ad66-a6edf89c71bf +author: 'SOC Prime, Adam Swan' +references: + - http://carnal0wnage.attackresearch.com/2012/06/webdav-server-to-download-custom.html + - https://github.com/OTRF/detection-hackathon-apt29 +tags: + - attack.command_and_control + - attack.t1043 +logsource: + product: zeek + service: http +date: 2020/05/01 +detection: + selection_webdav: + - c-useragent: '*WebDAV*' + - c-uri: '*webdav*' + selection_executable: + - resp_mime_types: '*dosexec*' + - c-uri: '*.exe' + condition: selection_webdav AND selection_executable +falsepositives: + - unknown +level: medium +status: experimental \ No newline at end of file diff --git a/rules/network/zeek/zeek_smb_converted_win_atsvc_task.yml b/rules/network/zeek/zeek_smb_converted_win_atsvc_task.yml index 69ef0801..17a3704f 100644 --- a/rules/network/zeek/zeek_smb_converted_win_atsvc_task.yml +++ b/rules/network/zeek/zeek_smb_converted_win_atsvc_task.yml @@ -16,8 +16,8 @@ logsource: service: smb_files detection: selection: - name: \\*\IPC$ - path: atsvc + path: \\*\IPC$ + name: atsvc #Accesses: '*WriteData*' condition: selection falsepositives: diff --git a/rules/network/zeek/zeek_smb_converted_win_impacket_secretdump.yml b/rules/network/zeek/zeek_smb_converted_win_impacket_secretdump.yml index 35552f34..16e2f318 100644 --- a/rules/network/zeek/zeek_smb_converted_win_impacket_secretdump.yml +++ b/rules/network/zeek/zeek_smb_converted_win_impacket_secretdump.yml @@ -13,8 +13,8 @@ logsource: service: smb_files detection: selection: - name: '\\*ADMIN$' - path: '*SYSTEM32\\*.tmp' + path: '\\*ADMIN$' + name: '*SYSTEM32\\*.tmp' condition: selection falsepositives: - 'unknown' diff --git a/rules/network/zeek/zeek_smb_converted_win_lm_namedpipe.yml b/rules/network/zeek/zeek_smb_converted_win_lm_namedpipe.yml index 1b0b92b5..eecef7a9 100644 --- a/rules/network/zeek/zeek_smb_converted_win_lm_namedpipe.yml +++ b/rules/network/zeek/zeek_smb_converted_win_lm_namedpipe.yml @@ -14,10 +14,10 @@ logsource: service: smb_files detection: selection1: - name: \\*\IPC$ + path: \\*\IPC$ selection2: - name: \\*\IPC$ - path: + path: \\*\IPC$ + name: - 'atsvc' - 'samr' - 'lsarpc' diff --git a/rules/network/zeek/zeek_smb_converted_win_susp_psexec.yml b/rules/network/zeek/zeek_smb_converted_win_susp_psexec.yml index 2086a287..044d6f96 100644 --- a/rules/network/zeek/zeek_smb_converted_win_susp_psexec.yml +++ b/rules/network/zeek/zeek_smb_converted_win_susp_psexec.yml @@ -13,8 +13,8 @@ logsource: service: smb_files detection: selection1: - name: \\*\IPC$ - path: + path: \\*\IPC$ + name: - '*-stdin' - '*-stdout' - '*-stderr' diff --git a/rules/network/zeek/zeek_smb_converted_win_susp_raccess_sensitive_fext.yml b/rules/network/zeek/zeek_smb_converted_win_susp_raccess_sensitive_fext.yml index 95045f9d..fa7f41f0 100644 --- a/rules/network/zeek/zeek_smb_converted_win_susp_raccess_sensitive_fext.yml +++ b/rules/network/zeek/zeek_smb_converted_win_susp_raccess_sensitive_fext.yml @@ -11,7 +11,7 @@ logsource: service: smb_files detection: selection: - path: + name: - '*.pst' - '*.ost' - '*.msg' diff --git a/rules/network/zeek/zeek_smb_converted_win_transferring_files_with_credential_data.yml b/rules/network/zeek/zeek_smb_converted_win_transferring_files_with_credential_data.yml index 7724e097..060189f4 100644 --- a/rules/network/zeek/zeek_smb_converted_win_transferring_files_with_credential_data.yml +++ b/rules/network/zeek/zeek_smb_converted_win_transferring_files_with_credential_data.yml @@ -13,7 +13,7 @@ logsource: service: smb_files detection: selection: - path: + name: - '\mimidrv' - '\lsass' - '\windows\minidump\' diff --git a/rules/proxy/proxy_turla_comrat.yml b/rules/proxy/proxy_turla_comrat.yml new file mode 100644 index 00000000..3a743adb --- /dev/null +++ b/rules/proxy/proxy_turla_comrat.yml @@ -0,0 +1,19 @@ +title: Turla ComRAT +id: 7857f021-007f-4928-8b2c-7aedbe64bb82 +status: experimental +description: Detects Turla ComRAT patterns +references: + - https://www.welivesecurity.com/wp-content/uploads/2020/05/ESET_Turla_ComRAT.pdf +author: Florian Roth +date: 2020/05/26 +tags: + - attack.g0010 +logsource: + category: proxy +detection: + selection: + c-uri|contains: '/index/index.php?h=' + condition: selection +falsepositives: + - Unknown +level: critical diff --git a/rules/proxy/proxy_ua_apt.yml b/rules/proxy/proxy_ua_apt.yml index d8328ce9..0baf02b2 100644 --- a/rules/proxy/proxy_ua_apt.yml +++ b/rules/proxy/proxy_ua_apt.yml @@ -46,6 +46,7 @@ detection: - 'hots scot' # Unkown iOS zero-day implant https://twitter.com/craiu/status/1176437994288484352?s=20 - 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT)' # https://blog.telsy.com/meeting-powerband-the-apt33-net-powerton-variant/ - 'Mozilla/5.0 (Windows NT 6.1; WOW64) Chrome/28.0.1500.95 Safari/537.36' # Hidden Cobra malware + - 'Mozilla/5.0 (Windows NT 6.2; Win32; rv:47.0)' # Strong Pity loader https://twitter.com/VK_Intel/status/1264185981118406657 condition: selection fields: - ClientIP diff --git a/rules/web/web_cve_2019_3398_confluence.yml b/rules/web/web_cve_2019_3398_confluence.yml new file mode 100644 index 00000000..35252909 --- /dev/null +++ b/rules/web/web_cve_2019_3398_confluence.yml @@ -0,0 +1,27 @@ +title: Confluence Exploitation CVE-2019-3398 +id: e9bc39ae-978a-4e49-91ab-5bd481fc668b +status: experimental +description: Detects the exploitation of the Confluence vulnerability described in CVE-2019-3398 +references: + - https://devcentral.f5.com/s/articles/confluence-arbitrary-file-write-via-path-traversal-cve-2019-3398-34181 +author: Florian Roth +date: 2020/05/26 +tags: + - attack.initial_access + - attack.t1190 +logsource: + category: webserver +detection: + selection: + cs-method: 'POST' + c-uri|contains|all: + - '/upload.action' + - 'filename=../../../../' + condition: selection +fields: + - c-ip + - c-dns +falsepositives: + - Unknown +level: critical + diff --git a/rules/windows/builtin/win_alert_ad_user_backdoors.yml b/rules/windows/builtin/win_alert_ad_user_backdoors.yml index 217b73a4..9ce1e7e7 100644 --- a/rules/windows/builtin/win_alert_ad_user_backdoors.yml +++ b/rules/windows/builtin/win_alert_ad_user_backdoors.yml @@ -19,10 +19,10 @@ logsource: detection: selection1: EventID: 4738 + filter_null: + AllowedToDelegateTo: null filter1: - AllowedToDelegateTo: - - null - - '-' + AllowedToDelegateTo: '-' selection2: EventID: 5136 AttributeLDAPDisplayName: 'msDS-AllowedToDelegateTo' @@ -33,7 +33,7 @@ detection: selection4: EventID: 5136 AttributeLDAPDisplayName: 'msDS-AllowedToActOnBehalfOfOtherIdentity' - condition: (selection1 and not 1 of filter*) or selection2 or selection3 or selection4 + condition: (selection1 and not filter1 and not filter_null) or selection2 or selection3 or selection4 falsepositives: - Unknown level: high diff --git a/rules/windows/builtin/win_susp_add_sid_history.yml b/rules/windows/builtin/win_susp_add_sid_history.yml index 21ac8c61..0a407a6e 100644 --- a/rules/windows/builtin/win_susp_add_sid_history.yml +++ b/rules/windows/builtin/win_susp_add_sid_history.yml @@ -24,7 +24,9 @@ detection: SidHistory: - '-' - '%%1793' - condition: selection1 or (selection2 and not selection3) + filter_null: + SidHistory: null + condition: selection1 or (selection2 and not selection3 and not filter_null) falsepositives: - Migration of an account into a new domain level: medium diff --git a/rules/windows/builtin/win_susp_backup_delete.yml b/rules/windows/builtin/win_susp_backup_delete.yml index 7741c3eb..32dfb5d0 100644 --- a/rules/windows/builtin/win_susp_backup_delete.yml +++ b/rules/windows/builtin/win_susp_backup_delete.yml @@ -16,7 +16,7 @@ logsource: detection: selection: EventID: 524 - Source: Backup + Source: Microsoft-Windows-Backup condition: selection falsepositives: - Unknown diff --git a/rules/windows/deprecated/win_susp_esentutl_activity.yml b/rules/windows/deprecated/win_susp_esentutl_activity.yml new file mode 100644 index 00000000..1e3e62db --- /dev/null +++ b/rules/windows/deprecated/win_susp_esentutl_activity.yml @@ -0,0 +1,29 @@ +title: Suspicious Esentutl Use +id: 56a8189f-11b2-48c8-8ca7-c54b03c2fbf7 +status: experimental +description: Detects flags often used with the LOLBAS Esentutl for malicious activity. It could be used in rare cases by administrators to access locked files or during maintenance. +author: Florian Roth +date: 2020/05/23 +references: + - https://lolbas-project.github.io/ + - https://twitter.com/chadtilbury/status/1264226341408452610 +tags: + - attack.defense_evasion + - attack.execution + - attack.s0404 + - attack.t1218 +logsource: + category: process_creation + product: windows +detection: + selection: + CommandLine|contains|all: + - ' /vss ' + - ' /y ' + condition: selection +fields: + - CommandLine + - ParentCommandLine +falsepositives: + - Administrative activity +level: high diff --git a/rules/windows/malware/win_mal_blue_mockingbird.yml b/rules/windows/malware/win_mal_blue_mockingbird.yml new file mode 100644 index 00000000..c40f28d7 --- /dev/null +++ b/rules/windows/malware/win_mal_blue_mockingbird.yml @@ -0,0 +1,45 @@ +action: global +title: Blue Mockingbird +id: c3198a27-23a0-4c2c-af19-e5328d49680e +status: experimental +description: Attempts to detect system changes made by Blue Mockingbird +references: + - https://redcanary.com/blog/blue-mockingbird-cryptominer/ +tags: + - attack.execution + - attack.t1112 + - attack.t1047 +author: Trent Liffick (@tliffick) +date: 2020/05/14 +falsepositives: + - unknown +level: high +detection: + condition: 1 of them +--- +logsource: + category: process_creation + product: windows +detection: + exec_selection: + Image|endswith: '\cmd.exe' + CommandLine|contains|all: + - 'sc config' + - 'wercplsupporte.dll' +--- +logsource: + category: process_creation + product: windows +detection: + wmic_cmd: + Image|endswith: '\wmic.exe' + CommandLine|endswith: 'COR_PROFILER' +--- +logsource: + product: windows + service: sysmon +detection: + mod_reg: + EventID: 13 + TargetObject|endswith: + - '\CurrentControlSet\Services\wercplsupport\Parameters\ServiceDll' diff --git a/rules/windows/powershell/powershell_ntfs_ads_access.yml b/rules/windows/powershell/powershell_ntfs_ads_access.yml index 422ed4ea..e2c531b7 100644 --- a/rules/windows/powershell/powershell_ntfs_ads_access.yml +++ b/rules/windows/powershell/powershell_ntfs_ads_access.yml @@ -16,6 +16,7 @@ logsource: detection: keyword1: - "set-content" + - "add-content" keyword2: - "-stream" condition: keyword1 and keyword2 diff --git a/rules/windows/process_creation/win_apt_greenbug_may20.yml b/rules/windows/process_creation/win_apt_greenbug_may20.yml new file mode 100644 index 00000000..8c630baa --- /dev/null +++ b/rules/windows/process_creation/win_apt_greenbug_may20.yml @@ -0,0 +1,47 @@ +title: Greenbug Campaign Indicators +id: 3711eee4-a808-4849-8a14-faf733da3612 +status: experimental +description: Detects tools and process executions as observed in a Greenbug campaign in May 2020 +references: + - https://symantec-enterprise-blogs.security.com/blogs/threat-intelligence/greenbug-espionage-telco-south-asia +author: Florian Roth +date: 2020/05/20 +modified: 2020/05/21 +tags: + - attack.g0049 +logsource: + category: process_creation + product: windows +detection: + selection1: + CommandLine|contains|all: + - 'bitsadmin /transfer' + - 'CSIDL_APPDATA' + selection2: + CommandLine|contains: + - 'CSIDL_SYSTEM_DRIVE' + selection3: + CommandLine|contains: + - '\msf.ps1' + - '8989 -e cmd.exe' + - 'system.Data.SqlClient.SqlDataAdapter($cmd); [void]$da.fill' + - '-nop -w hidden -c $k=new-object' + - '[Net.CredentialCache]::DefaultCredentials;IEX ' + - ' -nop -w hidden -c $m=new-object net.webclient;$m' + - '-noninteractive -executionpolicy bypass whoami' + - '-noninteractive -executionpolicy bypass netstat -a' + - 'L3NlcnZlc' # base64 encoded '/server=' + selection4: + Image|endswith: + - '\adobe\Adobe.exe' + - '\oracle\local.exe' + - '\revshell.exe' + - 'infopagesbackup\ncat.exe' + - 'CSIDL_SYSTEM\cmd.exe' + - '\programdata\oracle\java.exe' + - 'CSIDL_COMMON_APPDATA\comms\comms.exe' + - '\Programdata\VMware\Vmware.exe' + condition: 1 of them +falsepositives: + - Unknown +level: critical diff --git a/rules/windows/process_creation/win_apt_turla_comrat_may20.yml b/rules/windows/process_creation/win_apt_turla_comrat_may20.yml new file mode 100644 index 00000000..c2b7bf87 --- /dev/null +++ b/rules/windows/process_creation/win_apt_turla_comrat_may20.yml @@ -0,0 +1,33 @@ +title: Turla Group Commands May 2020 +id: 9e2e51c5-c699-4794-ba5a-29f5da40ac0c +status: experimental +description: Detects commands used by Turla group as reported by ESET in May 2020 +references: + - https://www.welivesecurity.com/wp-content/uploads/2020/05/ESET_Turla_ComRAT.pdf +tags: + - attack.g0010 + - attack.execution + - attack.t1086 + - attack.t1053 + - attack.t1027 + - attack.discovery + - attack.t1016 +author: Florian Roth +date: 2020/05/26 +logsource: + category: process_creation + product: windows +falsepositives: + - Unknown +detection: + selection1: + CommandLine|contains: + - 'tracert -h 10 yahoo.com' + - '.WSqmCons))|iex;' + - 'Fr`omBa`se6`4Str`ing' + selection2: + CommandLine|contains|all: + - 'net use https://docs.live.net' + - '@aol.co.uk' + condition: 1 of them +level: critical diff --git a/rules/windows/process_creation/win_exploit_cve_2020_1048.yml b/rules/windows/process_creation/win_exploit_cve_2020_1048.yml new file mode 100644 index 00000000..9f11649f --- /dev/null +++ b/rules/windows/process_creation/win_exploit_cve_2020_1048.yml @@ -0,0 +1,31 @@ +title: Suspicious PrinterPorts Creation (CVE-2020-1048) +id: cc08d590-8b90-413a-aff6-31d1a99678d7 +status: experimental +description: Detects new commands that add new printer port which point to suspicious file +author: EagleEye Team, Florian Roth +date: 2020/05/13 +modified: 2020/05/23 +references: + - https://windows-internals.com/printdemon-cve-2020-1048/ +tags: + - attack.persistence + - attack.execution +logsource: + category: process_creation + product: windows +detection: + selection1: + CommandLine|contains: + - 'Add-PrinterPort -Name' + selection2: + CommandLine|contains: + - '.exe' + - '.dll' + - '.bat' + selection3: + CommandLine|contains: + - 'Generic / Text Only' + condition: ( selection1 and selection2 ) or selection3 +falsepositives: + - New printer port install on host +level: high diff --git a/rules/windows/process_creation/win_hktl_createminidump.yml b/rules/windows/process_creation/win_hktl_createminidump.yml index a0e556d8..6129c97a 100644 --- a/rules/windows/process_creation/win_hktl_createminidump.yml +++ b/rules/windows/process_creation/win_hktl_createminidump.yml @@ -29,5 +29,5 @@ logsource: detection: selection: EventID: 11 - TargetFileName|contains: '*\lsass.dmp' + TargetFilename|contains: '*\lsass.dmp' condition: 1 of them diff --git a/rules/windows/process_creation/win_netsh_allow_port_rdp.yml b/rules/windows/process_creation/win_netsh_allow_port_rdp.yml new file mode 100644 index 00000000..f2fc0607 --- /dev/null +++ b/rules/windows/process_creation/win_netsh_allow_port_rdp.yml @@ -0,0 +1,31 @@ +title: Netsh RDP Port Opening +id: 01aeb693-138d-49d2-9403-c4f52d7d3d62 +description: Detects netsh commands that opens the port 3389 used for RDP, used in Sarwent Malware +references: + - https://labs.sentinelone.com/sarwent-malware-updates-command-detonation/ +date: 2020/05/23 +tags: + - attack.command_and_control + - attack.t1076 +status: experimental +author: Sander Wiebing +logsource: + category: process_creation + product: windows +detection: + selection1: + CommandLine|contains|all: + - netsh + - firewall add portopening + - tcp 3389 + selection2: + CommandLine|contains|all: + - netsh + - advfirewall firewall add rule + - action=allow + - protocol=TCP + - localport=3389 + condition: 1 of them +falsepositives: + - Legitimate administration +level: high diff --git a/rules/windows/process_creation/win_netsh_fw_add.yml b/rules/windows/process_creation/win_netsh_fw_add.yml index 7657dd25..59c3361f 100644 --- a/rules/windows/process_creation/win_netsh_fw_add.yml +++ b/rules/windows/process_creation/win_netsh_fw_add.yml @@ -1,4 +1,4 @@ -title: Netsh +title: Netsh Port or Application Allowed id: cd5cfd80-aa5f-44c0-9c20-108c4ae12e3c description: Allow Incoming Connections by Port or Application on Windows Firewall references: @@ -10,15 +10,18 @@ tags: - attack.command_and_control - attack.t1090 status: experimental -author: Markus Neis +author: Markus Neis, Sander Wiebing logsource: category: process_creation product: windows detection: - selection: + selection1: CommandLine: - - '*netsh firewall add*' - condition: selection + - '*netsh*' + selection2: + CommandLine: + - '*firewall add*' + condition: selection1 and selection2 falsepositives: - Legitimate administration level: medium diff --git a/rules/windows/process_creation/win_netsh_fw_add_susp_image.yml b/rules/windows/process_creation/win_netsh_fw_add_susp_image.yml new file mode 100644 index 00000000..bc54696c --- /dev/null +++ b/rules/windows/process_creation/win_netsh_fw_add_susp_image.yml @@ -0,0 +1,54 @@ +title: Netsh Program Allowed with Suspcious Location +id: a35f5a72-f347-4e36-8895-9869b0d5fc6d +description: Detects Netsh commands that allows a suspcious application location on Windows Firewall +references: + - https://www.virusradar.com/en/Win32_Kasidet.AD/description + - https://www.hybrid-analysis.com/sample/07e789f4f2f3259e7559fdccb36e96814c2dbff872a21e1fa03de9ee377d581f?environmentId=100 +date: 2020/05/25 +tags: + - attack.lateral_movement + - attack.command_and_control + - attack.t1090 +status: experimental +author: Sander Wiebing +logsource: + category: process_creation + product: windows +detection: + selection1: + CommandLine|contains|all: + - 'netsh' + - 'firewall add allowedprogram' + selection2: + CommandLine|contains|all: + - netsh + - advfirewall firewall add rule + - action=allow + - program= + susp_image: + CommandLine|contains: + - '*%TEMP%*' + - '*:\RECYCLER\\*' + - '*C:\$Recycle.bin\\*' + - '*:\SystemVolumeInformation\\*' + - 'C:\\Windows\\Tasks\\*' + - 'C:\\Windows\\debug\\*' + - 'C:\\Windows\\fonts\\*' + - 'C:\\Windows\\help\\*' + - 'C:\\Windows\\drivers\\*' + - 'C:\\Windows\\addins\\*' + - 'C:\\Windows\\cursors\\*' + - 'C:\\Windows\\system32\tasks\\*' + - '*C:\Windows\Temp\\*' + - '*C:\Temp\\*' + - '*C:\Users\Public\\*' + - '%Public%\\*' + - '*C:\Users\Default\\*' + - '*C:\Users\Desktop\\*' + - '*\Downloads\\*' + - '*\Temporary Internet Files\Content.Outlook\\*' + - '*\Local Settings\Temporary Internet Files\\*' + condition: (selection1 or selection2) and susp_image +falsepositives: + - Legitimate administration +level: high diff --git a/rules/windows/sysmon/sysmon_renamed_jusched.yml b/rules/windows/process_creation/win_renamed_jusched.yml similarity index 100% rename from rules/windows/sysmon/sysmon_renamed_jusched.yml rename to rules/windows/process_creation/win_renamed_jusched.yml diff --git a/rules/windows/sysmon/sysmon_renamed_powershell.yml b/rules/windows/process_creation/win_renamed_powershell.yml similarity index 95% rename from rules/windows/sysmon/sysmon_renamed_powershell.yml rename to rules/windows/process_creation/win_renamed_powershell.yml index 157f5876..9522fcee 100644 --- a/rules/windows/sysmon/sysmon_renamed_powershell.yml +++ b/rules/windows/process_creation/win_renamed_powershell.yml @@ -10,7 +10,7 @@ tags: - car.2013-05-009 logsource: product: windows - service: sysmon + category: process_creation detection: selection: Description: 'Windows PowerShell' diff --git a/rules/windows/sysmon/sysmon_renamed_procdump.yml b/rules/windows/process_creation/win_renamed_procdump.yml similarity index 95% rename from rules/windows/sysmon/sysmon_renamed_procdump.yml rename to rules/windows/process_creation/win_renamed_procdump.yml index 803ad339..2fbe3a4a 100644 --- a/rules/windows/sysmon/sysmon_renamed_procdump.yml +++ b/rules/windows/process_creation/win_renamed_procdump.yml @@ -11,7 +11,7 @@ tags: - attack.t1036 logsource: product: windows - service: sysmon + category: process_creation detection: selection: OriginalFileName: 'procdump' diff --git a/rules/windows/sysmon/sysmon_renamed_psexec.yml b/rules/windows/process_creation/win_renamed_psexec.yml similarity index 96% rename from rules/windows/sysmon/sysmon_renamed_psexec.yml rename to rules/windows/process_creation/win_renamed_psexec.yml index 75d5838a..208af0d3 100644 --- a/rules/windows/sysmon/sysmon_renamed_psexec.yml +++ b/rules/windows/process_creation/win_renamed_psexec.yml @@ -10,7 +10,7 @@ tags: - car.2013-05-009 logsource: product: windows - service: sysmon + category: process_creation detection: selection: Description: 'Execute processes remotely' diff --git a/rules/windows/process_creation/win_susp_crackmapexec_execution.yml b/rules/windows/process_creation/win_susp_crackmapexec_execution.yml new file mode 100644 index 00000000..ed8904ba --- /dev/null +++ b/rules/windows/process_creation/win_susp_crackmapexec_execution.yml @@ -0,0 +1,37 @@ +title: CrackMapExec Command Execution +id: 058f4380-962d-40a5-afce-50207d36d7e2 +status: experimental +description: Detect various execution methods of the CrackMapExec pentesting framework +references: + - https://github.com/byt3bl33d3r/CrackMapExec +tags: + - attack.execution + - attack.t1047 + - attack.t1053 + - attack.t1086 +author: Thomas Patzke +date: 2020/05/22 +logsource: + category: process_creation + product: windows +detection: + selection: + CommandLine: + # cme/protocols/smb/wmiexec.py (generalized execute_remote and execute_fileless) + - '*cmd.exe /Q /c * 1> \\\\*\\*\\* 2>&1' + # cme/protocols/smb/atexec.py:109 (fileless output via share) + - '*cmd.exe /C * > \\\\*\\*\\* 2>&1' + # cme/protocols/smb/atexec.py:111 (fileless output via share) + - '*cmd.exe /C * > *\\Temp\\* 2>&1' + # cme/helpers/powershell.py:139 (PowerShell execution with obfuscation) + - '*powershell.exe -exec bypass -noni -nop -w 1 -C "*' + # cme/helpers/powershell.py:149 (PowerShell execution without obfuscation) + - '*powershell.exe -noni -nop -w 1 -enc *' + condition: selection +fields: + - ComputerName + - User + - CommandLine +falsepositives: + - Unknown +level: high diff --git a/rules/windows/process_creation/win_susp_crackmapexec_powershell_obfuscation.yml b/rules/windows/process_creation/win_susp_crackmapexec_powershell_obfuscation.yml new file mode 100644 index 00000000..0d943703 --- /dev/null +++ b/rules/windows/process_creation/win_susp_crackmapexec_powershell_obfuscation.yml @@ -0,0 +1,37 @@ +title: CrackMapExec PowerShell Obfuscation +id: 6f8b3439-a203-45dc-a88b-abf57ea15ccf +status: experimental +description: The CrachMapExec pentesting framework implements a PowerShell obfuscation with some static strings detected by this rule. +references: + - https://github.com/byt3bl33d3r/CrackMapExec + - https://github.com/byt3bl33d3r/CrackMapExec/blob/0a49f75347b625e81ee6aa8c33d3970b5515ea9e/cme/helpers/powershell.py#L242 +tags: + - attack.execution + - attack.t1086 + - attack.defense_evasion + - attack.t1027 +author: Thomas Patzke +date: 2020/05/22 +logsource: + category: process_creation + product: windows +detection: + powershell_execution: + CommandLine|contains: 'powershell.exe' + snippets: + CommandLine|contains: + - 'join*split' + # Line 343ff + - "( $ShellId[1]+$ShellId[13]+'x')" + - '( $PSHome[*]+$PSHOME[*]+' + - "( $env:Public[13]+$env:Public[5]+'x')" + - "( $env:ComSpec[4,*,25]-Join'')" + - "[1,3]+'x'-Join'')" + condition: powershell_execution and snippets +fields: + - ComputerName + - User + - CommandLine +falsepositives: + - Unknown +level: high diff --git a/rules/windows/sysmon/sysmon_susp_file_characteristics.yml b/rules/windows/process_creation/win_susp_file_characteristics.yml similarity index 68% rename from rules/windows/sysmon/sysmon_susp_file_characteristics.yml rename to rules/windows/process_creation/win_susp_file_characteristics.yml index 27359b18..8243fe88 100644 --- a/rules/windows/sysmon/sysmon_susp_file_characteristics.yml +++ b/rules/windows/process_creation/win_susp_file_characteristics.yml @@ -1,20 +1,20 @@ title: Suspicious File Characteristics Due to Missing Fields id: 9637e8a5-7131-4f7f-bdc7-2b05d8670c43 -description: Detects Executables without FileVersion,Description,Product,Company likely created with py2exe +description: Detects Executables in the Downloads folder without FileVersion,Description,Product,Company likely created with py2exe status: experimental references: - https://securelist.com/muddywater/88059/ - https://www.virustotal.com/#/file/276a765a10f98cda1a38d3a31e7483585ca3722ecad19d784441293acf1b7beb/detection -author: Markus Neis +author: Markus Neis, Sander Wiebing date: 2018/11/22 -modified: 2019/11/09 +modified: 2020/05/26 tags: - attack.defense_evasion - attack.execution - attack.t1064 logsource: product: windows - service: sysmon + category: process_creation detection: selection1: Description: '\?' @@ -25,7 +25,9 @@ detection: selection3: Description: '\?' Company: '\?' - condition: 1 of them + folder: + Image: '*\Downloads\\*' + condition: (selection1 or selection2 or selection3) and folder fields: - CommandLine - ParentCommandLine diff --git a/rules/windows/process_creation/win_susp_renamed_debugview.yml b/rules/windows/process_creation/win_susp_renamed_debugview.yml new file mode 100644 index 00000000..dcab5bd6 --- /dev/null +++ b/rules/windows/process_creation/win_susp_renamed_debugview.yml @@ -0,0 +1,23 @@ +title: Renamed SysInternals Debug View +id: cd764533-2e07-40d6-a718-cfeec7f2da7f +status: experimental +description: Detects suspicious renamed SysInternals DebugView execution +references: + - https://www.epicturla.com/blog/sysinturla +author: Florian Roth +date: 2020/05/28 +logsource: + category: process_creation + product: windows +detection: + selection: + Product: + - 'Sysinternals DebugView' + - 'Sysinternals Debugview' + filter: + OriginalFilename: 'Dbgview.exe' + Image|endswith: '\Dbgview.exe' + condition: selection and not filter +falsepositives: + - Unknown +level: high diff --git a/rules/windows/process_creation/win_system_exe_anomaly.yml b/rules/windows/process_creation/win_system_exe_anomaly.yml index da242270..809970e8 100644 --- a/rules/windows/process_creation/win_system_exe_anomaly.yml +++ b/rules/windows/process_creation/win_system_exe_anomaly.yml @@ -30,6 +30,13 @@ detection: - '*\winlogon.exe' - '*\explorer.exe' - '*\taskhost.exe' + - '*\Taskmgr.exe' + - '*\sihost.exe' + - '*\RuntimeBroker.exe' + - '*\smartscreen.exe' + - '*\dllhost.exe' + - '*\audiodg.exe' + - '*\wlanext.exe' filter: Image: - 'C:\Windows\System32\\*' diff --git a/rules/windows/process_creation/win_task_folder_evasion.yml b/rules/windows/process_creation/win_task_folder_evasion.yml index 253824e2..dfe043a8 100644 --- a/rules/windows/process_creation/win_task_folder_evasion.yml +++ b/rules/windows/process_creation/win_task_folder_evasion.yml @@ -30,7 +30,6 @@ detection: fields: - CommandLine - ParentProcess - - CommandLine falsepositives: - Unknown level: high diff --git a/rules/windows/sysmon/sysmon_ads_executable.yml b/rules/windows/sysmon/sysmon_ads_executable.yml index 7e111015..dbb055ad 100644 --- a/rules/windows/sysmon/sysmon_ads_executable.yml +++ b/rules/windows/sysmon/sysmon_ads_executable.yml @@ -17,11 +17,11 @@ logsource: detection: selection: EventID: 15 - filter: - Imphash: - - '00000000000000000000000000000000' - - null - condition: selection and not filter + filter1: + Imphash: '00000000000000000000000000000000' + filter2: + Imphash: null + condition: selection and not 1 of filter* fields: - TargetFilename - Image diff --git a/rules/windows/sysmon/sysmon_alternate_powershell_hosts_moduleload.yml b/rules/windows/sysmon/sysmon_alternate_powershell_hosts_moduleload.yml deleted file mode 100644 index 5a1abf5e..00000000 --- a/rules/windows/sysmon/sysmon_alternate_powershell_hosts_moduleload.yml +++ /dev/null @@ -1,26 +0,0 @@ -title: Alternate PowerShell Hosts Module Load -id: f67f6c57-257d-4919-a416-69cd31f9aac3 -description: Detects alternate PowerShell hosts potentially bypassing detections looking for powershell.exe -status: experimental -date: 2019/09/12 -modified: 2019/11/10 -author: Roberto Rodriguez @Cyb3rWard0g -references: - - https://github.com/Cyb3rWard0g/ThreatHunter-Playbook/tree/master/playbooks/windows/02_execution/T1086_powershell/alternate_signed_powershell_hosts.md -tags: - - attack.execution - - attack.t1086 -logsource: - product: windows - service: sysmon -detection: - selection: - EventID: 7 - Description: 'system.management.automation' - ImageLoaded|contains: 'system.management.automation' - filter: - Image|endswith: '\powershell.exe' - condition: selection and not filter -falsepositives: - - Programs using PowerShell directly without invocation of a dedicated interpreter. -level: high diff --git a/rules/windows/sysmon/sysmon_alternate_powershell_hosts_pipe.yml b/rules/windows/sysmon/sysmon_alternate_powershell_hosts_pipe.yml index fb702e8a..067cd370 100644 --- a/rules/windows/sysmon/sysmon_alternate_powershell_hosts_pipe.yml +++ b/rules/windows/sysmon/sysmon_alternate_powershell_hosts_pipe.yml @@ -18,7 +18,9 @@ detection: EventID: 17 PipeName|startswith: '\PSHost' filter: - Image|endswith: '\powershell.exe' + Image|endswith: + - '\powershell.exe' + - '\powershell_ise.exe' condition: selection and not filter fields: - ComputerName diff --git a/rules/windows/sysmon/sysmon_cmstp_execution.yml b/rules/windows/sysmon/sysmon_cmstp_execution.yml index 37a9827c..e3b04a18 100644 --- a/rules/windows/sysmon/sysmon_cmstp_execution.yml +++ b/rules/windows/sysmon/sysmon_cmstp_execution.yml @@ -31,6 +31,7 @@ detection: selection2: EventID: 12 TargetObject: '*\cmmgr32.exe*' + EventType: 'CreateKey' # Registry Object Value Set selection3: EventID: 13 diff --git a/rules/windows/sysmon/sysmon_creation_system_file.yml b/rules/windows/sysmon/sysmon_creation_system_file.yml new file mode 100644 index 00000000..9f8143c8 --- /dev/null +++ b/rules/windows/sysmon/sysmon_creation_system_file.yml @@ -0,0 +1,57 @@ +title: File Created with System Process Name +id: d5866ddf-ce8f-4aea-b28e-d96485a20d3d +status: experimental +description: Detects the creation of a executable with a sytem process name in a suspicious folder +references: + - https://attack.mitre.org/techniques/T1036/ +author: Sander Wiebing +date: 2020/05/26 +tags: + - attack.defense_evasion + - attack.t1036 +logsource: + product: windows + service: sysmon +detection: + selection: + EventID: 11 + TargetFilename|endswith: + - '*\svchost.exe' + - '*\rundll32.exe' + - '*\services.exe' + - '*\powershell.exe' + - '*\regsvr32.exe' + - '*\spoolsv.exe' + - '*\lsass.exe' + - '*\smss.exe' + - '*\csrss.exe' + - '*\conhost.exe' + - '*\wininit.exe' + - '*\lsm.exe' + - '*\winlogon.exe' + - '*\explorer.exe' + - '*\taskhost.exe' + - '*\Taskmgr.exe' + - '*\taskmgr.exe' + - '*\sihost.exe' + - '*\RuntimeBroker.exe' + - '*\runtimebroker.exe' + - '*\smartscreen.exe' + - '*\dllhost.exe' + - '*\audiodg.exe' + - '*\wlanext.exe' + filter: + TargetFilename: + - 'C:\Windows\System32\\*' + - 'C:\Windows\system32\\*' + - 'C:\Windows\SysWow64\\*' + - 'C:\Windows\SysWOW64\\*' + - 'C:\Windows\winsxs\\*' + - 'C:\Windows\WinSxS\\*' + - '\SystemRoot\System32\\*' + condition: selection and not filter +fields: + - Image +falsepositives: + - System processes copied outside the default folder +level: high diff --git a/rules/windows/sysmon/sysmon_cve-2020-1048.yml b/rules/windows/sysmon/sysmon_cve-2020-1048.yml index 49159021..9c671ad3 100644 --- a/rules/windows/sysmon/sysmon_cve-2020-1048.yml +++ b/rules/windows/sysmon/sysmon_cve-2020-1048.yml @@ -1,20 +1,15 @@ -action: global -title: Suspicious PrinterPorts Created (CVE-2020-1048) +title: Suspicious New Printer Ports in Registry (CVE-2020-1048) id: 7ec912f2-5175-4868-b811-ec13ad0f8567 status: experimental -description: Detects new registry printer port was created or powershell command add new printer port which point to suspicious file -author: EagleEye Team, Florian Roth +description: Detects a new and suspicious printer port creation in Registry that could be an attempt to exploit CVE-2020-1048 +author: EagleEye Team, Florian Roth, NVISO date: 2020/05/13 -modified: 2020/05/15 +modified: 2020/05/26 references: - https://windows-internals.com/printdemon-cve-2020-1048/ tags: - attack.persistence - attack.execution -falsepositives: - - New printer port install on host -level: high ---- logsource: service: sysmon product: windows @@ -28,21 +23,13 @@ detection: - SetValue - DeleteValue - CreateValue - TargetObject|contains: + Details|contains: - '.dll' - '.exe' + - '.bat' + - '.com' - 'C:' condition: selection ---- -logsource: - category: process_creation - product: windows -detection: - selection1: - CommandLine|contains: 'Add-PrinterPort -Name' - selection2: - CommandLine|contains: - - '.dll' - - '.exe' - condition: selection1 and selection2 - +falsepositives: + - New printer port install on host +level: high \ No newline at end of file diff --git a/rules/windows/sysmon/sysmon_disable_security_events_logging_adding_reg_key_minint.yml b/rules/windows/sysmon/sysmon_disable_security_events_logging_adding_reg_key_minint.yml index 1b3c4afd..ea7a4ea4 100644 --- a/rules/windows/sysmon/sysmon_disable_security_events_logging_adding_reg_key_minint.yml +++ b/rules/windows/sysmon/sysmon_disable_security_events_logging_adding_reg_key_minint.yml @@ -18,6 +18,7 @@ detection: - EventID: 12 # key create # Sysmon gives us HKLM\SYSTEM\CurrentControlSet\.. if ControlSetXX is the selected one TargetObject: 'HKLM\SYSTEM\CurrentControlSet\Control\MiniNt' + EventType: 'CreateKey' # we don't want deletekey - EventID: 14 # key rename NewName: 'HKLM\SYSTEM\CurrentControlSet\Control\MiniNt' condition: selection diff --git a/rules/windows/sysmon/sysmon_in_memory_powershell.yml b/rules/windows/sysmon/sysmon_in_memory_powershell.yml index d6108e16..56e6e453 100644 --- a/rules/windows/sysmon/sysmon_in_memory_powershell.yml +++ b/rules/windows/sysmon/sysmon_in_memory_powershell.yml @@ -23,8 +23,9 @@ detection: filter: Image|endswith: - '\powershell.exe' + - '\powershell_ise.exe' - '\WINDOWS\System32\sdiagnhost.exe' - User: 'NT AUTHORITY\SYSTEM' + # User: 'NT AUTHORITY\SYSTEM' # if set, matches all powershell processes not launched by SYSTEM condition: selection and not filter falsepositives: - Used by some .NET binaries, minimal on user workstation. diff --git a/rules/windows/sysmon/sysmon_lsass_memory_dump_file_creation.yml b/rules/windows/sysmon/sysmon_lsass_memory_dump_file_creation.yml index 0f6036df..54f7e04f 100644 --- a/rules/windows/sysmon/sysmon_lsass_memory_dump_file_creation.yml +++ b/rules/windows/sysmon/sysmon_lsass_memory_dump_file_creation.yml @@ -20,7 +20,7 @@ detection: condition: selection fields: - ComputerName - - TargetFileName + - TargetFilename falsepositives: - Dumping lsass memory for forensic investigation purposes by legitimate incident responder or forensic invetigator level: medium diff --git a/rules/windows/sysmon/sysmon_registry_persistence_key_linking.yml b/rules/windows/sysmon/sysmon_registry_persistence_key_linking.yml index 65d99b28..e0131f92 100644 --- a/rules/windows/sysmon/sysmon_registry_persistence_key_linking.yml +++ b/rules/windows/sysmon/sysmon_registry_persistence_key_linking.yml @@ -16,6 +16,7 @@ logsource: detection: selection: EventID: 12 + EventType: 'CreateKey' # don't want DeleteKey events TargetObject: 'HKU\\*_Classes\CLSID\\*\TreatAs' condition: selection falsepositives: diff --git a/rules/windows/sysmon/sysmon_susp_office_dotnet_assembly_dll_load.yml b/rules/windows/sysmon/sysmon_susp_office_dotnet_assembly_dll_load.yml index 6017a716..1c63a4c5 100644 --- a/rules/windows/sysmon/sysmon_susp_office_dotnet_assembly_dll_load.yml +++ b/rules/windows/sysmon/sysmon_susp_office_dotnet_assembly_dll_load.yml @@ -16,12 +16,12 @@ detection: selection: EventID: 7 Image: - - '*\winword.exe*' - - '*\powerpnt.exe*' - - '*\excel.exe*' - - '*\outlook.exe*' + - '*\winword.exe' + - '*\powerpnt.exe' + - '*\excel.exe' + - '*\outlook.exe' ImageLoaded: - - '*C:\Windows\assembly\*' + - 'C:\Windows\assembly\*' condition: selection falsepositives: - Alerts on legitimate macro usage as well, will need to filter as appropriate diff --git a/rules/windows/sysmon/sysmon_susp_office_dotnet_gac_dll_load.yml b/rules/windows/sysmon/sysmon_susp_office_dotnet_gac_dll_load.yml index a0f3ddae..354d7e8a 100644 --- a/rules/windows/sysmon/sysmon_susp_office_dotnet_gac_dll_load.yml +++ b/rules/windows/sysmon/sysmon_susp_office_dotnet_gac_dll_load.yml @@ -16,12 +16,12 @@ detection: selection: EventID: 7 Image: - - '*\winword.exe*' - - '*\powerpnt.exe*' - - '*\excel.exe*' - - '*\outlook.exe*' + - '*\winword.exe' + - '*\powerpnt.exe' + - '*\excel.exe' + - '*\outlook.exe' ImageLoaded: - - '*C:\Windows\Microsoft.NET\assembly\GAC_MSIL*' + - 'C:\Windows\Microsoft.NET\assembly\GAC_MSIL*' condition: selection falsepositives: - Alerts on legitimate macro usage as well, will need to filter as appropriate diff --git a/rules/windows/sysmon/sysmon_susp_office_kerberos_dll_load.yml b/rules/windows/sysmon/sysmon_susp_office_kerberos_dll_load.yml index 86aedc7e..77aaf326 100644 --- a/rules/windows/sysmon/sysmon_susp_office_kerberos_dll_load.yml +++ b/rules/windows/sysmon/sysmon_susp_office_kerberos_dll_load.yml @@ -16,12 +16,12 @@ detection: selection: EventID: 7 Image: - - '*\winword.exe*' - - '*\powerpnt.exe*' - - '*\excel.exe*' - - '*\outlook.exe*' + - '*\winword.exe' + - '*\powerpnt.exe' + - '*\excel.exe' + - '*\outlook.exe' ImageLoaded: - - '*\kerberos.dll*' + - '*\kerberos.dll' condition: selection falsepositives: - Alerts on legitimate macro usage as well, will need to filter as appropriate diff --git a/rules/windows/sysmon/sysmon_susp_run_key_img_folder.yml b/rules/windows/sysmon/sysmon_susp_run_key_img_folder.yml index 6f6c9f6b..43c5990a 100644 --- a/rules/windows/sysmon/sysmon_susp_run_key_img_folder.yml +++ b/rules/windows/sysmon/sysmon_susp_run_key_img_folder.yml @@ -4,12 +4,12 @@ status: experimental description: Detects suspicious new RUN key element pointing to an executable in a suspicious folder references: - https://www.fireeye.com/blog/threat-research/2018/08/fin7-pursuing-an-enigmatic-and-evasive-global-criminal-operation.html -author: Florian Roth, Markus Neis +author: Florian Roth, Markus Neis, Sander Wiebing tags: - attack.persistence - attack.t1060 date: 2018/08/25 -modified: 2020/02/26 +modified: 2020/05/24 logsource: product: windows service: sysmon @@ -21,8 +21,6 @@ detection: - '*\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce\\*' Details: - '*C:\Windows\Temp\\*' - - '*\AppData\\*' - - '%AppData%\\*' - '*C:\$Recycle.bin\\*' - '*C:\Temp\\*' - '*C:\Users\Public\\*' @@ -31,12 +29,9 @@ detection: - '*C:\Users\Desktop\\*' - 'wscript*' - 'cscript*' - filter: - Details|contains: - - '\AppData\Local\Microsoft\OneDrive\' # OneDrive False Positives - condition: selection and not filter + condition: selection fields: - Image falsepositives: - - Software using the AppData folders for updates + - Software using weird folders for updates level: high diff --git a/rules/windows/sysmon/sysmon_susp_winword_vbadll_load.yml b/rules/windows/sysmon/sysmon_susp_winword_vbadll_load.yml index b371692e..c792c8c2 100644 --- a/rules/windows/sysmon/sysmon_susp_winword_vbadll_load.yml +++ b/rules/windows/sysmon/sysmon_susp_winword_vbadll_load.yml @@ -16,14 +16,14 @@ detection: selection: EventID: 7 Image: - - '*\winword.exe*' - - '*\powerpnt.exe*' - - '*\excel.exe*' - - '*\outlook.exe*' + - '*\winword.exe' + - '*\powerpnt.exe' + - '*\excel.exe' + - '*\outlook.exe' ImageLoaded: - - '*\VBE7.DLL*' - - '*\VBEUI.DLL*' - - '*\VBE7INTL.DLL*' + - '*\VBE7.DLL' + - '*\VBEUI.DLL' + - '*\VBE7INTL.DLL' condition: selection falsepositives: - Alerts on legitimate macro usage as well, will need to filter as appropriate diff --git a/rules/windows/sysmon/sysmon_minidumwritedump_lsass.yml b/rules/windows/sysmon/sysmon_suspicious_dbghelp_dbgcore_load.yml similarity index 79% rename from rules/windows/sysmon/sysmon_minidumwritedump_lsass.yml rename to rules/windows/sysmon/sysmon_suspicious_dbghelp_dbgcore_load.yml index 556b2b6f..b5f36b4e 100644 --- a/rules/windows/sysmon/sysmon_minidumwritedump_lsass.yml +++ b/rules/windows/sysmon/sysmon_suspicious_dbghelp_dbgcore_load.yml @@ -1,12 +1,12 @@ -title: Dumping Lsass.exe Memory with MiniDumpWriteDump API -id: dd5ab153-beaa-4315-9647-65abc5f71541 +title: Load of dbghelp/dbgcore DLL from Suspicious Process +id: 0e277796-5f23-4e49-a490-483131d4f6e1 status: experimental -description: Detects the use of MiniDumpWriteDump API for dumping lsass.exe memory in a stealth way. Tools like ProcessHacker and some attacker tradecract use this +description: Detects the load of dbghelp/dbgcore DLL (used to make memory dumps) by suspicious processes. Tools like ProcessHacker and some attacker tradecract use MiniDumpWriteDump API found in dbghelp.dll or dbgcore.dll. As an example, SilentTrynity C2 Framework has a module that leverages this API to dump the contents of Lsass.exe and transfer it over the network back to the attacker's machine. date: 2019/10/27 -modified: 2019/11/13 -author: Perez Diego (@darkquassar), oscd.community +modified: 2020/05/23 +author: Perez Diego (@darkquassar), oscd.community, Ecco references: - https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/nf-minidumpapiset-minidumpwritedump - https://www.pinvoke.net/default.aspx/dbghelp/MiniDumpWriteDump.html @@ -35,7 +35,7 @@ detection: - '\outlook.exe' - '\monitoringhost.exe' - '\wmic.exe' - - '\msiexec.exe' + # - '\msiexec.exe' an installer installing a program using one of those DLL will raise an alert - '\bash.exe' - '\wscript.exe' - '\cscript.exe' @@ -62,4 +62,4 @@ fields: - ImageLoaded falsepositives: - Penetration tests -level: critical +level: high diff --git a/rules/windows/sysmon/sysmon_svchost_dll_search_order_hijack.yml b/rules/windows/sysmon/sysmon_svchost_dll_search_order_hijack.yml index ef3fc978..9dbbf96a 100644 --- a/rules/windows/sysmon/sysmon_svchost_dll_search_order_hijack.yml +++ b/rules/windows/sysmon/sysmon_svchost_dll_search_order_hijack.yml @@ -27,12 +27,9 @@ detection: - '*\tsvipsrv.dll' - '*\wlbsctrl.dll' filter: - EventID: 7 - Image: - - '*\svchost.exe' ImageLoaded: - 'C:\Windows\WinSxS\*' condition: selection and not filter falsepositives: - Pentest -level: high \ No newline at end of file +level: high diff --git a/rules/windows/sysmon/sysmon_tsclient_filewrite_startup.yml b/rules/windows/sysmon/sysmon_tsclient_filewrite_startup.yml index c26821f2..efb359ac 100644 --- a/rules/windows/sysmon/sysmon_tsclient_filewrite_startup.yml +++ b/rules/windows/sysmon/sysmon_tsclient_filewrite_startup.yml @@ -11,7 +11,7 @@ detection: selection: EventID: 11 Image: '*\mstsc.exe' - TargetFileName: '*\Microsoft\Windows\Start Menu\Programs\Startup\\*' + TargetFilename: '*\Microsoft\Windows\Start Menu\Programs\Startup\\*' condition: selection falsepositives: - unknown diff --git a/rules/windows/sysmon/sysmon_wmi_module_load.yml b/rules/windows/sysmon/sysmon_wmi_module_load.yml index 69fa4c76..8c660f19 100644 --- a/rules/windows/sysmon/sysmon_wmi_module_load.yml +++ b/rules/windows/sysmon/sysmon_wmi_module_load.yml @@ -29,9 +29,12 @@ detection: filter: Image|endswith: - '\WmiPrvSe.exe' - - '\WmiPrvSE.exe' - '\WmiAPsrv.exe' - '\svchost.exe' + - '\DeviceCensus.exe' + - '\CompatTelRunner.exe' + - '\sdiagnhost.exe' + - '\SIHClient.exe' condition: selection and not filter fields: - ComputerName diff --git a/tests/test_rules.py b/tests/test_rules.py index 881dbcd7..752611ed 100755 --- a/tests/test_rules.py +++ b/tests/test_rules.py @@ -486,6 +486,25 @@ class TestRules(unittest.TestCase): self.assertEqual(faulty_rules, [], Fore.RED + "There are rules with missing or malformed 'id' fields. Create an id (e.g. here: https://www.uuidgenerator.net/version4) and add it to the reported rule(s).") + def test_sysmon_rule_without_eventid(self): + faulty_rules = [] + for file in self.yield_next_rule_file_path(self.path_to_rules): + logsource = self.get_rule_part(file_path=file, part_name="logsource") + service = logsource.get('service', '') + if service.lower() == 'sysmon': + with open(file) as f: + found = False + for line in f: + if re.search(r'.*EventID:.*$', line): # might be on a single line or in multiple lines + found = True + break + if not found: + faulty_rules.append(file) + + self.assertEqual(faulty_rules, [], Fore.RED + + "There are rules using sysmon events but with no EventID specified") + + def test_missing_date(self): faulty_rules = [] for file in self.yield_next_rule_file_path(self.path_to_rules): @@ -538,7 +557,7 @@ class TestRules(unittest.TestCase): faulty_rules.append(file) wrong_casing = [] for word in title.split(" "): - if word.islower() and not word.lower() in allowed_lowercase_words and not "." in word and not word[0].isdigit(): + if word.islower() and not word.lower() in allowed_lowercase_words and not "." in word and not "/" in word and not word[0].isdigit(): wrong_casing.append(word) if len(wrong_casing) > 0: print(Fore.RED + "Rule {} has a title that has not title capitalization. Words: '{}'".format(file, ", ".join(wrong_casing))) diff --git a/tools/config/ala.yml b/tools/config/ala.yml new file mode 100644 index 00000000..1f4dd8ff --- /dev/null +++ b/tools/config/ala.yml @@ -0,0 +1,101 @@ +title: Azure Sentinel +order: 20 +backends: + - ala + - ala-rule +fieldmappings: + ComputerName: Computer + Event-ID: EventID + Event_ID: EventID + eventId: EventID + event_id: EventID + event-id: EventID + eventid: EventID + hashes: Hashes + file_hash: Hashes + url.query: URL + resource.URL: URL + src_ip: SourceIp + source.ip: SourceIp + FileName: TargetFilename + dst_ip: DestinationIP + destination.ip: DestinationIP + event_data.AccessMask: AccessMask + event_data.AllowedToDelegateTo: AllowedToDelegateTo + event_data.AttributeLDAPDisplayName: AttributeLDAPDisplayName + event_data.AuditPolicyChanges: AuditPolicyChanges + event_data.AuthenticationPackageName: AuthenticationPackageName + event_data.CallingProcessName: CallingProcessName + event_data.CallTrace": CallTrace + event_data.CommandLine: CommandLine + Commandline: CommandLine + cmd: CommandLine + event_data.ComputerName: ComputerName + event_data.CurrentDirectory: CurrentDirectory + event_data.Description: Description + event_data.DestinationHostname: DestinationHostname + event_data.DestinationIp: DestinationIp + event_data.DestinationPort: DestinationPort + event_data.Details: Details + event_data.EngineVersion: EngineVersion + event_data.EventType: EventType + event_data.FailureCode: FailureCode + event_data.FileName: FileName + event_data.GrantedAccess: GrantedAccess + event_data.GroupName: GroupName + event_data.GroupSid: GroupSid + event_data.Hashes: Hashes + event_data.HiveName: HiveName + event_data.HostVersion: HostVersion + Image: + service=security: Process + category=process_creation: NewProcessName + default: Image + event_data.Image: + service=security: Process + category=process_creation: NewProcessName + default: Image + event_data.ImageLoaded": ImageLoaded + event_data.ImagePath: ImagePath + event_data.Imphash: Imphash + event_data.IpAddress: IpAddress + event_data.KeyLength: KeyLength + event_data.LogonProcessName: LogonProcessName + event_data.LogonType: LogonType + event_data.NewProcessName: NewProcessName + event_data.ObjectClass: ObjectClass + event_data.ObjectName: ObjectName + event_data.ObjectType: ObjectType + event_data.ObjectValueName: ObjectValueName + event_data.ParentCommandLine: ParentCommandLine + event_data.ParentImage: + category=process_creation: ParentProcessName + default: ParentImage + ParentImage: + category=process_creation: ParentProcessName + default: ParentImage + event_data.ParentProcessName: ParentProcessName + event_data.Path: Path + event_data.PipeName: PipeName + event_data.ProcessCommandLine: CommanProcessCommandLinedLine + event_data.ProcessName: ProcessName + event_data.Properties: Properties + event_data.SecurityID: SecurityID + event_data.ServiceFileName: ServiceFileName + event_data.ServiceName: ServiceName + event_data.ShareName: ShareName + event_data.Signature: Signature + event_data.Source: Source + event_data.SourceImage: SourceImage + event_data.StartModule: StartModule + event_data.Status: Status + event_data.SubjectUserName: SubjectUserName + event_data.SubjectUserSid: SubjectUserSid + event_data.TargetFilename: TargetFilename + event_data.TargetImage: TargetImage + event_data.TargetObject: TargetObject + event_data.TicketEncryptionType: TicketEncryptionType + event_data.TicketOptions: TicketOptions + event_data.User: User + event_data.WorkstationName: WorkstationName + diff --git a/tools/config/arcsight-zeek.yml b/tools/config/arcsight-zeek.yml index 08050e8f..f9544552 100644 --- a/tools/config/arcsight-zeek.yml +++ b/tools/config/arcsight-zeek.yml @@ -498,7 +498,7 @@ fieldmappings: #service=socks: status_msg: - 'message' - #subject: + subject: - 'message' #service=known_certs: #service=sip: @@ -967,7 +967,7 @@ fieldmappings: auth_success: name cipher_alg: message #client: deviceCustomString5 - compression_alg: + compression_alg: cshka: message direction: deviceDirection hassh: message @@ -1054,4 +1054,117 @@ fieldmappings: id_orig_h: sourceAddress id_orig_p: sourcePort id_resp_h: destinationAddress - id_resp_p: destinationPort \ No newline at end of file + id_resp_p: destinationPort + # Temporary one off rule name fields + cs-uri: requestUrl + destination.domain: + destination.ip: destinationAddress + destination.port: destinationPort + http.response.status_code: deviceSeverity + #http.request.body.content + source.domain: + #sourceAddress: #TONOTE: is arcsight + source.port: sourcePort + agent.version: deviceCustomString2 + c-ip: sourceAddress + clientip: sourceAddress + clientIP: sourceAddress + dest_domain: + - url.domain + dest_ip: destinationAddress + dest_port: destinationPort + #TODO:WhatShouldThisBe?==dest: + #TODO:WhatShouldThisBe?==destination: + #TODO:WhatShouldThisBe?==Destination: + destination.hostname: destinationHostName + #DestinationAddress: #TONOTE: is arcsight + #DestinationHostname: #TONOTE: is arcsight + DestinationIp: destinationAddress + DestinationIP: destinationAddress + DestinationPort: destinationPort + dst-ip: destinationAddress + dstip: destinationAddress + dstport: destinationPort + Host: requestHost + #host: + HostVersion: deviceCustomString2 + http_host: destinationHostName + http_uri: requestUrl + http_url: requestUrl + http_user_agent: + - deviceCustomString5 + - requestClientApplication + http.request.url-query-params: + - requestUrl + - requestUrlQuery + HttpMethod: requestMethod + in_url: requestUrl + #parent_domain: + # - url.registered_domain + # - destination.registered_domain + post_url_parameter: requestUrl + Request Url: requestUrl + request_url: requestUrl + request_URL: requestUrl + RequestUrl: requestUrl + #response: http.response.status_code + resource.url: requestUrl + resource.URL: requestUrl + sc_status: deviceSeverity + sender_domain: message + service.response_code: deviceSeverity + SourceAddr: sourceAddress + SourceAddress: sourceAddress + SourceIP: sourceAddress + SourceIp: sourceAddress + SourceNetworkAddress: + - source.address + - sourceAddress + SourcePort: sourcePort + srcip: sourceAddress + Status: deviceSeverity + #status: deviceSeverity + url: requestUrl + URL: requestUrl + url_query: + - requestUrl + - requestUrlQuery + url.query: + - requestUrl + - requestUrlQuery + uri_path: requestUrl + #user_agent: user_agent.original + user_agent.name: + - deviceCustomString5 + - requestClientApplication + user-agent: + - deviceCustomString5 + - requestClientApplication + User-Agent: + - deviceCustomString5 + - requestClientApplication + useragent: + - deviceCustomString5 + - requestClientApplication + UserAgent: + - deviceCustomString5 + - requestClientApplication + User Agent: + - deviceCustomString5 + - requestClientApplication + web_dest: destinationHostName + web.dest: destinationHostName + Web.dest: destinationHostName + web.host: destinationHostName + Web.host: destinationHostName + web_method: requestMethod + Web_method: requestMethod + web.method: requestMethod + Web.method: requestMethod + web_src: sourceAddress + web_status: deviceSeverity + Web_status: deviceSeverity + web.status: deviceSeverity + Web.status: deviceSeverity + web_uri: requestUrl + web_url: requestUrl diff --git a/tools/config/arcsight.yml b/tools/config/arcsight.yml index f6a9bc53..d9dd1d7b 100644 --- a/tools/config/arcsight.yml +++ b/tools/config/arcsight.yml @@ -349,4 +349,132 @@ fieldmappings: keywords: - deviceCustomString1 ScriptBlockText: - - deviceCustomString1 \ No newline at end of file + - deviceCustomString1 + AccessMask: deviceCustomString1 + AccountName: deviceCustomString1 + AllowedToDelegateTo: deviceCustomString1 + AttributeLDAPDisplayName: deviceCustomString1 + AuditPolicyChanges: deviceCustomString1 + AuthenticationPackageName: deviceCustomString1 + CallingProcessName: deviceCustomString1 + Command: deviceCustomString1 + Command_Line: deviceCustomString1 + ComputerName: deviceCustomString1 + destination.domain: deviceCustomString1 + DestinationIP: deviceCustomString1 + EngineVersion: deviceCustomString1 + Event: deviceCustomString1 + event.category: deviceCustomString1 + event.raw: deviceCustomString1 + event_data.AccessMask: deviceCustomString1 + event_data.AccountName: deviceCustomString1 + event_data.AllowedToDelegateTo: deviceCustomString1 + event_data.AttributeLDAPDisplayName: deviceCustomString1 + event_data.AuditPolicyChanges: deviceCustomString1 + event_data.AuthenticationPackageName: deviceCustomString1 + event_data.CallingProcessName: deviceCustomString1 + event_data.CallTrace: deviceCustomString1 + event_data.CommandLine: deviceCustomString1 + event_data.ComputerName: deviceCustomString1 + event_data.CurrentDirectory: deviceCustomString1 + event_data.Description: deviceCustomString1 + event_data.DestinationHostname: deviceCustomString1 + event_data.DestinationIp: deviceCustomString1 + event_data.DestinationIsIpv6: deviceCustomString1 + event_data.DestinationPort: deviceCustomString1 + event_data.Details: deviceCustomString1 + event_data.EngineVersion: deviceCustomString1 + event_data.EventType: deviceCustomString1 + event_data.FailureCode: deviceCustomString1 + event_data.FileName: deviceCustomString1 + event_data.GrantedAccess: deviceCustomString1 + event_data.GroupName: deviceCustomString1 + event_data.GroupSid: deviceCustomString1 + event_data.Hashes: deviceCustomString1 + event_data.HiveName: deviceCustomString1 + event_data.HostVersion: deviceCustomString1 + event_data.Image: deviceCustomString1 + event_data.ImageLoaded: deviceCustomString1 + event_data.ImagePath: deviceCustomString1 + event_data.Imphash: deviceCustomString1 + event_data.IpAddress: deviceCustomString1 + event_data.KeyLength: deviceCustomString1 + event_data.LogonProcessName: deviceCustomString1 + event_data.LogonType: deviceCustomString1 + event_data.NewProcessName: deviceCustomString1 + event_data.ObjectClass: deviceCustomString1 + event_data.ObjectName: deviceCustomString1 + event_data.ObjectType: deviceCustomString1 + event_data.ObjectValueName: deviceCustomString1 + event_data.ParentCommandLine: deviceCustomString1 + event_data.ParentImage: deviceCustomString1 + event_data.ParentProcessName: deviceCustomString1 + event_data.Path: deviceCustomString1 + event_data.PipeName: deviceCustomString1 + event_data.ProcessCommandLine: deviceCustomString1 + event_data.ProcessName: deviceCustomString1 + event_data.Properties: deviceCustomString1 + event_data.SecurityID: deviceCustomString1 + event_data.ServiceFileName: deviceCustomString1 + event_data.ServiceName: deviceCustomString1 + event_data.ShareName: deviceCustomString1 + event_data.Signature: deviceCustomString1 + event_data.Source: deviceCustomString1 + event_data.SourceImage: deviceCustomString1 + event_data.StartModule: deviceCustomString1 + event_data.Status: deviceCustomString1 + event_data.SubjectUserName: deviceCustomString1 + event_data.SubjectUserSid: deviceCustomString1 + event_data.TargetFilename: deviceCustomString1 + event_data.TargetImage: deviceCustomString1 + event_data.TargetObject: deviceCustomString1 + event_data.TicketEncryptionType: deviceCustomString1 + event_data.TicketOptions: deviceCustomString1 + event_data.User: deviceCustomString1 + event_data.WorkstationName: deviceCustomString1 + FailureCode: deviceCustomString1 + GroupName: deviceCustomString1 + GroupSid: deviceCustomString1 + hashes: deviceCustomString1 + Header.Accept: deviceCustomString1 + HiveName: deviceCustomString1 + host.scan.vuln_name: deviceCustomString1 + HostVersion: deviceCustomString1 + ImagePath: deviceCustomString1 + Imphash: deviceCustomString1 + IpAddress: deviceCustomString1 + IpPort: deviceCustomString1 + KeyLength: deviceCustomString1 + log_name: deviceCustomString1 + LogonType: deviceCustomString1 + NewProcessName: deviceCustomString1 + ObjectClass: deviceCustomString1 + ObjectName: deviceCustomString1 + ObjectType: deviceCustomString1 + ObjectValueName: deviceCustomString1 + ParentProcessName: deviceCustomString1 + Path: deviceCustomString1 + ProcessCommandLine: deviceCustomString1 + ProcessName: deviceCustomString1 + Properties: deviceCustomString1 + resource.URL: deviceCustomString1 + SecurityEvent: deviceCustomString1 + SecurityID: deviceCustomString1 + SelectionURL: deviceCustomString1 + ServiceFileName: deviceCustomString1 + ServiceName: deviceCustomString1 + ShareName: deviceCustomString1 + Source: deviceCustomString1 + source_name: deviceCustomString1 + SourceIP: deviceCustomString1 + Status: deviceCustomString1 + SubjectDomainName: deviceCustomString1 + SubjectUserName: deviceCustomString1 + SubjectUserSid: deviceCustomString1 + SysmonEvent: deviceCustomString1 + TargetDomainName: deviceCustomString1 + TargetUserSid: deviceCustomString1 + TicketEncryptionType: deviceCustomString1 + TicketOptions: deviceCustomString1 + winlog.channel: deviceCustomString1 + WorkstationName: deviceCustomString1 \ No newline at end of file diff --git a/tools/config/crowdstrike.yml b/tools/config/crowdstrike.yml new file mode 100644 index 00000000..8a90c07e --- /dev/null +++ b/tools/config/crowdstrike.yml @@ -0,0 +1,19 @@ +title: Splunk Windows log source conditions +order: 20 +backends: + - crowdstrike +logsources: + windows-sysmon: + product: windows + service: sysmon + conditions: + EventID: 1 + process_creation_1: + category: process_creation + product: windows + +fieldmappings: + EventID: EventID + CommandLine: Commandline + Command_Line: Commandline + Image: ImageFileName diff --git a/tools/config/ecs-cloudtrail.yml b/tools/config/ecs-cloudtrail.yml new file mode 100644 index 00000000..fe9419bd --- /dev/null +++ b/tools/config/ecs-cloudtrail.yml @@ -0,0 +1,60 @@ +title: Elastic Common Schema And Elastic Exported Fields Mapping For AWS CloudTrail Logs +order: 20 +backends: + - es-qs + - es-dsl + - es-rule + - kibana + - xpack-watcher + - elastalert + - elastalert-dsl +fieldmappings: + additionalEventdata: aws.cloudtrail.additional_eventdata + apiVersion: aws.cloudtrail.api_version + awsRegion: cloud.region + errorCode: aws.cloudtrail.error_code + errorMessage: aws.cloudtrail.error_message + eventID: event.id + eventName: event.action + eventSource: event.provider + eventTime: '@timestamp' + eventType: aws.cloudtrail.event_type + eventVersion: aws.cloudtrail.event_version + managementEvent: aws.cloudtrail.management_event + readOnly: aws.cloudtrail.read_only + requestID: aws.cloudtrail.request_id + requestParameters: aws.cloudtrail.request_parameters + resources.accountId: aws.cloudtrail.resources.account_id + resources.ARN: aws.cloudtrail.resources.arn + resources.type: aws.cloudtrail.resources.type + responseElements: aws.cloudtrail.response_elements + serviceEventDetails: aws.cloudtrail.service_event_details + sharedEventId: aws.cloudtrail.shared_event_id + sourceIPAddress: source.address + userAgent: user_agent + userIdentity.accessKeyId: aws.cloudtrail.user_identity.access_key_id + userIdentity.accountId: cloud.account.id + userIdentity.arn: aws.cloudtrail.user_identity.arn + userIdentity.invokedBy: aws.cloudtrail.user_identity.invoked_by + userIdentity.principalId: user.id + userIdentity.sessionContext.attributes.creationDate: aws.cloudtrail.user_identity.session_context.creation_date + userIdentity.sessionContext.attributes.mfaAuthenticated: aws.cloudtrail.user_identity.session_context.mfa_authenticated + userIdentity.type: aws.cloudtrail.user_identity.type + userIdentity.userName: user.name + vpcEndpointId: aws.cloudtrail.vpc_endpoint_id +overrides: + - field: event.outcome + value: failure + regexes: + - (\(\(aws.cloudtrail.error_message.keyword:.* event.action:\"ConsoleLogin\"\)\)) + - (\(\(aws.cloudtrail.error_code.keyword:.* event.action:\"ConsoleLogin\"\)\)) + - (\(\(aws.cloudtrail.error_message.keyword:.* aws.cloudtrail.response_elements.keyword:\*Failure\*\)\)) + - (\(\(aws.cloudtrail.error_code.keyword:.* aws.cloudtrail.response_elements.keyword:\*Failure\*\)\)) + - (\(\(event.action:\"ConsoleLogin\".* aws.cloudtrail.error_message.keyword:\*\)\)) + - (\(\(event.action:\"ConsoleLogin\".* aws.cloudtrail.error_code.keyword:\*\)\)) + - (\(\(aws.cloudtrail.response_elements.keyword:\*Failure\*.* aws.cloudtrail.error_message.keyword:\*\)\)) + - (\(\(aws.cloudtrail.response_elements.keyword:\*Failure\*.* aws.cloudtrail.error_code.keyword:\*\)\)) + - field: event.outcome + value: success + literals: + - 'NOT (event.outcome:failure)' \ No newline at end of file diff --git a/tools/config/ecs-dns.yml b/tools/config/ecs-dns.yml new file mode 100644 index 00000000..d41c0639 --- /dev/null +++ b/tools/config/ecs-dns.yml @@ -0,0 +1,69 @@ +title: Elastic Common Schema mapping for proxy and webserver logs including NSM DNS logs (zeek/suricata) +order: 20 +backends: + - es-qs + - es-dsl + - elasticsearch-rule + - kibana + - xpack-watcher + - elastalert + - elastalert-dsl +# zeek-category-dns: + # category: dns + # conditions: + # event.dataset: dns +# zeek-dns: + # product: zeek + # service: dns + # conditions: + # event.dataset: dns +defaultindex: + - filebeat-* +# logsourcemerging: or +fieldmappings: + # All Logs Applied Mapping & Taxonomy + dst: + - destination.address + - destination.ip + dst_ip: + - destination.address + - destination.ip + dst_port: destination.port + src: + - source.address + - source.ip + src_ip: + - source.address + - source.ip + src_port: source.port + # DNS Taxonomy + answer: dns.answers.name + c-dns: dns.question.name + parent_domain: dns.question.registered_domain + query: dns.question.name + QueryName: dns.question.name + r-dns: dns.question.name + record_type: dns.answers.type + response: dns.answers + #question_length: + # Zeek DNS specific + AA: dns.AA + addl: dns.addl + answers: dns.answers.name + auth: dns.auth + qclass_name: dns.question.class + qclass: dns.qclass + qtype_name: dns.question.type + qtype: dns.qtype + query: dns.question.name + #question_length: labels.dns.query_length + RA: dns.RA + rcode_name: dns.response_code + rcode: dns.rcode + RD: dns.RD + rejected: dns.rejected + rtt: dns.rtt + TC: dns.TC + trans_id: dns.id + TTLs: dns.answers.ttl + Z: dns.Z diff --git a/tools/config/ecs-proxy.yml b/tools/config/ecs-proxy.yml index 38fa49e5..0659f7c3 100644 --- a/tools/config/ecs-proxy.yml +++ b/tools/config/ecs-proxy.yml @@ -1,30 +1,222 @@ -title: Elastic Common Schema mapping for proxy logs +title: Elastic Common Schema mapping for proxy and webserver logs including NSM logs (zeek/suricata) order: 20 backends: - es-qs - es-dsl - es-rule + - corelight_elasticsearch-rule - kibana - xpack-watcher - elastalert - elastalert-dsl - ee-outliers -logsources: - proxy: - category: proxy - index: filebeat-* +defaultindex: + - filebeat-* fieldmappings: - c-uri: url.original + # All Logs Applied Mapping & Taxonomy + dst: + - destination.address + - destination.ip + dst_ip: + - destination.address + - destination.ip + dst_port: destination.port + src: + - source.address + - source.ip + src_ip: + - source.address + - source.ip + src_port: source.port + # Web/Proxy Taxonomy + cs-bytes: http.request.body.bytes + cs-cookie-vars: http.cookie_vars c-uri-extension: url.extension c-uri-query: url.query c-uri-stem: url.original + c-uri: url.original c-useragent: user_agent.original cs-bytes: http.request.body.bytes cs-cookie: http.cookie - cs-host: url.domain + cs-host: + - url.domain + - destination.domain cs-method: http.request.method cs-referrer: http.request.referrer cs-version: http.version - r-dns: url.domain - sc-status: http.response.status_code + r-dns: + - destination.domain + - url.domain sc-bytes: http.response.body.bytes + sc-status: http.response.status_code + # Temporary one off rule name fields + destination.domain: + # destination.ip: + # destination.port: + # http.response.status_code + # http.request.body.content + # source.domain: + # source.ip: + # source.port: + agent.version: http.version + c-ip: + - source.address + - source.ip + clientip: + - source.address + - source.ip + clientIP: + - source.address + - source.ip + dest_domain: + - destination.domain + - url.domain + dest_ip: + - destination.address + - destination.ip + dest_port: destination.port + #TODO:WhatShouldThisBe?==dest: + #TODO:WhatShouldThisBe?==destination: + #TODO:WhatShouldThisBe?==Destination: + destination.hostname: + - destination.domain + - url.domain + DestinationAddress: + DestinationHostname: + - destination.domain + - url.domain + DestinationIp: + - destination.address + - destination.ip + DestinationIP: + - destination.address + - destination.ip + DestinationPort: destination.port + dst-ip: + - destination.address + - destination.ip + dstip: + - destination.address + - destination.ip + dstport: destination.port + Host: + - destination.domain + - url.domain + host: + - destination.domain + - url.domain + HostVersion: http.version + http_host: + - destination.domain + - url.domain + http_uri: url.original + http_url: url.original + http_user_agent: user_agent.original + http.request.url-query-params: url.original + HttpMethod: http.request.method + in_url: url.original + parent_domain: + - url.registered_domain + - destination.registered_domain + post_url_parameter: url.original + Request Url: url.original + request_url: url.original + request_URL: url.original + RequestUrl: url.original + response: http.response.status_code + resource.url: url.original + resource.URL: url.original + sc_status: http.response.status_code + sender_domain: + - destination.domain + - url.domain + service.response_code: http.response.status_code + source: + - source.address + - source.ip + SourceAddr: + - source.address + - source.ip + SourceAddress: + - source.address + - source.ip + SourceIP: + - source.address + - source.ip + SourceIp: + - source.address + - source.ip + SourceNetworkAddress: + - source.address + - source.ip + SourcePort: source.port + srcip: + - source.address + - source.ip + Status: http.response.status_code + status: http.response.status_code + url: url.original + URL: url.original + url_query: url.original + url.query: url.original + uri_path: url.original + user_agent: user_agent.original + user_agent.name: user_agent.original + user-agent: user_agent.original + User-Agent: user_agent.original + useragent: user_agent.original + UserAgent: user_agent.original + web_dest: + - url.domain + - destination.domain + web.dest: + - url.domain + - destination.domain + Web.dest: + - url.domain + - destination.domain + web.host: + - url.domain + - destination.domain + Web.host: + - url.domain + - destination.domain + web_method: http.request.method + Web_method: http.request.method + web.method: http.request.method + Web.method: http.request.method + web_src: + - source.address + - source.ip + web_status: http.response.status_code + Web_status: http.response.status_code + web.status: http.response.status_code + Web.status: http.response.status_code + web_uri: url.original + web_url: url.original + # Zeek HTTP as Proxy/Web + client_header_names: http.client_header_names + cookie_vars: http.cookie_vars + flash_version: http.flash_version + info_code: http.info_code + info_msg: http.info_msg + method: http.request.method + omniture: http.omniture + orig_filenames: http.orig_filenames + orig_mime_types: http.orig_mime_types + origin: http.origin + #password: source.user.password + post_body: http.post_body + proxied: http.proxied + referrer: http.request.referrer + request_body_len: http.request.body.bytes + resp_filenames: http.resp_filenames + resp_mime_types: http.resp_mime_types + response_body_len: http.response.body.bytes + server_header_names: http.server_header_names + status_code: http.response.status_code + status_msg: http.status_msg + trans_depth: http.trans_depth + uri_vars: http.uri_vars + username: source.user.name + version: http.version diff --git a/tools/config/ecs-zeek-corelight.yml b/tools/config/ecs-zeek-corelight.yml index 9d6a29e3..0707a7f7 100644 --- a/tools/config/ecs-zeek-corelight.yml +++ b/tools/config/ecs-zeek-corelight.yml @@ -35,16 +35,18 @@ logsources: rewrite: product: zeek service: dns + conditions: + event.dataset: dns zeek-category-proxy: category: proxy rewrite: - product: zeek - service: http + product: zeek + service: http zeek-category-webserver: category: webserver rewrite: - product: zeek - service: http + product: zeek + service: http zeek-conn: product: zeek service: conn @@ -396,134 +398,250 @@ fieldmappings: uid: log.id.uid uids: log.id.uids uuid: log.id.uuid - # Overlapping fields/mappings (aka: shared fields) + # Deep mappings / Overlapping fields/mappings (aka: shared fields) #_action - action: '*.action' + action: + #- '*.action' + service=mqtt: mqtt.action + service=smb_files: smb.action + service=tunnel: tunnel.action mqtt_action: smb.action smb_action: smb.action tunnel_action: tunnel.action #_addl - addl: weird.addl + addl: + #- '*.addl' + service=dns: dns.addl + service=weird: weird.addl dns_addl: dns.addl weird_addl: weird.addl #_analyzer - analyzer: '*.analyzer' + analyzer: + #- '*.analyzer' + service=dpd: dpd.analyzer + service=files: files.analyzer dpd_analyzer: dpd.analyzer files_analyzer: file.analyzer #_arg - arg: '*.arg' + arg: + #- '*.arg' + service=ftp: ftp.arg + service=msqyl: mysql.arg + service=pop3: pop3.arg ftp_arg: ftp.arg - pop3_arg: pop3.arg mysql_arg: mysql.arg + pop3_arg: pop3.arg #_auth - #auth: - #service=rfb: rfb.auth #RFB does not exist in newer logs, so skipping to cover dns.auth + auth: + #- dns.auth + service=dns: dns.auth + service=rfb: rfb.auth dns_auth: dns.auth rfb_auth: rfb.auth #_cipher - cipher: tls.cipher + cipher: + #- '*.client' + service=kerberos: kerberos.cipher + service=ssl: tls.cipher kerberos_cipher: kerberos.cipher + ssl_cipher: tls.cipher tls_cipher: tls.cipher #_client - client: '*.client' + client: + #- '*.client' + service=kerberos: kerberos.client + service=ssh: ssh.client kerberos_client: kerberos.client ssh_client: ssh.client #_command - command: '*.command' + command: + #- '*.command' + service=irc: irc.command + service=ftp: ftp.command + service=pop3: pop3.command ftp_command: ftp.command - irc_command: ssh.client + irc_command: irc.command pop3_command: pop3.command #_date - date: '*.date' + date: + #- '*.date' + service=sip: sip.date + service=smtp: smtp.date sip_date: sip.date smtp_date: smtp.date #_duration - duration: event.duration + duration: + #- event.duration + service=conn: event.duration + service=files: files.duration + service=snmp: event.duration conn_duration: event.duration files_duration: files.duration snmp_duration: event.duration #_from - from: '*.from' + from: + #- '*.from' + service=kerberos: kerberos.from + service=smtp: smtp.from kerberos_from: kerberos.from smtp_from: smtp.from #_is_orig - is_orig: '*.is_orig' - is_orig_file: file.is_orig - is_orig_pop3: pop3.is_orig + is_orig: + #- '*.is_orig' + service=file: file.is_orig + service=pop3: pop3.is_orig + files_is_orig: file.is_orig + pop3_is_orig: pop3.is_orig #_local_orig - local_orig: '*.local_orig' + local_orig: + #- '*.local_orig' + service=conn: conn.local_orig + service=files: file.local_orig conn_local_orig: conn.local_orig files_local_orig: file.local_orig #_method - method: http.request.method + method: + #- http.request.method + service=http: http.request.method + service=sip: sip.method http_method: http.request.method sip_method: sip.method #_msg - msg: notice.msg + msg: + #- notice.msg + service=notice: notice.msg + service=pop3: pop3.msg notice_msg: notice.msg pop3_msg: pop3.msg #_name - name: file.name + name: + #- file.name + service=smb_files: file.name + service=software: software.name + service=weird: weird.name smb_files_name: file.name software_name: software.name weird_name: weird.name #_path - path: file.path + path: + #- file.path + service=smb_files: file.path + service=smb_mapping: file.path + service=smtp: smtp.path smb_files_path: file.path smb_mapping_path: file.path smtp_path: smtp.path #_reply_msg - reply_msg: '*.reply_msg' + reply_msg: + #- '*.reply_msg' + service=ftp: ftp.reply_msg + service=radius: radius.reply_msg ftp_reply_msg: ftp.reply_msg radius_reply_msg: radius.reply_msg #_reply_to - reply_to: '*.reply_to' + reply_to: + #- '*.reply_to' + service=sip: sip.reply_to + service=smtp: smtp.reply_to sip_reply_to: sip.reply_to smtp_reply_to: smtp.reply_to #_response_body_len - response_body_len: http.response.body.bytes + response_body_len: + #- http.response.body.bytes + service=http: http.response.body.bytes + service=sip: sip.response_body_len http_response_body_len: http.response.body.bytes sip_response_body_len: sip.response_body_len #_request_body_len - request_body_len: http.request.body.bytes + request_body_len: + #- http.request.body.bytes + service=http: http.response.body.bytes + service=sip: sip.request_body_len http_request_body_len: http.response.body.bytes sip_request_body_len: sip.response_body_len + #_rtt + #rtt: + #- event.duration + #- 'zeek.*.rtt' + #service=dns: event.duration + #service=dce_rpc: event.duration + dns_rtt: event.duration + dce_rpc_rtt: event.duration #_service - service: '*.service' + service: + #- '*.service' + service=kerberos: kerberos.service + service=smb_mapping: smb.service kerberos_service: kerberos.service smb_mapping_kerberos: smb.service #_status - status: '*.status' + status: + #- '*.status' + service=mqtt: mqtt.status + service=pop3: pop3.status + service=socks: socks.status mqtt_status: mqtt.status pop3_status: pop3.status socks_status: socks.status #_status_code - status_code: 'http.response.status_code' + status_code: + #- 'http.response.status_code' + service=http: http.response.status_code + service=sip: sip.status_code http_status_code: http.response.status_code sip_status_code: sip.status_code #_status_msg - status_msg: http.status_msg + status_msg: + #- '*.status_msg' + service=http: http.status_msg + service=sip: sip.status_msg http_status_msg: http.status_msg sip_status_msg: sip.status_msg #_subject - subject: tls.subject + subject: + #- '*.subject' + service=known_certs: known_certs.subject + service=sip: sip.subject + service=smtp: smtp.subject + service=ssl: tls.subject known_certs_subject: known_certs.subject sip_subject: sip.subject smtp_subject: smtp.subject ssl_subject: tls.subject + #_service + #_trans_depth - trans_depth: '*.trans_depth' + trans_depth: + #- '*.trans_depth' + service=http: http.trans_depth + service=sip: sip.trans_depth + service=smtp: smtp.trans_depth http_trans_depth: http.trans_depth sip_trans_depth: sip.trans_depth smtp_trans_depth: smtp.trans_depth + #_user_agent + #user_agent: #already normalized + http_user_agent: user_agent.original + gquic_user_agent: user_agent.original + sip_user_agent: user_agent.original + smtp_user_agent: user_agent.original #_version - version: '*.version' + version: + #- '*.version' + service=gquic: gquic.version + service=http: http.version + service=ntp: ntp.version + service=socks: socks.version + service=snmp: snmp.version + service=ssh: ssh.version + service=tls: tls.version gquic_version: gquic.version http_version: http.version ntp_version: ntp.version socks_version: socks.version snmp_version: snmp.version ssh_version: ssh.version + ssl_version: tls.version tls_version: tls.version # Conn and Conn Long cache_add_rx_ev: conn.cache_add_rx_ev @@ -579,7 +697,6 @@ fieldmappings: # DNS AA: dns.AA #addl: dns.addl - auth: dns.auth answers: dns.answers.name TTLs: dns.answers.ttl RA: dns.RA @@ -1055,11 +1172,119 @@ fieldmappings: id_resp_p: destination.port # Temporary one off rule name fields cs-uri: url.original + # destination.domain: + # destination.ip: + # destination.port: + # http.response.status_code + # http.request.body.content + # source.domain: + # source.ip: + # source.port: + agent.version: http.version + c-ip: source.ip clientip: source.ip - clientIP: source.io + clientIP: source.ip dest_domain: - - query - - host - - server_name + - destination.domain + - url.domain dest_ip: destination.ip - dest_port: destination.port \ No newline at end of file + dest_port: destination.port + #TODO:WhatShouldThisBe?==dest: + #TODO:WhatShouldThisBe?==destination: + #TODO:WhatShouldThisBe?==Destination: + destination.hostname: + - destination.domain + - url.domain + DestinationAddress: destination.ip + DestinationHostname: + - destination.domain + - url.domain + DestinationIp: destination.ip + DestinationIP: destination.ip + DestinationPort: destination.port + dst-ip: destination.ip + dstip: destination.ip + dstport: destination.port + Host: + - destination.domain + - url.domain + #host: + # - destination.domain + # - url.domain + HostVersion: http.version + http_host: + - destination.domain + - url.domain + http_uri: url.original + http_url: url.original + #http_user_agent: user_agent.original + http.request.url-query-params: url.original + HttpMethod: http.request.method + in_url: url.original + #parent_domain: + # - url.registered_domain + # - destination.registered_domain + post_url_parameter: url.original + Request Url: url.original + request_url: url.original + request_URL: url.original + RequestUrl: url.original + #response: http.response.status_code + resource.url: url.original + resource.URL: url.original + sc_status: http.response.status_code + sender_domain: + - destination.domain + - url.domain + service.response_code: http.response.status_code + SourceAddr: + - source.address + - source.ip + SourceAddress: source.ip + SourceIP: source.ip + SourceIp: source.ip + SourceNetworkAddress: + - source.address + - source.ip + SourcePort: source.port + srcip: source.ip + Status: http.response.status_code + #status: http.response.status_code + url: url.original + URL: url.original + url_query: url.original + url.query: url.original + uri_path: url.original + #user_agent: user_agent.original + user_agent.name: user_agent.original + user-agent: user_agent.original + User-Agent: user_agent.original + useragent: user_agent.original + UserAgent: user_agent.original + User Agent: user_agent.original + web_dest: + - url.domain + - destination.domain + web.dest: + - url.domain + - destination.domain + Web.dest: + - url.domain + - destination.domain + web.host: + - url.domain + - destination.domain + Web.host: + - url.domain + - destination.domain + web_method: http.request.method + Web_method: http.request.method + web.method: http.request.method + Web.method: http.request.method + web_src: source.ip + web_status: http.response.status_code + Web_status: http.response.status_code + web.status: http.response.status_code + Web.status: http.response.status_code + web_uri: url.original + web_url: url.original diff --git a/tools/config/elk-defaultindex-filebeat.yml b/tools/config/elk-defaultindex-filebeat.yml new file mode 100644 index 00000000..24f52574 --- /dev/null +++ b/tools/config/elk-defaultindex-filebeat.yml @@ -0,0 +1,2 @@ +defaultindex: + - filebeat-* diff --git a/tools/config/elk-defaultindex-logstash.yml b/tools/config/elk-defaultindex-logstash.yml new file mode 100644 index 00000000..7c826199 --- /dev/null +++ b/tools/config/elk-defaultindex-logstash.yml @@ -0,0 +1,2 @@ +defaultindex: + - logstash-* diff --git a/tools/config/elk-defaultindex.yml b/tools/config/elk-defaultindex.yml new file mode 100644 index 00000000..99a94b8f --- /dev/null +++ b/tools/config/elk-defaultindex.yml @@ -0,0 +1,3 @@ +defaultindex: + - logstash-* + - filebeat-* diff --git a/tools/config/elk-linux.yml b/tools/config/elk-linux.yml new file mode 100644 index 00000000..9b2d4808 --- /dev/null +++ b/tools/config/elk-linux.yml @@ -0,0 +1,15 @@ +logsources: + apache: + category: webserver + index: logstash-apache-* + webapp-error: + category: application + index: logstash-apache_error-* + linux-auth: + product: linux + service: auth + index: logstash-auth-* +fieldmappings: + client_ip: clientip + url: request +defaultindex: logstash-* diff --git a/tools/config/elk-windows.yml b/tools/config/elk-windows.yml new file mode 100644 index 00000000..a408123c --- /dev/null +++ b/tools/config/elk-windows.yml @@ -0,0 +1,30 @@ +logsources: + windows: + product: windows + index: logstash-windows-* + windows-application: + product: windows + service: application + conditions: + EventLog: Application + windows-security: + product: windows + service: security + conditions: + EventLog: Security + windows-sysmon: + product: windows + service: sysmon + conditions: + EventLog: Microsoft-Windows-Sysmon + windows-dns-server: + product: windows + service: dns-server + conditions: + EventLog: 'DNS Server' + windows-driver-framework: + product: windows + service: driver-framework + conditions: + source: 'Microsoft-Windows-DriverFrameworks-UserMode/Operational' +defaultindex: logstash-* diff --git a/tools/config/elk-winlogbeat-sp.yml b/tools/config/elk-winlogbeat-sp.yml new file mode 100644 index 00000000..f1abce0a --- /dev/null +++ b/tools/config/elk-winlogbeat-sp.yml @@ -0,0 +1,95 @@ +logsources: + windows: + product: windows + index: + + windows-application: + product: windows + service: application + conditions: + log_name: Application + windows-security: + product: windows + service: security + conditions: + log_name: Security + windows-sysmon: + product: windows + service: sysmon + conditions: + log_name: 'Microsoft-Windows-Sysmon/Operational' + windows-dns-server: + product: windows + service: dns-server + conditions: + log_name: 'DNS Server' + windows-driver-framework: + product: windows + service: driver-framework + conditions: + source: 'Microsoft-Windows-DriverFrameworks-UserMode/Operational' +defaultindex: +# Extract all field names qith yq: +# yq -r '.detection | del(.condition) | map(keys) | .[][]' $(find sigma/rules/windows -name '*.yml') | sort -u | grep -v ^EventID$ | sed 's/^\(.*\)/ \1: event_data.\1/g' +# Keep EventID! Clean up the list afterwards! +fieldmappings: + EventID: event_id + AccessMask: event_data.AccessMask + AccountName: event_data.AccountName + AllowedToDelegateTo: event_data.AllowedToDelegateTo + AttributeLDAPDisplayName: event_data.AttributeLDAPDisplayName + AuditPolicyChanges: event_data.AuditPolicyChanges + AuthenticationPackageName: event_data.AuthenticationPackageName + CallingProcessName: event_data.CallingProcessName + CallTrace: event_data.CallTrace + CommandLine: event_data.CommandLine + ComputerName: event_data.ComputerName + CurrentDirectory: event_data.CurrentDirectory + Description: event_data.Description + DestinationHostname: event_data.DestinationHostname + DestinationIp: event_data.DestinationIp + DestinationIsIpv6: event_data.DestinationIsIpv6 + DestinationPort: event_data.DestinationPort + Details: event_data.Details + EngineVersion: event_data.EngineVersion + EventType: event_data.EventType + FailureCode: event_data.FailureCode + FileName: event_data.FileName + GrantedAccess: event_data.GrantedAccess + GroupName: event_data.GroupName + Hashes: event_data.Hashes + HiveName: event_data.HiveName + HostVersion: event_data.HostVersion + Image: event_data.Image + ImageLoaded: event_data.ImageLoaded + ImagePath: event_data.ImagePath + Imphash: event_data.Imphash + LogonProcessName: event_data.LogonProcessName + LogonType: event_data.LogonType + NewProcessName: event_data.NewProcessName + ObjectClass: event_data.ObjectClass + ObjectName: event_data.ObjectName + ObjectType: event_data.ObjectType + ObjectValueName: event_data.ObjectValueName + ParentCommandLine: event_data.ParentCommandLine + ParentImage: event_data.ParentImage + Path: event_data.Path + PipeName: event_data.PipeName + ProcessName: event_data.ProcessName + Properties: event_data.Properties + ServiceFileName: event_data.ServiceFileName + ServiceName: event_data.ServiceName + ShareName: event_data.ShareName + Signature: event_data.Signature + Source: event_data.Source + SourceImage: event_data.SourceImage + StartModule: event_data.StartModule + Status: event_data.Status + SubjectUserName: event_data.SubjectUserName + TargetFilename: event_data.TargetFilename + TargetImage: event_data.TargetImage + TargetObject: event_data.TargetObject + TicketEncryptionType: event_data.TicketEncryptionType + TicketOptions: event_data.TicketOptions + User: event_data.User + WorkstationName: event_data.WorkstationName diff --git a/tools/config/elk-winlogbeat.yml b/tools/config/elk-winlogbeat.yml new file mode 100644 index 00000000..20bf500f --- /dev/null +++ b/tools/config/elk-winlogbeat.yml @@ -0,0 +1,94 @@ +logsources: + windows: + product: windows + index: winlogbeat-* + windows-application: + product: windows + service: application + conditions: + log_name: Application + windows-security: + product: windows + service: security + conditions: + log_name: Security + windows-sysmon: + product: windows + service: sysmon + conditions: + log_name: 'Microsoft-Windows-Sysmon/Operational' + windows-dns-server: + product: windows + service: dns-server + conditions: + log_name: 'DNS Server' + windows-driver-framework: + product: windows + service: driver-framework + conditions: + source: 'Microsoft-Windows-DriverFrameworks-UserMode/Operational' +defaultindex: winlogbeat-* +# Extract all field names qith yq: +# yq -r '.detection | del(.condition) | map(keys) | .[][]' $(find sigma/rules/windows -name '*.yml') | sort -u | grep -v ^EventID$ | sed 's/^\(.*\)/ \1: event_data.\1/g' +# Keep EventID! Clean up the list afterwards! +fieldmappings: + EventID: event_id + AccessMask: event_data.AccessMask + AccountName: event_data.AccountName + AllowedToDelegateTo: event_data.AllowedToDelegateTo + AttributeLDAPDisplayName: event_data.AttributeLDAPDisplayName + AuditPolicyChanges: event_data.AuditPolicyChanges + AuthenticationPackageName: event_data.AuthenticationPackageName + CallingProcessName: event_data.CallingProcessName + CallTrace: event_data.CallTrace + CommandLine: event_data.CommandLine + ComputerName: event_data.ComputerName + CurrentDirectory: event_data.CurrentDirectory + Description: event_data.Description + DestinationHostname: event_data.DestinationHostname + DestinationIp: event_data.DestinationIp + DestinationIsIpv6: event_data.DestinationIsIpv6 + DestinationPort: event_data.DestinationPort + Details: event_data.Details + EngineVersion: event_data.EngineVersion + EventType: event_data.EventType + FailureCode: event_data.FailureCode + FileName: event_data.FileName + GrantedAccess: event_data.GrantedAccess + GroupName: event_data.GroupName + Hashes: event_data.Hashes + HiveName: event_data.HiveName + HostVersion: event_data.HostVersion + Image: event_data.Image + ImageLoaded: event_data.ImageLoaded + ImagePath: event_data.ImagePath + Imphash: event_data.Imphash + LogonProcessName: event_data.LogonProcessName + LogonType: event_data.LogonType + NewProcessName: event_data.NewProcessName + ObjectClass: event_data.ObjectClass + ObjectName: event_data.ObjectName + ObjectType: event_data.ObjectType + ObjectValueName: event_data.ObjectValueName + ParentCommandLine: event_data.ParentCommandLine + ParentImage: event_data.ParentImage + Path: event_data.Path + PipeName: event_data.PipeName + ProcessName: event_data.ProcessName + Properties: event_data.Properties + ServiceFileName: event_data.ServiceFileName + ServiceName: event_data.ServiceName + ShareName: event_data.ShareName + Signature: event_data.Signature + Source: event_data.Source + SourceImage: event_data.SourceImage + StartModule: event_data.StartModule + Status: event_data.Status + SubjectUserName: event_data.SubjectUserName + TargetFilename: event_data.TargetFilename + TargetImage: event_data.TargetImage + TargetObject: event_data.TargetObject + TicketEncryptionType: event_data.TicketEncryptionType + TicketOptions: event_data.TicketOptions + User: event_data.User + WorkstationName: event_data.WorkstationName diff --git a/tools/config/filebeat-zeek-ecs.yml b/tools/config/filebeat-zeek-ecs.yml new file mode 100644 index 00000000..9000db4f --- /dev/null +++ b/tools/config/filebeat-zeek-ecs.yml @@ -0,0 +1,468 @@ +title: Zeek field mappings for default collection of JSON logs with no parsing/normalization done and sending into logstash-*index +order: 20 +backends: + - es-qs + - es-dsl + - elasticsearch-rule + - kibana + - xpack-watcher + - elastalert + - elastalert-dsl +logsources: + zeek: + product: zeek + index: 'logstash*' + zeek-category-accounting: + category: accounting + rewrite: + product: zeek + service: syslog + zeek-category-firewall: + category: firewall + conditions: + '@stream': conn + zeek-category-dns: + category: dns + conditions: + '@stream': dns + zeek-category-proxy: + category: proxy + rewrite: + product: zeek + service: http + zeek-category-webserver: + category: webserver + conditions: + '@stream': http + rewrite: + product: zeek + service: http + zeek-conn: + product: zeek + service: conn + conditions: + '@stream': conn + zeek-conn_long: + product: zeek + service: conn_long + conditions: + '@stream': conn_long + zeek-dce_rpc: + product: zeek + service: dce_rpc + conditions: + '@stream': dce_rpc + zeek-dns: + product: zeek + service: dns + conditions: + '@stream': dns + zeek-dnp3: + product: zeek + service: dnp3 + conditions: + '@stream': dnp3 + zeek-dpd: + product: zeek + service: dpd + conditions: + '@stream': dpd + zeek-files: + product: zeek + service: files + conditions: + '@stream': files + zeek-ftp: + product: zeek + service: ftp + conditions: + '@stream': ftp + zeek-gquic: + product: zeek + service: gquic + conditions: + '@stream': gquic + zeek-http: + product: zeek + service: http + conditions: + '@stream': http + zeek-http2: + product: zeek + service: http2 + conditions: + '@stream': http2 + zeek-intel: + product: zeek + service: intel + conditions: + '@stream': intel + zeek-irc: + product: zeek + service: irc + conditions: + '@stream': irc + zeek-kerberos: + product: zeek + service: kerberos + conditions: + '@stream': kerberos + zeek-known_certs: + product: zeek + service: known_certs + conditions: + '@stream': known_certs + zeek-known_hosts: + product: zeek + service: known_hosts + conditions: + '@stream': known_hosts + zeek-known_modbus: + product: zeek + service: known_modbus + conditions: + '@stream': known_modbus + zeek-known_services: + product: zeek + service: known_services + conditions: + '@stream': known_services + zeek-modbus: + product: zeek + service: modbus + conditions: + '@stream': modbus + zeek-modbus_register_change: + product: zeek + service: modbus_register_change + conditions: + '@stream': modbus_register_change + zeek-mqtt_connect: + product: zeek + service: mqtt_connect + conditions: + '@stream': mqtt_connect + zeek-mqtt_publish: + product: zeek + service: mqtt_publish + conditions: + '@stream': mqtt_publish + zeek-mqtt_subscribe: + product: zeek + service: mqtt_subscribe + conditions: + '@stream': mqtt_subscribe + zeek-mysql: + product: zeek + service: mysql + conditions: + '@stream': mysql + zeek-notice: + product: zeek + service: notice + conditions: + '@stream': notice + zeek-ntlm: + product: zeek + service: ntlm + conditions: + '@stream': ntlm + zeek-ntp: + product: zeek + service: ntp + conditions: + '@stream': ntp + zeek-ocsp: + product: zeek + service: ntp + conditions: + '@stream': ocsp + zeek-pe: + product: zeek + service: pe + conditions: + '@stream': pe + zeek-pop3: + product: zeek + service: pop3 + conditions: + '@stream': pop3 + zeek-radius: + product: zeek + service: radius + conditions: + '@stream': radius + zeek-rdp: + product: zeek + service: rdp + conditions: + '@stream': rdp + zeek-rfb: + product: zeek + service: rfb + conditions: + '@stream': rfb + zeek-sip: + product: zeek + service: sip + conditions: + '@stream': sip + zeek-smb_files: + product: zeek + service: smb_files + conditions: + '@stream': smb_files + zeek-smb_mapping: + product: zeek + service: smb_mapping + conditions: + '@stream': smb_mapping + zeek-smtp: + product: zeek + service: smtp + conditions: + '@stream': smtp + zeek-smtp_links: + product: zeek + service: smtp_links + conditions: + '@stream': smtp_links + zeek-snmp: + product: zeek + service: snmp + conditions: + '@stream': snmp + zeek-socks: + product: zeek + service: socks + conditions: + '@stream': socks + zeek-software: + product: zeek + service: software + conditions: + '@stream': software + zeek-ssh: + product: zeek + service: ssh + conditions: + '@stream': ssh + zeek-ssl: + product: zeek + service: ssl + conditions: + '@stream': ssl + zeek-tls: # In case people call it TLS even though orig log is called ssl + product: zeek + service: tls + conditions: + '@stream': ssl + zeek-syslog: + product: zeek + service: syslog + conditions: + '@stream': syslog + zeek-tunnel: + product: zeek + service: tunnel + conditions: + '@stream': tunnel + zeek-traceroute: + product: zeek + service: traceroute + conditions: + '@stream': traceroute + zeek-weird: + product: zeek + service: weird + conditions: + '@stream': weird + zeek-x509: + product: zeek + service: x509 + conditions: + '@stream': x509 + zeek-ip_search: + product: zeek + service: network + conditions: + '@stream': + - conn + - conn_long + - dce_rpc + - dhcp + - dnp3 + - dns + - ftp + - gquic + - http + - irc + - kerberos + - modbus + - mqtt_connect + - mqtt_publish + - mqtt_subscribe + - mysql + - ntlm + - ntp + - radius + - rfb + - sip + - smb_files + - smb_mapping + - smtp + - smtp_links + - snmp + - socks + - ssh + - tls #SSL + - tunnel + - weird +defaultindex: 'logstash-*' +fieldmappings: + # All Logs Applied Mapping & Taxonomy + dst_ip: id.resp_h + dst_port: id.resp_p + network_protocol: proto + src_ip: id.orig_h + src_port: id.orig_p + # DNS matching Taxonomy & DNS Category + answer: answers + #question_length: # Does not exist in open source version + record_type: qtype_name + #parent_domain: # Does not exist in open source version + # HTTP matching Taxonomy & Web/Proxy Category + cs-bytes: request_body_len + cs-cookie: cookie + r-dns: host + sc-bytes: response_body_len + sc-status: status_code + c-uri: uri + c-uri-extension: uri + c-uri-query: uri + c-uri-stem: uri + c-useragent: user_agent + cs-host: host + cs-method: method + cs-referrer: referrer + cs-version: version + # Temporary one off rule name fields + agent.version: version + c-cookie: cookie + c-ip: id.orig_h + cs-uri: uri + clientip: id.orig_h + clientIP: id.orig_h + dest_domain: + - query + - host + - server_name + dest_ip: id.resp_h + dest_port: id.resp_p + #TODO:WhatShouldThisBe?==dest: + #TODO:WhatShouldThisBe?==destination: + #TODO:WhatShouldThisBe?==Destination: + destination.hostname: + - query + - host + - server_name + DestinationAddress: + DestinationHostname: + - host + - query + - server_name + DestinationIp: id.resp_h + DestinationIP: id.resp_h + DestinationPort: id.resp_p + dst-ip: id.resp_h + dstip: id.resp_h + dstport: id.resp_p + Host: + - host + - query + - server_name + HostVersion: http.version + http_host: + - host + - query + - server_name + http_uri: uri + http_url: uri + http_user_agent: user_agent + http.request.url-query-params: uri + HttpMethod: method + in_url: uri + # parent_domain: # Not in open source zeek + post_url_parameter: uri + Request Url: uri + request_url: uri + request_URL: uri + RequestUrl: uri + #response: status_code + resource.url: uri + resource.URL: uri + sc_status: status_code + sender_domain: + - query + - server_name + service.response_code: status_code + source: id.orig_h + SourceAddr: id.orig_h + SourceAddress: id.orig_h + SourceIP: id.orig_h + SourceIp: id.orig_h + SourceNetworkAddress: id.orig_h + SourcePort: id.orig_p + srcip: id.orig_h + Status: status_code + status: status_code + url: uri + URL: uri + url_query: uri + url.query: uri + uri_path: uri + user_agent: user_agent + user_agent.name: user_agent + user-agent: user_agent + User-Agent: user_agent + useragent: user_agent + UserAgent: user_agent + User Agent: user_agent + web_dest: + - host + - query + - server_name + web.dest: + - host + - query + - server_name + Web.dest: + - host + - query + - server_name + web.host: + - host + - query + - server_name + Web.host: + - host + - query + - server_name + web_method: method + Web_method: method + web.method: method + Web.method: method + web_src: id.orig_h + web_status: status_code + Web_status: status_code + web.status: status_code + Web.status: status_code + web_uri: uri + web_url: uri + # Most are in ECS, but for things not using Elastic - these need renamed + destination.ip: id.resp_h + destination.port: id.resp_p + http.request.body.content: post_body + #source.domain: + source.ip: id.orig_h + source.port: id.orig_p \ No newline at end of file diff --git a/tools/config/humio.yml b/tools/config/humio.yml new file mode 100644 index 00000000..dce843f8 --- /dev/null +++ b/tools/config/humio.yml @@ -0,0 +1,625 @@ +title: Humio log source conditions +order: 20 +backends: + - humio +logsources: + zeek: + product: zeek + zeek-category-accounting: + category: accounting + rewrite: + product: zeek + service: syslog + zeek-category-firewall: + category: firewall + rewrite: + product: zeek + service: conn + zeek-category-dns: + category: dns + rewrite: + product: zeek + service: dns + zeek-category-proxy: + category: proxy + rewrite: + product: zeek + service: http + zeek-category-webserver: + category: webserver + rewrite: + product: zeek + service: http + zeek-conn: + product: zeek + service: conn + conditions: + '@stream': conn + zeek-conn_long: + product: zeek + service: conn_long + conditions: + '@stream': conn_long + zeek-dce_rpc: + product: zeek + service: dce_rpc + conditions: + '@stream': dce_rpc + zeek-dns: + product: zeek + service: dns + conditions: + '@stream': dns + zeek-dnp3: + product: zeek + service: dnp3 + conditions: + '@stream': dnp3 + zeek-dpd: + product: zeek + service: dpd + conditions: + '@stream': dpd + zeek-files: + product: zeek + service: files + conditions: + '@stream': files + zeek-ftp: + product: zeek + service: ftp + conditions: + '@stream': ftp + zeek-gquic: + product: zeek + service: gquic + conditions: + '@stream': gquic + zeek-http: + product: zeek + service: http + conditions: + '@stream': http + zeek-http2: + product: zeek + service: http2 + conditions: + '@stream': http2 + zeek-intel: + product: zeek + service: intel + conditions: + '@stream': intel + zeek-irc: + product: zeek + service: irc + conditions: + '@stream': irc + zeek-kerberos: + product: zeek + service: kerberos + conditions: + '@stream': kerberos + zeek-known_certs: + product: zeek + service: known_certs + conditions: + '@stream': known_certs + zeek-known_hosts: + product: zeek + service: known_hosts + conditions: + '@stream': known_hosts + zeek-known_modbus: + product: zeek + service: known_modbus + conditions: + '@stream': known_modbus + zeek-known_services: + product: zeek + service: known_services + conditions: + '@stream': known_services + zeek-modbus: + product: zeek + service: modbus + conditions: + '@stream': modbus + zeek-modbus_register_change: + product: zeek + service: modbus_register_change + conditions: + '@stream': modbus_register_change + zeek-mqtt_connect: + product: zeek + service: mqtt_connect + conditions: + '@stream': mqtt_connect + zeek-mqtt_publish: + product: zeek + service: mqtt_publish + conditions: + '@stream': mqtt_publish + zeek-mqtt_subscribe: + product: zeek + service: mqtt_subscribe + conditions: + '@stream': mqtt_subscribe + zeek-mysql: + product: zeek + service: mysql + conditions: + '@stream': mysql + zeek-notice: + product: zeek + service: notice + conditions: + '@stream': notice + zeek-ntlm: + product: zeek + service: ntlm + conditions: + '@stream': ntlm + zeek-ntp: + product: zeek + service: ntp + conditions: + '@stream': ntp + zeek-ocsp: + product: zeek + service: ntp + conditions: + '@stream': ocsp + zeek-pe: + product: zeek + service: pe + conditions: + '@stream': pe + zeek-pop3: + product: zeek + service: pop3 + conditions: + '@stream': pop3 + zeek-radius: + product: zeek + service: radius + conditions: + '@stream': radius + zeek-rdp: + product: zeek + service: rdp + conditions: + '@stream': rdp + zeek-rfb: + product: zeek + service: rfb + conditions: + '@stream': rfb + zeek-sip: + product: zeek + service: sip + conditions: + '@stream': sip + zeek-smb_files: + product: zeek + service: smb_files + conditions: + '@stream': smb_files + zeek-smb_mapping: + product: zeek + service: smb_mapping + conditions: + '@stream': smb_mapping + zeek-smtp: + product: zeek + service: smtp + conditions: + '@stream': smtp + zeek-smtp_links: + product: zeek + service: smtp_links + conditions: + '@stream': smtp_links + zeek-snmp: + product: zeek + service: snmp + conditions: + '@stream': snmp + zeek-socks: + product: zeek + service: socks + conditions: + '@stream': socks + zeek-software: + product: zeek + service: software + conditions: + '@stream': software + zeek-ssh: + product: zeek + service: ssh + conditions: + '@stream': ssh + zeek-ssl: + product: zeek + service: ssl + conditions: + '@stream': ssl + zeek-tls: # In case people call it TLS even though orig log is called ssl + product: zeek + service: tls + conditions: + '@stream': ssl + zeek-syslog: + product: zeek + service: syslog + conditions: + '@stream': syslog + zeek-tunnel: + product: zeek + service: tunnel + conditions: + '@stream': tunnel + zeek-traceroute: + product: zeek + service: traceroute + conditions: + '@stream': traceroute + zeek-weird: + product: zeek + service: weird + conditions: + '@stream': weird + zeek-x509: + product: zeek + service: x509 + conditions: + '@stream': x509 + zeek-ip_search: + product: zeek + service: network + conditions: + '@stream': + - conn + - conn_long + - dce_rpc + - dhcp + - dnp3 + - dns + - ftp + - gquic + - http + - irc + - kerberos + - modbus + - mqtt_connect + - mqtt_publish + - mqtt_subscribe + - mysql + - ntlm + - ntp + - radius + - rfb + - sip + - smb_files + - smb_mapping + - smtp + - smtp_links + - snmp + - socks + - ssh + - tls #SSL + - tunnel + - weird +fieldmappings: + # Deep mappings Taxonomy for overall/general fields + dst_ip: + product=windows: winlog.event_data.DestinationIp + product=zeek: id.resp_h + src_ip: + product=windows: winlog.event_data.SourceIp + product=zeek: id.orig_h + dst_port: + product=windows: winlog.event_data.DestinationPort + product=zeek: id.resp_p + src_port: + product=windows: winlog.event_data.SourcePort + product=zeek: id.orig_p + network_protocol: + product=zeek: proto + # Deep mappings Taxonomy for DNS Category and DNS service + answer: + product=zeek: answers + #question_length: # product=zeek: # Does not exist in open source version + record_type: + product=zeek: qtype_name + #parent_domain: #product=zeek: # Does not exist in open source version + # Deep mappings Taxonomy for HTTP, Webserver category, and Proxy category + cs-bytes: + product=zeek: request_body_len + cs-cookie: + product=zeek: cookie + r-dns: + product=zeek: host + sc-bytes: + product=zeek: response_body_len + sc-status: + product=zeek: status_code + c-uri: + product=zeek: uri + c-uri-extension: + product=zeek: uri + c-uri-query: + product=zeek: uri + c-uri-stem: + product=zeek: uri + c-useragent: + product=zeek: user_agent + cs-host: + product=zeek: host + cs-method: + product=zeek: method + cs-referrer: + product=zeek: referrer + cs-version: + product=zeek: version + # Windows / WEF / Winlogbeat + EventID: winlog.event_id + Event_ID: winlog.event_id + eventId: winlog.event_id + event_id: winlog.event_id + event-id: winlog.event_id + eventid: winlog.event_id + AccessMask: winlog.event_data.AccessMask + AccountName: winlog.event_data.AccountName + AllowedToDelegateTo: winlog.event_data.AllowedToDelegateTo + AttributeLDAPDisplayName: winlog.event_data.AttributeLDAPDisplayName + AuditPolicyChanges: winlog.event_data.AuditPolicyChanges + AuthenticationPackageName: winlog.event_data.AuthenticationPackageName + CallingProcessName: winlog.event_data.CallingProcessName + CallTrace: winlog.event_data.CallTrace + Channel: winlog.channel + CommandLine: winlog.event_data.CommandLine + ComputerName: winlog.ComputerName + CurrentDirectory: winlog.event_data.CurrentDirectory + Description: winlog.event_data.Description + DestinationHostname: winlog.event_data.DestinationHostname + DestinationIp: winlog.event_data.DestinationIp + DestinationIsIpv6: winlog.event_data.DestinationIsIpv6 + DestinationPort: winlog.event_data.DestinationPort + Details: winlog.event_data.Details + EngineVersion: winlog.event_data.EngineVersion + EventType: winlog.event_data.EventType + FailureCode: winlog.event_data.FailureCode + FileName: winlog.event_data.FileName + GrantedAccess: winlog.event_data.GrantedAccess + GroupName: winlog.event_data.GroupName + GroupSid: winlog.event_data.GroupSid + Hashes: winlog.event_data.Hashes + HiveName: winlog.event_data.HiveName + HostVersion: winlog.event_data.HostVersion + Image: winlog.event_data.Image + ImageLoaded: winlog.event_data.ImageLoaded + ImagePath: winlog.event_data.ImagePath + Imphash: winlog.event_data.Imphash + IpAddress: winlog.event_data.IpAddress + KeyLength: winlog.event_data.KeyLength + LogonProcessName: winlog.event_data.LogonProcessName + LogonType: winlog.event_data.LogonType + NewProcessName: winlog.event_data.NewProcessName + ObjectClass: winlog.event_data.ObjectClass + ObjectName: winlog.event_data.ObjectName + ObjectType: winlog.event_data.ObjectType + ObjectValueName: winlog.event_data.ObjectValueName + ParentCommandLine: winlog.event_data.ParentCommandLine + ParentProcessName: winlog.event_data.ParentProcessName + ParentImage: winlog.event_data.ParentImage + Path: winlog.event_data.Path + PipeName: winlog.event_data.PipeName + ProcessCommandLine: winlog.event_data.ProcessCommandLine + ProcessName: winlog.event_data.ProcessName + Properties: winlog.event_data.Properties + SecurityID: winlog.event_data.SecurityID + ServiceFileName: winlog.event_data.ServiceFileName + ServiceName: winlog.event_data.ServiceName + ShareName: winlog.event_data.ShareName + Signature: winlog.event_data.Signature + Source: winlog.event_data.Source + SourceImage: winlog.event_data.SourceImage + SourceIp: winlog.event_data.SourceIp + StartModule: winlog.event_data.StartModule + Status: winlog.event_data.Status + SubjectUserName: winlog.event_data.SubjectUserName + SubjectUserSid: winlog.event_data.SubjectUserSid + TargetFilename: winlog.event_data.TargetFilename + Targetfilename: winlog.event_data.TargetFilename + TargetImage: winlog.event_data.TargetImage + TargetObject: winlog.event_data.TargetObject + TicketEncryptionType: winlog.event_data.TicketEncryptionType + TicketOptions: winlog.event_data.TicketOptions + User: winlog.event_data.User + WorkstationName: winlog.event_data.WorkstationName + # Channel: WLAN-Autoconfig AND EventID: 8001 + AuthenticationAlgorithm: winlog.event_data.AuthenticationAlgorithm + BSSID: winlog.event_data.BSSID + BSSType: winlog.event_data.BSSType + CipherAlgorithm: winlog.event_data.CipherAlgorithm + ConnectionId: winlog.event_data.ConnectionId + ConnectionMode: winlog.event_data.ConnectionMode + InterfaceDescription: winlog.event_data.InterfaceDescription + InterfaceGuid: winlog.event_data.InterfaceGuid + OnexEnabled: winlog.event_data.OnexEnabled + PHYType: winlog.event_data.PHYType + ProfileName: winlog.event_data.ProfileName + SSID: winlog.event_data.SSID + # Zeek Deep Mappings + # Temporary one off rule name fields + agent.version: + product=zeek: version + c-cookie: + product=zeek: cookie + c-ip: + product=zeek: id.orig_h + cs-uri: + product=zeek: uri + clientip: + product=zeek: id.orig_h + clientIP: + product=zeek: id.orig_h + dest_domain: + product=zeek: host + #- query + #- server_name + dest_ip: + product=zeek: id.resp_h + dest_port: + product=zeek: id.resp_p + #TODO:WhatShouldThisBe?==dest: + #TODO:WhatShouldThisBe?==destination: + #TODO:WhatShouldThisBe?==Destination: + destination.hostname: + product=zeek: host + #- query + #- server_name + DestinationAddress: + product=zeek: id.resp_h + dst-ip: + product=zeek: id.resp_h + dstip: + product=zeek: id.resp_h + dstport: + product=zeek: id.resp_p + Host: + product=zeek: host + #- query + #- server_name + http_host: + product=zeek: host + #- query + #- server_name + http_uri: + product=zeek: uri + http_url: + product=zeek: uri + http_user_agent: + product=zeek: user_agent + http.request.url-query-params: + product=zeek: uri + HttpMethod: + product=zeek: method + in_url: + product=zeek: uri + post_url_parameter: + product=zeek: uri + Request Url: + product=zeek: uri + request_url: + product=zeek: uri + request_URL: + product=zeek: uri + RequestUrl: + product=zeek: uri + response: + product=zeek: status_code + resource.url: + product=zeek: uri + resource.URL: + product=zeek: uri + sc_status: + product=zeek: status_code + service.response_code: + product=zeek: status_code + source: + product=zeek: id.orig_h + SourceAddr: + product=zeek: id.orig_h + SourceAddress: + product=zeek: id.orig_h + SourceIP: + product=zeek: id.orig_h + SourceNetworkAddress: + product=zeek: id.orig_h + SourcePort: + product=zeek: id.orig_p + srcip: + product=zeek: id.orig_h + status: + product=zeek: status_code + url: + product=zeek: uri + URL: + product=zeek: uri + url_query: + product=zeek: uri + url.query: + product=zeek: uri + uri_path: + product=zeek: uri + user_agent: + product=zeek: user_agent + user_agent.name: + product=zeek: user_agent + user-agent: + product=zeek: user_agent + User-Agent: + product=zeek: user_agent + useragent: + product=zeek: user_agent + UserAgent: + product=zeek: user_agent + User Agent: + product=zeek: user_agent + web_dest: + product=zeek: host + #- query + #- server_name + web.dest: + product=zeek: host + #- query + #- server_name + Web.dest: + product=zeek: host + #- query + #- server_name + web.host: + product=zeek: host + #- query + #- server_name + Web.host: + product=zeek: host + #- query + #- server_name + web_method: + product=zeek: method + Web_method: + product=zeek: method + web.method: + product=zeek: method + Web.method: + product=zeek: method + web_src: + product=zeek: id.orig_h + web_status: + product=zeek: status_code + Web_status: + product=zeek: status_code + web.status: + product=zeek: status_code + Web.status: + product=zeek: status_code + web_uri: + product=zeek: uri + web_url: + product=zeek: uri + # Already + destination.ip: + product=zeek: id.resp_h + destination.port: + product=zeek: id.resp_p + http.request.body.content: + product=zeek: post_body + #source.domain: + source.ip: + product=zeek: id.orig_h + source.port: + product=zeek: id.orig_p diff --git a/tools/config/logstash-zeek-default-json.yml b/tools/config/logstash-zeek-default-json.yml index 7f5f16ff..6915fe14 100644 --- a/tools/config/logstash-zeek-default-json.yml +++ b/tools/config/logstash-zeek-default-json.yml @@ -363,4 +363,111 @@ fieldmappings: - host - server_name dest_ip: id.resp_h - dest_port: id.resp_p \ No newline at end of file + dest_port: id.resp_p + #TODO:WhatShouldThisBe?==dest: + #TODO:WhatShouldThisBe?==destination: + #TODO:WhatShouldThisBe?==Destination: + destination.hostname: + - query + - host + - server_name + DestinationAddress: id.resp_h + DestinationHostname: + - host + - query + - server_name + DestinationIp: id.resp_h + DestinationIP: id.resp_h + DestinationPort: id.resp_p + dst-ip: id.resp_h + dstip: id.resp_h + dstport: id.resp_p + Host: + - host + - query + - server_name + HostVersion: http.version + http_host: + - host + - query + - server_name + http_uri: uri + http_url: uri + http_user_agent: user_agent + http.request.url-query-params: uri + HttpMethod: method + in_url: uri + # parent_domain: # Not in open source zeek + post_url_parameter: uri + Request Url: uri + request_url: uri + request_URL: uri + RequestUrl: uri + #response: status_code + resource.url: uri + resource.URL: uri + sc_status: status_code + sender_domain: + - query + - server_name + service.response_code: status_code + source: id.orig_h + SourceAddr: id.orig_h + SourceAddress: id.orig_h + SourceIP: id.orig_h + SourceIp: id.orig_h + SourceNetworkAddress: id.orig_h + SourcePort: id.orig_p + srcip: id.orig_h + Status: status_code + status: status_code + url: uri + URL: uri + url_query: uri + url.query: uri + uri_path: uri + user_agent: user_agent + user_agent.name: user_agent + user-agent: user_agent + User-Agent: user_agent + useragent: user_agent + UserAgent: user_agent + User Agent: user_agent + web_dest: + - host + - query + - server_name + web.dest: + - host + - query + - server_name + Web.dest: + - host + - query + - server_name + web.host: + - host + - query + - server_name + Web.host: + - host + - query + - server_name + web_method: method + Web_method: method + web.method: method + Web.method: method + web_src: id.orig_h + web_status: status_code + Web_status: status_code + web.status: status_code + Web.status: status_code + web_uri: uri + web_url: uri + # Most are in ECS, but for things not using Elastic - these need renamed + destination.ip: id.resp_h + destination.port: id.resp_p + http.request.body.content: post_body + #source.domain: + source.ip: id.orig_h + source.port: id.orig_p diff --git a/tools/config/powershell-windows-all.yml b/tools/config/powershell-windows-all.yml new file mode 100644 index 00000000..8464ade0 --- /dev/null +++ b/tools/config/powershell-windows-all.yml @@ -0,0 +1,62 @@ +logsources: + windows-application: + product: windows + service: application + conditions: + LogName: 'Application' + windows-security: + product: windows + service: security + conditions: + LogName: 'Security' + windows-system: + product: windows + service: system + conditions: + LogName: 'System' + windows-sysmon: + product: windows + service: sysmon + conditions: + LogName: 'Microsoft-Windows-Sysmon/Operational' + windows-powershell: + product: windows + service: powershell + conditions: + LogName: 'Microsoft-Windows-PowerShell/Operational' + windows-classicpowershell: + product: windows + service: powershell-classic + conditions: + LogName: 'Windows PowerShell' + windows-taskscheduler: + product: windows + service: taskscheduler + conditions: + LogName: 'Microsoft-Windows-TaskScheduler/Operational' + windows-wmi: + product: windows + service: wmi + conditions: + LogName: 'Microsoft-Windows-WMI-Activity/Operational' + windows-dns-server: + product: windows + service: dns-server + category: dns + conditions: + LogName: 'DNS Server' + windows-dns-server-audit: + product: windows + service: dns-server-audit + conditions: + LogName: 'Microsoft-Windows-DNS-Server/Audit' + windows-driver-framework: + product: windows + service: driver-framework + conditions: + LogName: 'Microsoft-Windows-DriverFrameworks-UserMode/Operational' + windows-ntlm: + product: windows + service: ntlm + conditions: + LogName: 'Microsoft-Windows-NTLM/Operational' diff --git a/tools/config/qradar.yml b/tools/config/qradar.yml index 1768f96b..428a73cf 100644 --- a/tools/config/qradar.yml +++ b/tools/config/qradar.yml @@ -1,52 +1,98 @@ title: QRadar backends: - - qradar + - qradar order: 20 logsources: - apache: - product: apache - conditions: - LOGSOURCETYPENAME(devicetype): ilike '%apache%' - - windows: - product: windows - conditions: - LOGSOURCETYPENAME(devicetype): 'Microsoft Windows Security Event Log' - - qflow: - product: qflow - index: flows - - netflow: - product: netflow - index: flows - - ipfix: - product: ipfix - index: flows - - flow: - category: flow - index: flows - + apache: + product: apache + index: apache + conditions: + LOGSOURCETYPENAME(devicetype): '*apache*' + windows: + product: windows + index: windows + conditions: + LOGSOURCETYPENAME(devicetype): '*Microsoft Windows Security Event Log*' + qflow: + product: qflow + index: flows + netflow: + product: netflow + index: flows + ipfix: + product: ipfix + index: flows + flow: + category: flow + index: flows fieldmappings: - EventID: - - Event ID Code - dst: - - destinationIP - dst_ip: - - destinationIP - src: - - sourceIP - src_ip: - - sourceIP - c-ip: sourceIP - cs-ip: sourceIP - c-uri: url - c-uri-extension: file_extension - c-useragent: user_agent - c-uri-query: uri_query - cs-method: Method - r-dns: FQDN - ClientIP: sourceIP - ServiceFileName: Service Name + event_id: EventID + EventID: EventID + dst: destinationip + dst_ip: destinationip + src: sourceip + src_ip: sourceip + c-ip: sourceip + cs-ip: sourceip + c-uri: URL + c-uri-extension: URL + c-useragent: user_agent + c-uri-query: uri_query + cs-method: Method + r-dns: FQDN + ClientIP: sourceip + ServiceFileName: ServiceFileName + event_data.CommandLine: Process CommandLine + CommandLine: Process CommandLine + file_hash: File Hash + hash: File Hash + #Message: search_payload + Event-ID: EventID + Event_ID: EventID + eventId: EventID + event-id: EventID + eventid: EventID + hashes: File Hash + url.query: URL + resource.URL: URL + event_data.CallingProcessName: CallingProcessName + event_data.ComputerName: Hostname/HOSTNAME + ComputerName: Hostname/HOSTNAME + event_data.DestinationHostname: Hostname/HOSTNAME + DestinationHostname: Hostname/HOSTNAME + event_data.DestinationIp: destinationip + event_data.DestinationPort: destinationip + event_data.Details: Target Details + Details: Target Details + event_data.FileName: Filename + event_data.Hashes: File Hash + Hashes: File Hash + event_data.Image: Image + event_data.ImageLoaded: LoadedImage + event_data.ImagePath: SourceImage + ImagePath: Image + event_data.Imphash: IMP Hash + Imphash: IMP Hash + event_data.ParentCommandLine: ParentCommandLine + event_data.ParentImage: ParentImage + event_data.ParentProcessName: ParentImageName + event_data.Path: File Path + Path: File Path + event_data.PipeName: PipeName + event_data.ProcessCommandLine: Process CommandLine + ProcessCommandLine: Process CommandLine + event_data.ServiceFileName: ServiceFileName + event_data.ShareName: ShareName + event_data.Signature: Signature + event_data.SourceImage: SourceImage + event_data.StartModule: StartModule + event_data.SubjectUserName: username + event_data.SubjectUserSid: SubjectUserSid + event_data.TargetFilename: Filename + TargetFilename: Filename + event_data.TargetImage: TargetImage + TargetImage: TargetImage + event_data.TicketOptions: TicketOptions + event_data.User: username + User: username + user: username \ No newline at end of file diff --git a/tools/config/splunk-zeek.yml b/tools/config/splunk-zeek.yml index c126b633..1cefcca7 100644 --- a/tools/config/splunk-zeek.yml +++ b/tools/config/splunk-zeek.yml @@ -343,4 +343,127 @@ fieldmappings: id_orig_h: id.orig_h id_orig_p: id.orig_p id_resp_h: id.resp_h - id_resp_p: id.resp_p \ No newline at end of file + id_resp_p: id.resp_p + # Temporary one off rule name fields + agent.version: version + c-cookie: cookie + c-ip: id.orig_h + cs-uri: uri + clientip: id.orig_h + clientIP: id.orig_h + dest_domain: + - query + - host + - server_name + dest_ip: id.resp_h + dest_port: id.resp_p + #TODO:WhatShouldThisBe?==dest: + #TODO:WhatShouldThisBe?==destination: + #TODO:WhatShouldThisBe?==Destination: + destination.hostname: + - query + - host + - server_name + DestinationAddress: id.resp_h + DestinationHostname: + - host + - query + - server_name + DestinationIp: id.resp_h + DestinationIP: id.resp_h + DestinationPort: id.resp_p + dst-ip: id.resp_h + dstip: id.resp_h + dstport: id.resp_p + Host: + - host + - query + - server_name + HostVersion: http.version + http_host: + - host + - query + - server_name + http_uri: uri + http_url: uri + http_user_agent: user_agent + http.request.url-query-params: uri + HttpMethod: method + in_url: uri + # parent_domain: # Not in open source zeek + post_url_parameter: uri + Request Url: uri + request_url: uri + request_URL: uri + RequestUrl: uri + #response: status_code + resource.url: uri + resource.URL: uri + sc_status: status_code + sender_domain: + - query + - server_name + service.response_code: status_code + source: id.orig_h + SourceAddr: id.orig_h + SourceAddress: id.orig_h + SourceIP: id.orig_h + SourceIp: id.orig_h + SourceNetworkAddress: id.orig_h + SourcePort: id.orig_p + srcip: id.orig_h + Status: status_code + status: status_code + url: uri + URL: uri + url_query: uri + url.query: uri + uri_path: uri + user_agent: user_agent + user_agent.name: user_agent + user-agent: user_agent + User-Agent: user_agent + useragent: user_agent + UserAgent: user_agent + User Agent: user_agent + web_dest: + - host + - query + - server_name + web.dest: + - host + - query + - server_name + Web.dest: + - host + - query + - server_name + web.host: + - host + - query + - server_name + Web.host: + - host + - query + - server_name + web_method: method + Web_method: method + web.method: method + Web.method: method + web_src: id.orig_h + web_status: status_code + Web_status: status_code + web.status: status_code + Web.status: status_code + web_uri: uri + web_url: uri + # Most are in ECS, but for things not using Elastic - these need renamed + destination.ip: id.resp_h + destination.port: id.resp_p + http.request.body.content: post_body + source.domain: + - host + - query + - server_name + source.ip: id.orig_h + source.port: id.orig_p diff --git a/tools/config/winlogbeat-modules-enabled.yml b/tools/config/winlogbeat-modules-enabled.yml index 2acf480e..69954e22 100644 --- a/tools/config/winlogbeat-modules-enabled.yml +++ b/tools/config/winlogbeat-modules-enabled.yml @@ -60,8 +60,7 @@ fieldmappings: CallTrace: winlog.event_data.CallTrace Channel: winlog.channel CommandLine: process.args - ComputerName: winlog.computer_name - ContextInfo: winlog.event_data.ContextInfo + ComputerName: winlog.ComputerName CurrentDirectory: process.working_directory Description: winlog.event_data.Description DestinationHostname: destination.domain @@ -84,6 +83,7 @@ fieldmappings: - group.id - winlog.event_data.GroupSid Hashes: winlog.event_data.Hashes + file_hash: winlog.event_data.Hashes HiveName: winlog.event_data.HiveName HostVersion: winlog.event_data.HostVersion Image: process.executable @@ -95,7 +95,6 @@ fieldmappings: KeyLength: winlog.event_data.KeyLength LogonProcessName: winlog.event_data.LogonProcessName LogonType: winlog.event_data.LogonType - Message: winlog.event_data.Message NewProcessName: winlog.event_data.NewProcessName ObjectClass: winlog.event_data.ObjectClass ObjectName: winlog.event_data.ObjectName diff --git a/tools/config/winlogbeat-old.yml b/tools/config/winlogbeat-old.yml index f840408b..ce0124fd 100644 --- a/tools/config/winlogbeat-old.yml +++ b/tools/config/winlogbeat-old.yml @@ -59,8 +59,7 @@ fieldmappings: CallTrace: event_data.CallTrace Channel: winlog.channel CommandLine: event_data.CommandLine - ComputerName: computer_name - ContextInfo: event_data.ContextInfo + ComputerName: event_data.ComputerName CurrentDirectory: event_data.CurrentDirectory Description: event_data.Description DestinationHostname: event_data.DestinationHostname @@ -86,7 +85,6 @@ fieldmappings: KeyLength: event_data.KeyLength LogonProcessName: event_data.LogonProcessName LogonType: event_data.LogonType - Message: event_data.Message NewProcessName: event_data.NewProcessName ObjectClass: event_data.ObjectClass ObjectName: event_data.ObjectName diff --git a/tools/config/winlogbeat.yml b/tools/config/winlogbeat.yml index 91921ff6..2171cef0 100644 --- a/tools/config/winlogbeat.yml +++ b/tools/config/winlogbeat.yml @@ -59,8 +59,7 @@ fieldmappings: CallTrace: winlog.event_data.CallTrace Channel: winlog.channel CommandLine: winlog.event_data.CommandLine - ComputerName: winlog.computer_name - ContextInfo: winlog.event_data.ContextInfo + ComputerName: winlog.ComputerName CurrentDirectory: winlog.event_data.CurrentDirectory Description: winlog.event_data.Description DestinationHostname: winlog.event_data.DestinationHostname @@ -88,7 +87,6 @@ fieldmappings: KeyLength: winlog.event_data.KeyLength LogonProcessName: winlog.event_data.LogonProcessName LogonType: winlog.event_data.LogonType - Message: winlog.event_data.Message NewProcessName: winlog.event_data.NewProcessName ObjectClass: winlog.event_data.ObjectClass ObjectName: winlog.event_data.ObjectName @@ -137,4 +135,4 @@ fieldmappings: OnexEnabled: winlog.event_data.OnexEnabled PHYType: winlog.event_data.PHYType ProfileName: winlog.event_data.ProfileName - SSID: winlog.event_data.SSID \ No newline at end of file + SSID: winlog.event_data.SSID diff --git a/tools/sigma/backends/ala.py b/tools/sigma/backends/ala.py index ea5fd950..bffd4ebf 100644 --- a/tools/sigma/backends/ala.py +++ b/tools/sigma/backends/ala.py @@ -13,22 +13,49 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . - -import re, json +import os +import sys +import re +import json import xml.etree.ElementTree as xml -from ..config.mapping import ( +from sigma.config.mapping import ( SimpleFieldMapping, MultiFieldMapping, ConditionalFieldMapping ) -from ..parser.condition import SigmaAggregationParser -from ..parser.exceptions import SigmaParseError -from ..parser.modifiers.type import SigmaRegularExpressionModifier -from .base import SingleTextQueryBackend +from sigma.parser.condition import SigmaAggregationParser + +from sigma.parser.modifiers.type import SigmaRegularExpressionModifier +from sigma.backends.base import SingleTextQueryBackend + +from sigma.parser.modifiers.base import SigmaTypeModifier +from sigma.parser.modifiers.transform import SigmaContainsModifier, SigmaStartswithModifier, SigmaEndswithModifier from .data import sysmon_schema from .exceptions import NotSupportedError -class AzureLogAnalyticsBackend(SingleTextQueryBackend): +class DeepFieldMappingMixin(object): + + def fieldNameMapping(self, fieldname, value): + if isinstance(fieldname, str): + get_config = self.sigmaconfig.fieldmappings.get(fieldname) + if not get_config and '|' in fieldname: + fieldname = fieldname.split('|', 1)[0] + get_config = self.sigmaconfig.fieldmappings.get(fieldname) + if isinstance(get_config, ConditionalFieldMapping): + condition = self.sigmaconfig.fieldmappings.get(fieldname).conditions + for key, item in self.logsource.items(): + if condition.get(key) and condition.get(key, {}).get(item): + new_fieldname = condition.get(key, {}).get(item) + if any(new_fieldname): + return super().fieldNameMapping(new_fieldname[0], value) + return super().fieldNameMapping(fieldname, value) + + + def generate(self, sigmaparser): + self.logsource = sigmaparser.parsedyaml.get("logsource", {}) + return super().generate(sigmaparser) + +class AzureLogAnalyticsBackend(DeepFieldMappingMixin, SingleTextQueryBackend): """Converts Sigma rule into Azure Log Analytics Queries.""" identifier = "ala" active = True @@ -43,8 +70,7 @@ class AzureLogAnalyticsBackend(SingleTextQueryBackend): ) config_required = False - reEscape = re.compile('("|(?', val) val = re.sub('\\*', '.*', val) + if "\\" in val: + return "%s \"(?i)%s\"" % (op, val) + return "%s \"(?i)%s\"" % (op, val) + elif val.startswith("*") or val.endswith("*"): + op = "contains" + val = re.sub('([".^$]|(?![*?]))', '\g<1>', val) + val = re.sub('\\*', '', val) val = re.sub('\\?', '.', val) - if "\\" in val: - return "%s @\"%s\"" % (op, val) - else: # value possibly only starts and/or ends with *, use prefix/postfix match - if val.endswith("*") and val.startswith("*"): - op = "contains" - val = self.cleanValue(val[1:-1]) - elif val.endswith("*"): - op = "startswith" - val = self.cleanValue(val[:-1]) - elif val.startswith("*"): - op = "endswith" - val = self.cleanValue(val[1:]) - - if "\\" in val: - return "%s @\"%s\"" % (op, val) - + # if "\\" in val: + # return "%s @\"%s\"" % (op, val) + return "%s \"%s\"" % (op, val) + # elif "\\" in val: + # return "%s @\"%s\"" % (op, val) return "%s \"%s\"" % (op, val) def generate(self, sigmaparser): self.table = None - try: - self.category = sigmaparser.parsedyaml['logsource'].setdefault('category', None) - self.product = sigmaparser.parsedyaml['logsource'].setdefault('product', None) - self.service = sigmaparser.parsedyaml['logsource'].setdefault('service', None) - except KeyError: - self.category = None - self.product = None - self.service = None + self.category = sigmaparser.parsedyaml['logsource'].setdefault('category', None) + self.product = sigmaparser.parsedyaml['logsource'].setdefault('product', None) + self.service = sigmaparser.parsedyaml['logsource'].setdefault('service', None) detection = sigmaparser.parsedyaml.get("detection", {}) - is_parent_cmd = False if "keywords" in detection.keys(): return super().generate(sigmaparser) - if self.category == "process_creation": - self.table = "SysmonEvent" + self.table = "SecurityEvent" self.eventid = "1" elif self.service == "security": self.table = "SecurityEvent" @@ -154,6 +167,12 @@ class AzureLogAnalyticsBackend(SingleTextQueryBackend): self.table = "SysmonEvent" elif self.service == "powershell": self.table = "Event" + elif self.service == "office365": + self.table = "OfficeActivity" + elif self.service == "azuread": + self.table = "AuditLogs" + elif self.service == "azureactivity": + self.table = "AzureActivity" else: if self.service: if "-" in self.service: @@ -181,8 +200,8 @@ class AzureLogAnalyticsBackend(SingleTextQueryBackend): elif self.sysmon: parse_string = self.map_sysmon_schema(self.eventid) before = "%s | parse EventData with * %s | where " % (self.table, parse_string) - elif self.category == "process_creation" and not self._has_logsource_event_cond: - before = "%s | where EventID == \"%s\" | where " % (self.table, self.eventid) + # elif self.category == "process_creation" and not self._has_logsource_event_cond: + # before = "%s | where EventID == \"%s\" | where " % (self.table, self.eventid) else: before = "%s | where " % self.table return before @@ -193,6 +212,7 @@ class AzureLogAnalyticsBackend(SingleTextQueryBackend): and creates an appropriate table reference. """ key, value = node + key = self.fieldNameMapping(key, value) if type(value) == list: # handle map items with values list like multiple OR-chained conditions return "(" + self.generateORNode( [(key, v) for v in value] @@ -207,17 +227,26 @@ class AzureLogAnalyticsBackend(SingleTextQueryBackend): self.table = "SecurityEvent" elif self.service == "system": self.table = "Event" - elif type(value) in (str, int): # default value processing - mapping = (key, self.default_value_mapping) + return self.mapExpression % (key, value) + elif type(value) in [SigmaTypeModifier, SigmaContainsModifier, SigmaRegularExpressionModifier, SigmaStartswithModifier, SigmaEndswithModifier]: + return self.generateMapItemTypedNode(key, value) + elif type(value) in (str, int): # default value processing' + #default_filters = ["endswith", "contains", "startswith", "re"] + # if any([item for item in default_filters if item in key]): + # key = re.sub(key, default_filters, "") + # return self.regexExpression % (key, self.cleanValue(value)) + # else: + # value_mapping = self.default_value_mapping + value_mapping = self.default_value_mapping + mapping = (key, value_mapping) if len(mapping) == 1: mapping = mapping[0] if type(mapping) == str: return mapping elif callable(mapping): - conds = mapping(key, value) return self.generateSubexpressionNode( self.generateANDNode( - [cond for cond in mapping(key, value)] + [cond for cond in mapping(key, self.cleanValue(value))] ) ) elif len(mapping) == 2: @@ -226,12 +255,29 @@ class AzureLogAnalyticsBackend(SingleTextQueryBackend): if type(mapitem) == str: result.append(mapitem) elif callable(mapitem): - result.append(mapitem(val)) + result.append(mapitem(self.cleanValue(val))) return "{} {}".format(*result) else: raise TypeError("Backend does not support map values of type " + str(type(value))) + elif type(value) == list: + return self.generateMapItemListNode(key, value) - return super().generateMapItemNode(node) + elif value is None: + return self.nullExpression % (key, ) + else: + raise TypeError("Backend does not support map values of type " + str(type(value))) + + def generateMapItemTypedNode(self, fieldname, value): + return "%s %s" % (fieldname, self.generateTypedValueNode(value)) + + def generateTypedValueNode(self, node): + try: + val = str(node) + if "*" in val: + val = re.sub('\\*', '.*', val) + return self.typedValueExpression[type(node)] % (val) + except KeyError: + raise NotImplementedError("Type modifier '{}' is not supported by backend".format(node.identifier)) def generateAggregation(self, agg): if agg is None: @@ -269,36 +315,6 @@ class AzureLogAnalyticsBackend(SingleTextQueryBackend): ) ) - def generateAfter(self, parsed): - del parsed - if self._fields: - all_fields = list(self._fields) - if self._agg_var: - all_fields = set(all_fields + [self._agg_var]) - project_fields = self._map_fields(all_fields) - project_list = ", ".join(str(fld) for fld in set(project_fields)) - return " | project " + project_list - return "" - - def _map_fields(self, fields): - for field in fields: - mapped_field = self._map_field(field) - if isinstance(mapped_field, str): - yield mapped_field - elif isinstance(mapped_field, list): - for subfield in mapped_field: - yield subfield - - def _map_field(self, fieldname): - mapping = self.sigmaconfig.fieldmappings.get(fieldname) - if isinstance(mapping, ConditionalFieldMapping): - fieldname = self._map_conditional_field(fieldname) - elif isinstance(mapping, MultiFieldMapping): - fieldname = mapping.resolve_fieldname(fieldname, self._parser) - elif isinstance(mapping, SimpleFieldMapping): - fieldname = mapping.resolve_fieldname(fieldname, self._parser) - return fieldname - def _map_conditional_field(self, fieldname): mapping = self.sigmaconfig.fieldmappings.get(fieldname) # if there is a conditional mapping for this fieldname @@ -325,35 +341,89 @@ class AzureAPIBackend(AzureLogAnalyticsBackend): def __init__(self, *args, **kwargs): """Initialize field mappings""" super().__init__(*args, **kwargs) + self.techniques = self._load_mitre_file("techniques") - def create_rule(self, config): - tags = config.get("tags", []) + def find_technique(self, key_ids): + for key_id in set(key_ids): + if not key_id: + continue + for technique in self.techniques: + if key_id == technique.get("technique_id", ""): + yield technique + + def _load_mitre_file(self, mitre_type): + try: + backend_dir = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", "config", "mitre")) + path = os.path.join(backend_dir, "{}.json".format(mitre_type)) + with open(path) as config_file: + config = json.load(config_file) + return config + except (IOError, OSError) as e: + print("Failed to open {} configuration file '%s': %s".format(path, str(e)), file=sys.stderr) + return [] + except json.JSONDecodeError as e: + print("Failed to parse {} configuration file '%s' as valid YAML: %s" % (path, str(e)), file=sys.stderr) + return [] + + def skip_tactics_or_techniques(self, src_technics, src_tactics): + tactics = set() + technics = set() + + local_storage_techniques = {item["technique_id"]: item for item in self.find_technique(src_technics)} + + for key_id in src_technics: + src_tactic = local_storage_techniques.get(key_id, {}).get("tactic") + if not src_tactic: + continue + src_tactic = set(src_tactic) + + for item in src_tactics: + if item in src_tactic: + technics.add(key_id) + tactics.add(item) + + return sorted(tactics), sorted(technics) + + def parse_severity(self, old_severity): + if old_severity.lower() == "critical": + return "high" + return old_severity + + def get_tactics_and_techniques(self, tags): tactics = list() technics = list() + for tag in tags: tag = tag.replace("attack.", "") - if re.match("[tT][0-9]{4}", tag): + if re.match("[t][0-9]{4}", tag, re.IGNORECASE): technics.append(tag.title()) else: if "_" in tag: - tag_list = tag.split("_") - tag_list = [item.title() for item in tag_list] - tactics.append("".join(tag_list)) - else: - tactics.append(tag.title()) + tag = tag.replace("_", " ") + tag = tag.title() + tactics.append(tag) + + return tactics, technics + + def create_rule(self, config): + tags = config.get("tags", []) + + tactics, technics = self.get_tactics_and_techniques(tags) + tactics, technics = self.skip_tactics_or_techniques(technics, tactics) + tactics = list(map(lambda s: s.replace(" ", ""), tactics)) rule = { "displayName": "{} by {}".format(config.get("title"), config.get('author')), "description": "{} {}".format(config.get("description"), "Technique: {}.".format(",".join(technics))), - "severity": config.get("level", "medium"), + "severity": self.parse_severity(config.get("level", "medium")), "enabled": True, "query": config.get("translation"), "queryFrequency": "12H", "queryPeriod": "12H", "triggerOperator": "GreaterThan", - "triggerThreshold": 1, + "triggerThreshold": 0, "suppressionDuration": "12H", - "suppressionEnabled": False, + "suppressionEnabled": True, "tactics": tactics } return json.dumps(rule) @@ -365,3 +435,5 @@ class AzureAPIBackend(AzureLogAnalyticsBackend): configs.update({"translation": translation}) rule = self.create_rule(configs) return rule + else: + raise NotSupportedError("No table could be determined from Sigma rule") diff --git a/tools/sigma/backends/arcsight.py b/tools/sigma/backends/arcsight.py index 2d92d59e..6cd10709 100644 --- a/tools/sigma/backends/arcsight.py +++ b/tools/sigma/backends/arcsight.py @@ -222,7 +222,7 @@ class ArcSightESMBackend(SingleTextQueryBackend): elif isinstance(value, str) and value.endswith("*"): return self.startsWithExpression % (key, self.generateValueNode(self.CleanNode(value))) else: - return self.generateValueNode(value) + return self.mapExpression % (key, self.generateValueNode(value)) elif isinstance(value, list): new_value = list() for item in value: diff --git a/tools/sigma/backends/base.py b/tools/sigma/backends/base.py index 4675b019..1ef7e175 100644 --- a/tools/sigma/backends/base.py +++ b/tools/sigma/backends/base.py @@ -18,7 +18,9 @@ import sys import sigma import yaml +import re +from sigma.backends.exceptions import NotSupportedError from .mixins import RulenameCommentMixin, QuoteCharMixin from sigma.parser.modifiers.base import SigmaTypeModifier @@ -90,6 +92,7 @@ class BaseBackend: options = tuple() # a list of tuples with following elements: option name, default value, help text, target attribute name (option name if None) config_required = True default_config = None + mapExpression = "" def __init__(self, sigmaconfig, backend_options=dict()): """ @@ -130,29 +133,48 @@ class BaseBackend: result = self.generateNode(parsed.parsedSearch) if parsed.parsedAgg: result += self.generateAggregation(parsed.parsedAgg) + #result = self.applyOverrides(result) return result + def applyOverrides(self, query): + try: + if 'overrides' in self.sigmaconfig.config and isinstance(query, str): + for expression in self.sigmaconfig.config['overrides']: + if 'regexes' in expression: + for x in expression['regexes']: + sub = expression['field'] + value = expression['value'] + query = re.sub(x, self.mapExpression % (sub, value), query) + if 'literals' in expression: + for x in expression['literals']: + sub = expression['field'] + value = expression['value'] + query = query.replace(x, self.mapExpression % (sub, value)) + except Exception: + pass + return query + def generateNode(self, node): if type(node) == sigma.parser.condition.ConditionAND: - return self.generateANDNode(node) + return self.applyOverrides(self.generateANDNode(node)) elif type(node) == sigma.parser.condition.ConditionOR: - return self.generateORNode(node) + return self.applyOverrides(self.generateORNode(node)) elif type(node) == sigma.parser.condition.ConditionNOT: - return self.generateNOTNode(node) + return self.applyOverrides(self.generateNOTNode(node)) elif type(node) == sigma.parser.condition.ConditionNULLValue: - return self.generateNULLValueNode(node) + return self.applyOverrides(self.generateNULLValueNode(node)) elif type(node) == sigma.parser.condition.ConditionNotNULLValue: - return self.generateNotNULLValueNode(node) + return self.applyOverrides(self.generateNotNULLValueNode(node)) elif type(node) == sigma.parser.condition.NodeSubexpression: - return self.generateSubexpressionNode(node) + return self.applyOverrides(self.generateSubexpressionNode(node)) elif type(node) == tuple: - return self.generateMapItemNode(node) + return self.applyOverrides(self.generateMapItemNode(node)) elif type(node) in (str, int): - return self.generateValueNode(node) + return self.applyOverrides(self.generateValueNode(node)) elif type(node) == list: - return self.generateListNode(node) + return self.applyOverrides(self.generateListNode(node)) elif isinstance(node, SigmaTypeModifier): - return self.generateTypedValueNode(node) + return self.applyOverrides(self.generateTypedValueNode(node)) else: raise TypeError("Node type %s was not expected in Sigma parse tree" % (str(type(node)))) diff --git a/tools/sigma/backends/carbonblack.py b/tools/sigma/backends/carbonblack.py index ea1e7f9a..a06af826 100644 --- a/tools/sigma/backends/carbonblack.py +++ b/tools/sigma/backends/carbonblack.py @@ -2,7 +2,7 @@ import re import requests import json import os -from ..config.eventdict import event +from sigma.config.eventdict import event from fnmatch import fnmatch from sigma.backends.base import SingleTextQueryBackend @@ -83,7 +83,7 @@ class CarbonBlackQueryBackend(CarbonBlackWildcardHandlingMixin, SingleTextQueryB if val.startswith("*"): val = val.replace("*", "",1) if val.startswith("\\"): - val = val.replace("\\", "", 1) + val = val.replace("\\", "", 1) if val.startswith("*\\"): val = val.replace("*\\", "*") if val.startswith("*/"): @@ -108,7 +108,7 @@ class CarbonBlackQueryBackend(CarbonBlackWildcardHandlingMixin, SingleTextQueryB elif type(new_value) is list: for index, vl in enumerate(new_value): new_value[index] = self.cleanIPRange(vl) - + return new_value def generateValueNode(self, node): @@ -131,7 +131,6 @@ class CarbonBlackQueryBackend(CarbonBlackWildcardHandlingMixin, SingleTextQueryB else: transformed_fieldname = self.fieldNameMapping(fieldname, value) if(transformed_fieldname == "ipaddr"): - print("OK") value = self.cleanIPRange(value) if self.mapListsSpecialHandling == False and type(value) in (str, int, list) or self.mapListsSpecialHandling == True and type(value) in (str, int): #return self.mapExpression % (transformed_fieldname, self.generateNode(value)) diff --git a/tools/sigma/backends/discovery.py b/tools/sigma/backends/discovery.py index fdb2347f..399ce79e 100644 --- a/tools/sigma/backends/discovery.py +++ b/tools/sigma/backends/discovery.py @@ -25,7 +25,7 @@ from sigma.tools import getAllSubclasses, getClassDict def getBackendList(): """Return list of backend classes""" path = os.path.dirname(__file__) - return frozenset(getAllSubclasses(path, "backends", BaseBackend)) + return getAllSubclasses(path, "backends", BaseBackend) def getBackendDict(): return getClassDict(getBackendList()) diff --git a/tools/sigma/backends/elasticsearch.py b/tools/sigma/backends/elasticsearch.py index 397ff943..88cdd9c6 100644 --- a/tools/sigma/backends/elasticsearch.py +++ b/tools/sigma/backends/elasticsearch.py @@ -23,12 +23,39 @@ from random import randrange import sigma import yaml -from sigma.parser.modifiers.type import SigmaRegularExpressionModifier +from sigma.parser.modifiers.type import SigmaRegularExpressionModifier, SigmaTypeModifier from sigma.parser.condition import ConditionOR, ConditionAND, NodeSubexpression + +from sigma.config.mapping import ConditionalFieldMapping from .base import BaseBackend, SingleTextQueryBackend from .mixins import RulenameCommentMixin, MultiRuleOutputMixin from .exceptions import NotSupportedError + +class DeepFieldMappingMixin(object): + + def fieldNameMapping(self, fieldname, value): + if isinstance(fieldname, str): + get_config = self.sigmaconfig.fieldmappings.get(fieldname) + if not get_config and '|' in fieldname: + fieldname = fieldname.split('|', 1)[0] + get_config = self.sigmaconfig.fieldmappings.get(fieldname) + if isinstance(get_config, ConditionalFieldMapping): + condition = self.sigmaconfig.fieldmappings.get(fieldname).conditions + for key, item in self.logsource.items(): + if condition.get(key) and condition.get(key, {}).get(item): + new_fieldname = condition.get(key, {}).get(item) + if any(new_fieldname): + return super().fieldNameMapping(new_fieldname[0], value) + return super().fieldNameMapping(fieldname, value) + + + def generate(self, sigmaparser): + self.logsource = sigmaparser.parsedyaml.get("logsource", {}) + return super().generate(sigmaparser) + + + class ElasticsearchWildcardHandlingMixin(object): """ Determine field mapping to keyword subfields depending on existence of wildcards in search values. Further, @@ -86,6 +113,31 @@ class ElasticsearchWildcardHandlingMixin(object): else: return False + def generateMapItemNode(self, node): + fieldname, value = node + if fieldname.lower().find("hash") != -1: + if isinstance(value, list): + res = [] + for item in value: + try: + res.extend([item.lower(), item.upper()]) + except AttributeError: # not a string (something that doesn't support upper/lower casing) + res.append(item) + value = res + elif isinstance(value, str): + value = [value.upper(), value.lower()] + transformed_fieldname = self.fieldNameMapping(fieldname, value) + if self.mapListsSpecialHandling == False and type(value) in (str, int, list) or self.mapListsSpecialHandling == True and type(value) in (str, int): + return self.mapExpression % (transformed_fieldname, self.generateNode(value)) + elif type(value) == list: + return self.generateMapItemListNode(transformed_fieldname, value) + elif isinstance(value, SigmaTypeModifier): + return self.generateMapItemTypedNode(transformed_fieldname, value) + elif value is None: + return self.nullExpression % (transformed_fieldname, ) + else: + raise TypeError("Backend does not support map values of type " + str(type(value))) + def fieldNameMapping(self, fieldname, value, *agg_option): """ Decide whether to use a keyword field or analyzed field. Using options on fields to make into keywords OR not and the field naming of keyword. @@ -162,6 +214,8 @@ class ElasticsearchWildcardHandlingMixin(object): Adds the beginning and ending '/' to make regex query if still determined that it should be a regex """ if value and not value == 'null' and not re.match(r'^/.*/$', value) and (re.search('[a-zA-Z]', value) and not re.match(self.uuid_regex, value) or self.containsWildcard(value)): # re.search for alpha is fastest: + # Turn single ending '\\' into non escaped (ie: '\\*') + #value = re.sub( r"((?\\*", value ) # Make upper/lower value = re.sub( r"[A-Za-z]", lambda x: "[" + x.group( 0 ).upper() + x.group( 0 ).lower() + "]", value ) # Turn `*` into wildcard, only if odd number of '\'(because this would mean already escaped) @@ -180,7 +234,7 @@ class ElasticsearchWildcardHandlingMixin(object): return { 'is_regex': False, 'value': value } -class ElasticsearchQuerystringBackend(ElasticsearchWildcardHandlingMixin, SingleTextQueryBackend): +class ElasticsearchQuerystringBackend(DeepFieldMappingMixin, ElasticsearchWildcardHandlingMixin, SingleTextQueryBackend): """Converts Sigma rule into Elasticsearch query string. Only searches, no aggregations.""" identifier = "es-qs" active = True @@ -244,7 +298,7 @@ class ElasticsearchQuerystringBackend(ElasticsearchWildcardHandlingMixin, Single else: return super().generateSubexpressionNode(node) -class ElasticsearchDSLBackend(RulenameCommentMixin, ElasticsearchWildcardHandlingMixin, BaseBackend): +class ElasticsearchDSLBackend(DeepFieldMappingMixin, RulenameCommentMixin, ElasticsearchWildcardHandlingMixin, BaseBackend): """ElasticSearch DSL backend""" identifier = 'es-dsl' active = True @@ -579,7 +633,8 @@ class KibanaBackend(ElasticsearchQuerystringBackend, MultiRuleOutputMixin): if self.output_type == "import": # output format that can be imported via Kibana UI for item in self.kibanaconf: # JSONize kibanaSavedObjectMeta.searchSourceJSON item['_source']['kibanaSavedObjectMeta']['searchSourceJSON'] = json.dumps(item['_source']['kibanaSavedObjectMeta']['searchSourceJSON']) - return json.dumps(self.kibanaconf, indent=2) + if self.kibanaconf: + return json.dumps(self.kibanaconf, indent=2) elif self.output_type == "curl": for item in self.indexsearch: return item @@ -908,7 +963,7 @@ class XPackWatcherBackend(ElasticsearchQuerystringBackend, MultiRuleOutputMixin) raise NotImplementedError("Output type '%s' not supported" % self.output_type) return result -class ElastalertBackend(MultiRuleOutputMixin): +class ElastalertBackend(DeepFieldMappingMixin, MultiRuleOutputMixin): """Elastalert backend""" active = True supported_alert_methods = {'email', 'http_post'} @@ -1202,12 +1257,14 @@ class ElasticSearchRuleBackend(ElasticsearchQuerystringBackend): tags = configs.get("tags", []) tactics_list = list() technics_list = list() + new_tags = list() for tag in tags: tag = tag.replace("attack.", "") if re.match("[t][0-9]{4}", tag, re.IGNORECASE): tech = self.find_technique(tag.title()) if tech: + new_tags.append(tag.title()) technics_list.append(tech) else: if "_" in tag: @@ -1215,22 +1272,29 @@ class ElasticSearchRuleBackend(ElasticsearchQuerystringBackend): tag_list = [item.title() for item in tag_list] tact = self.find_tactics(key_name=" ".join(tag_list)) if tact: + new_tags.append(" ".join(tag_list)) tactics_list.append(tact) elif re.match("[ta][0-9]{4}", tag, re.IGNORECASE): tact = self.find_tactics(key_id=tag.upper()) if tact: + new_tags.append(tag.upper()) tactics_list.append(tact) else: tact = self.find_tactics(key_name=tag.title()) if tact: + new_tags.append(tag.title()) tactics_list.append(tact) threat = self.create_threat_description(tactics_list=tactics_list, techniques_list=technics_list) - rule_id = configs.get("title", "").lower().replace(" ", "_") + rule_name = configs.get("title", "").lower() + rule_id = re.sub(re.compile('[()*+!,\[\].\s"]'), "_", rule_name) risk_score = self.map_risk_score(configs.get("level", "medium")) + references = configs.get("reference") + if references is None: + references = configs.get("references") rule = { "description": configs.get("description", ""), "enabled": True, - "false_positives": configs.get('falsepositives'), + "false_positives": configs.get('falsepositives', "Unkown"), "filters": [], "from": "now-360s", "immutable": False, @@ -1243,15 +1307,16 @@ class ElasticSearchRuleBackend(ElasticsearchQuerystringBackend): "risk_score": risk_score, "name": configs.get("title", ""), "query":configs.get("translation"), - "references": configs.get("references"), "meta": { "from": "1m" }, "severity": configs.get("level", "medium"), - "tags": tags, + "tags": new_tags, "to": "now", "type": "query", "threat": threat, "version": 1 } + if references: + rule.update({"references": references}) return json.dumps(rule) diff --git a/tools/sigma/backends/humio.py b/tools/sigma/backends/humio.py new file mode 100644 index 00000000..21577e15 --- /dev/null +++ b/tools/sigma/backends/humio.py @@ -0,0 +1,160 @@ +# Output backends for sigmac +# Copyright 2016-2018 Thomas Patzke, Florian Roth, Roey + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +import re + +from sigma.parser.modifiers.type import SigmaRegularExpressionModifier + +from sigma.parser.condition import SigmaAggregationParser +from .base import SingleTextQueryBackend +from .mixins import MultiRuleOutputMixin + +class HumioBackend(SingleTextQueryBackend): + """Converts Sigma rule into Humio query.""" + identifier = "humio" + active = True + + reEscape = re.compile('("|(?. - -import re -import yaml -from collections import namedtuple -from .base import BaseBackend -from sigma.parser.modifiers.base import SigmaTypeModifier -from sigma.parser.modifiers.type import SigmaRegularExpressionModifier - -# A few helper functions for cases where field mapping cannot be done -# as easily one by one, or can be done more efficiently. -def _windowsEventLogFieldName(fieldName): - if 'EventID' == fieldName: - return 'Event/System/EventID' - return 'Event/EventData/%s' % (fieldName,) - -def _mapProcessCreationOperations(node): - # Here we fix some common pitfalls found in rules - # in a consistent fashion (already processed to D&R rule). - - # First fixup is looking for a specific path prefix - # based on a specific drive letter. There are many cases - # where the driver letter can change or where the early - # boot process refers to it as "\Device\HarddiskVolume1\". - if ("starts with" == node["op"] and - "event/FILE_PATH" == node["path"] and - node["value"].lower().startswith("c:\\")): - node["op"] = "matches" - node["re"] = "^(?:(?:.:)|(?:\\\\Device\\\\HarddiskVolume.))\\\\%s" % (re.escape(node["value"][3:]),) - del(node["value"]) - - return node - -# We support many different log sources so we keep different mapping depending -# on the log source and category. -# The mapping key is product/category/service. -# The mapping value is tuple like: -# - top-level parameters -# - pre-condition is a D&R rule node filtering relevant events. -# - field mappings is a dict with a mapping or a callable to convert the field name. -# Individual mapping values can also be callabled(fieldname, value) returning a new fieldname and value. -# - isAllStringValues is a bool indicating whether all values should be converted to string. -# - keywordField is the field name to alias for keywords if supported or None if not. -# - postOpMapper is a callback that can modify an operation once it has been generated. -SigmaLCConfig = namedtuple('SigmaLCConfig', [ - 'topLevelParams', - 'preConditions', - 'fieldMappings', - 'isAllStringValues', - 'keywordField', - 'postOpMapper', -]) -_allFieldMappings = { - "windows/process_creation/": SigmaLCConfig( - topLevelParams = { - "events": [ - "NEW_PROCESS", - "EXISTING_PROCESS", - ] - }, - preConditions = { - "op": "is windows", - }, - fieldMappings = { - "CommandLine": "event/COMMAND_LINE", - "Image": "event/FILE_PATH", - "ParentImage": "event/PARENT/FILE_PATH", - "ParentCommandLine": "event/PARENT/COMMAND_LINE", - "User": "event/USER_NAME", - "OriginalFileName": "event/ORIGINAL_FILE_NAME", - # Custom field names coming from somewhere unknown. - "NewProcessName": "event/FILE_PATH", - "ProcessCommandLine": "event/COMMAND_LINE", - # Another one-off command line. - "Command": "event/COMMAND_LINE", - }, - isAllStringValues = False, - keywordField = "event/COMMAND_LINE", - postOpMapper = _mapProcessCreationOperations - ), - "windows//": SigmaLCConfig( - topLevelParams = { - "target": "log", - "log type": "wel", - }, - preConditions = None, - fieldMappings = _windowsEventLogFieldName, - isAllStringValues = True, - keywordField = None, - postOpMapper = None - ), - "windows_defender//": SigmaLCConfig( - topLevelParams = { - "target": "log", - "log type": "wel", - }, - preConditions = None, - fieldMappings = _windowsEventLogFieldName, - isAllStringValues = True, - keywordField = None, - postOpMapper = None - ), - "dns//": SigmaLCConfig( - topLevelParams = { - "event": "DNS_REQUEST", - }, - preConditions = None, - fieldMappings = { - "query": "event/DOMAIN_NAME", - }, - isAllStringValues = False, - keywordField = None, - postOpMapper = None - ), - "linux//": SigmaLCConfig( - topLevelParams = { - "events": [ - "NEW_PROCESS", - "EXISTING_PROCESS", - ] - }, - preConditions = { - "op": "is linux", - }, - fieldMappings = { - "exe": "event/FILE_PATH", - "type": None, - }, - isAllStringValues = False, - keywordField = 'event/COMMAND_LINE', - postOpMapper = None - ), - "unix//": SigmaLCConfig( - topLevelParams = { - "events": [ - "NEW_PROCESS", - "EXISTING_PROCESS", - ] - }, - preConditions = { - "op": "is linux", - }, - fieldMappings = { - "exe": "event/FILE_PATH", - "type": None, - }, - isAllStringValues = False, - keywordField = 'event/COMMAND_LINE', - postOpMapper = None - ), - "netflow//": SigmaLCConfig( - topLevelParams = { - "event": "NETWORK_CONNECTIONS", - }, - preConditions = None, - fieldMappings = { - "destination.port": "event/NETWORK_ACTIVITY/DESTINATION/PORT", - "source.port": "event/NETWORK_ACTIVITY/SOURCE/PORT", - }, - isAllStringValues = False, - keywordField = None, - postOpMapper = None - ), - "/proxy/": SigmaLCConfig( - topLevelParams = { - "event": "HTTP_REQUEST", - }, - preConditions = None, - fieldMappings = { - "c-uri|contains": "event/URL", - "c-uri": "event/URL", - "URL": "event/URL", - "cs-uri-query": "event/URL", - "cs-uri-stem": "event/URL", - }, - isAllStringValues = False, - keywordField = None, - postOpMapper = None - ), -} - -class LimaCharlieBackend(BaseBackend): - """Converts Sigma rule into LimaCharlie D&R rules. Contributed by LimaCharlie. https://limacharlie.io""" - identifier = "limacharlie" - active = True - config_required = False - default_config = ["limacharlie"] - - def generate(self, sigmaparser): - # Take the log source information and figure out which set of mappings to use. - ruleConfig = sigmaparser.parsedyaml - ls_rule = ruleConfig['logsource'] - try: - category = ls_rule['category'] - except KeyError: - category = "" - try: - product = ls_rule['product'] - except KeyError: - product = "" - # try: - # service = ls_rule['service'] - # except KeyError: - # service = "" - - # If there is a timeframe component, we do not currently - # support it for now. - if ruleConfig.get( 'detection', {} ).get( 'timeframe', None ) is not None: - raise NotImplementedError("Timeframes are not supported by backend.") - - # Don't use service for now, most Windows Event Logs - # uses a different service with no category, since we - # treat all Windows Event Logs together we can ignore - # the service. - service = "" - - # See if we have a definition for the source combination. - mappingKey = "%s/%s/%s" % (product, category, service) - topFilter, preCond, mappings, isAllStringValues, keywordField, postOpMapper = _allFieldMappings.get(mappingKey, tuple([None, None, None, None, None, None])) - if mappings is None: - raise NotImplementedError("Log source %s/%s/%s not supported by backend." % (product, category, service)) - - # Field name conversions. - self._fieldMappingInEffect = mappings - - # LC event type pre-selector for the type of data. - self._preCondition = preCond - - # Are all the values treated as strings? - self._isAllStringValues = isAllStringValues - - # Are we supporting keywords full text search? - self._keywordField = keywordField - - # Call to fixup all operations after the fact. - self._postOpMapper = postOpMapper - - # Call the original generation code. - detectComponent = super().generate(sigmaparser) - - # We expect a string (yaml) as output, so if - # we get anything else we assume it's a core - # library value and just return it as-is. - if not isinstance( detectComponent, str): - return detectComponent - - # This redundant to deserialize it right after - # generating the yaml, but we try to use the parent - # official class code as much as possible for future - # compatibility. - detectComponent = yaml.safe_load(detectComponent) - - # Check that we got a proper node and not just a string - # which we don't really know what to do with. - if not isinstance(detectComponent, dict): - raise NotImplementedError("Selection combination not supported.") - - # Apply top level filter. - detectComponent.update(topFilter) - - # Now prepare the Response component. - respondComponents = [{ - "action": "report", - "name": ruleConfig["title"], - }] - - # Add a lot of the metadata available to the report. - if ruleConfig.get("tags", None) is not None: - respondComponents[0].setdefault("metadata", {})["tags"] = ruleConfig["tags"] - - if ruleConfig.get("description", None) is not None: - respondComponents[0].setdefault("metadata", {})["description"] = ruleConfig["description"] - - if ruleConfig.get("references", None) is not None: - respondComponents[0].setdefault("metadata", {})["references"] = ruleConfig["references"] - - if ruleConfig.get("level", None) is not None: - respondComponents[0].setdefault("metadata", {})["level"] = ruleConfig["level"] - - if ruleConfig.get("author", None) is not None: - respondComponents[0].setdefault("metadata", {})["author"] = ruleConfig["author"] - - if ruleConfig.get("falsepositives", None) is not None: - respondComponents[0].setdefault("metadata", {})["falsepositives"] = ruleConfig["falsepositives"] - - # Assemble it all as a single, complete D&R rule. - return yaml.safe_dump({ - "detect": detectComponent, - "respond": respondComponents, - }, default_flow_style = False) - - def generateQuery(self, parsed): - # We override the generateQuery function because - # we generate proper JSON structures internally - # and only convert to string (yaml) once the - # whole thing is assembled. - result = self.generateNode(parsed.parsedSearch) - - if self._preCondition is not None: - result = { - "op": "and", - "rules": [ - self._preCondition, - result, - ] - } - if self._postOpMapper is not None: - result = self._postOpMapper(result) - return yaml.safe_dump(result) - - def generateANDNode(self, node): - generated = [ self.generateNode(val) for val in node ] - filtered = [ g for g in generated if g is not None ] - if not filtered: - return None - - # Map any possible keywords. - filtered = self._mapKeywordVals(filtered) - - if 1 == len(filtered): - if self._postOpMapper is not None: - filtered[0] = self._postOpMapper(filtered[0]) - return filtered[0] - result = { - "op": "and", - "rules": filtered, - } - if self._postOpMapper is not None: - result = self._postOpMapper(result) - return result - - def generateORNode(self, node): - generated = [self.generateNode(val) for val in node] - filtered = [g for g in generated if g is not None] - if not filtered: - return None - - # Map any possible keywords. - filtered = self._mapKeywordVals(filtered) - - if 1 == len(filtered): - if self._postOpMapper is not None: - filtered[0] = self._postOpMapper(filtered[0]) - return filtered[0] - result = { - "op": "or", - "rules": filtered, - } - if self._postOpMapper is not None: - result = self._postOpMapper(result) - return result - - def generateNOTNode(self, node): - generated = self.generateNode(node.item) - if generated is None: - return None - if not isinstance(generated, dict): - raise NotImplementedError("Not operator not available on non-dict nodes.") - generated["not"] = not generated.get("not", False) - return generated - - def generateSubexpressionNode(self, node): - return self.generateNode(node.items) - - def generateListNode(self, node): - return [self.generateNode(value) for value in node] - - def generateMapItemNode(self, node): - fieldname, value = node - - fieldNameAndValCallback = None - - # The mapping can be a dictionary of mapping or a callable - # to get the correct value. - if callable(self._fieldMappingInEffect): - fieldname = self._fieldMappingInEffect(fieldname) - else: - try: - # The mapping can also be a callable that will - # return a mapped key AND value. - if callable(self._fieldMappingInEffect[fieldname]): - fieldNameAndValCallback = self._fieldMappingInEffect[fieldname] - else: - fieldname = self._fieldMappingInEffect[fieldname] - except: - raise NotImplementedError("Field name %s not supported by backend." % (fieldname,)) - - # If fieldname returned is None, it's a special case where we - # ignore the node. - if fieldname is None: - return None - - if isinstance(value, (int, str)): - if fieldNameAndValCallback is not None: - fieldname, value = fieldNameAndValCallback(fieldname, value) - op, newVal = self._valuePatternToLcOp(value) - newOp = { - "op": op, - "path": fieldname, - "case sensitive": False, - } - if op == "matches": - newOp["re"] = newVal - else: - newOp["value"] = newVal - if self._postOpMapper is not None: - newOp = self._postOpMapper(newOp) - return newOp - elif isinstance(value, list): - subOps = [] - for v in value: - if fieldNameAndValCallback is not None: - fieldname, v = fieldNameAndValCallback(fieldname, v) - op, newVal = self._valuePatternToLcOp(v) - newOp = { - "op": op, - "path": fieldname, - "case sensitive": False, - } - if op == "matches": - newOp["re"] = newVal - else: - newOp["value"] = newVal - if self._postOpMapper is not None: - newOp = self._postOpMapper(newOp) - subOps.append(newOp) - if 1 == len(subOps): - return subOps[0] - return { - "op": "or", - "rules": subOps - } - elif isinstance(value, SigmaTypeModifier): - if isinstance(value, SigmaRegularExpressionModifier): - if fieldNameAndValCallback is not None: - fieldname, value = fieldNameAndValCallback(fieldname, value) - result = { - "op": "matches", - "path": fieldname, - "re": re.compile(value), - } - if self._postOpMapper is not None: - result = self._postOpMapper(result) - return result - else: - raise TypeError("Backend does not support TypeModifier: %s" % (str(type(value)))) - elif value is None: - if fieldNameAndValCallback is not None: - fieldname, value = fieldNameAndValCallback(fieldname, value) - result = { - "op": "exists", - "not": True, - "path": fieldname, - } - if self._postOpMapper is not None: - result = self._postOpMapper(result) - return result - else: - raise TypeError("Backend does not support map values of type " + str(type(value))) - - def generateValueNode(self, node): - return node - - def _valuePatternToLcOp(self, val): - # Here we convert the string values supported by Sigma that - # can include wildcards into either proper values (string or int) - # or into altered values to be functionally equivalent using - # a few different LC D&R rule operators. - - # No point evaluating non-strings. - if not isinstance(val, str): - return ("is", str(val) if self._isAllStringValues else val) - - # Is there any wildcard in this string? If not, we can short circuit. - if "*" not in val and "?" not in val: - return ("is", val) - - # Now we do a small optimization for the shortcut operators - # available in LC. We try to see if the wildcards are around - # the main value, but NOT within. If that's the case we can - # use the "starts with", "ends with" or "contains" operators. - isStartsWithWildcard = False - isEndsWithWildcard = False - tmpVal = val - if tmpVal.startswith("*"): - isStartsWithWildcard = True - tmpVal = tmpVal[1:] - if tmpVal.endswith("*") and not (tmpVal.endswith("\\*") and not tmpVal.endswith("\\\\*")): - isEndsWithWildcard = True - if tmpVal.endswith("\\\\*"): - # An extra \ had to be there so it didn't escapte the - # *, but since we plan on removing the *, we can also - # remove one \. - tmpVal = tmpVal[:-2] - else: - tmpVal = tmpVal[:-1] - - # Check to see if there are any other wildcards. If there are - # we cannot use our shortcuts. - if "*" not in tmpVal and "?" not in tmpVal: - if isStartsWithWildcard and isEndsWithWildcard: - return ("contains", tmpVal) - - if isStartsWithWildcard: - return ("ends with", tmpVal) - - if isEndsWithWildcard: - return ("starts with", tmpVal) - - # This is messy, but it is accurate in generating a RE based on - # the simplified wildcard system, while also supporting the - # escaping of those wildcards. - segments = [] - tmpVal = val - while True: - nEscapes = 0 - for i in range(len(tmpVal)): - # We keep a running count of backslash escape - # characters we see so that if we meet a wildcard - # we can tell whether the wildcard is escaped - # (with odd number of escapes) or if it's just a - # backslash literal before a wildcard (even number). - if "\\" == tmpVal[i]: - nEscapes += 1 - continue - - if "*" == tmpVal[i]: - if 0 == nEscapes: - segments.append(re.escape(tmpVal[:i])) - segments.append(".*") - elif nEscapes % 2 == 0: - segments.append(re.escape(tmpVal[:i - nEscapes])) - segments.append(tmpVal[i - nEscapes:i]) - segments.append(".*") - else: - segments.append(re.escape(tmpVal[:i - nEscapes])) - segments.append(tmpVal[i - nEscapes:i + 1]) - tmpVal = tmpVal[i + 1:] - break - - if "?" == tmpVal[i]: - if 0 == nEscapes: - segments.append(re.escape(tmpVal[:i])) - segments.append(".") - elif nEscapes % 2 == 0: - segments.append(re.escape(tmpVal[:i - nEscapes])) - segments.append(tmpVal[i - nEscapes:i]) - segments.append(".") - else: - segments.append(re.escape(tmpVal[:i - nEscapes])) - segments.append(tmpVal[i - nEscapes:i + 1]) - tmpVal = tmpVal[i + 1:] - break - - nEscapes = 0 - else: - segments.append(re.escape(tmpVal)) - break - - val = ''.join(segments) - - return ("matches", val) - - def _mapKeywordVals(self, values): - # This function ensures that the list of values passed - # are proper D&R operations, if they are strings it indicates - # they were requested as keyword matches. We only support - # keyword matches when specified in the config. We generally just - # map them to the most common field in LC that makes sense. - mapped = [] - - for val in values: - # Non-keywords are just passed through. - if not isinstance(val, str): - mapped.append(val) - continue - - if self._keywordField is None: - raise NotImplementedError("Full-text keyboard searches not supported.") - - # This seems to be indicative only of "keywords" which are mostly - # representative of full-text searches. We don't suport that but - # in some data sources we can alias them to an actual field. - op, newVal = self._valuePatternToLcOp(val) - newOp = { - "op": op, - "path": self._keywordField, - } - if op == "matches": - newOp["re"] = newVal - else: - newOp["value"] = newVal - mapped.append(newOp) - - return mapped +# LimaCharlie backend for sigmac created by LimaCharlie.io +# Copyright 2019 Refraction Point, Inc + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +import re +import yaml +from collections import namedtuple +from .base import BaseBackend +from sigma.parser.modifiers.base import SigmaTypeModifier +from sigma.parser.modifiers.type import SigmaRegularExpressionModifier + +# A few helper functions for cases where field mapping cannot be done +# as easily one by one, or can be done more efficiently. +def _windowsEventLogFieldName(fieldName): + if 'EventID' == fieldName: + return 'Event/System/EventID' + return 'Event/EventData/%s' % (fieldName,) + +def _mapProcessCreationOperations(node): + # Here we fix some common pitfalls found in rules + # in a consistent fashion (already processed to D&R rule). + + # First fixup is looking for a specific path prefix + # based on a specific drive letter. There are many cases + # where the driver letter can change or where the early + # boot process refers to it as "\Device\HarddiskVolume1\". + if ("starts with" == node["op"] and + "event/FILE_PATH" == node["path"] and + node["value"].lower().startswith("c:\\")): + node["op"] = "matches" + node["re"] = "^(?:(?:.:)|(?:\\\\Device\\\\HarddiskVolume.))\\\\%s" % (re.escape(node["value"][3:]),) + del(node["value"]) + + return node + +# We support many different log sources so we keep different mapping depending +# on the log source and category. +# The mapping key is product/category/service. +# The mapping value is tuple like: +# - top-level parameters +# - pre-condition is a D&R rule node filtering relevant events. +# - field mappings is a dict with a mapping or a callable to convert the field name. +# Individual mapping values can also be callabled(fieldname, value) returning a new fieldname and value. +# - isAllStringValues is a bool indicating whether all values should be converted to string. +# - keywordField is the field name to alias for keywords if supported or None if not. +# - postOpMapper is a callback that can modify an operation once it has been generated. +SigmaLCConfig = namedtuple('SigmaLCConfig', [ + 'topLevelParams', + 'preConditions', + 'fieldMappings', + 'isAllStringValues', + 'keywordField', + 'postOpMapper', +]) +_allFieldMappings = { + "windows/process_creation/": SigmaLCConfig( + topLevelParams = { + "events": [ + "NEW_PROCESS", + "EXISTING_PROCESS", + ] + }, + preConditions = { + "op": "is windows", + }, + fieldMappings = { + "CommandLine": "event/COMMAND_LINE", + "Image": "event/FILE_PATH", + "ParentImage": "event/PARENT/FILE_PATH", + "ParentCommandLine": "event/PARENT/COMMAND_LINE", + "User": "event/USER_NAME", + "OriginalFileName": "event/ORIGINAL_FILE_NAME", + # Custom field names coming from somewhere unknown. + "NewProcessName": "event/FILE_PATH", + "ProcessCommandLine": "event/COMMAND_LINE", + # Another one-off command line. + "Command": "event/COMMAND_LINE", + }, + isAllStringValues = False, + keywordField = "event/COMMAND_LINE", + postOpMapper = _mapProcessCreationOperations + ), + "windows//": SigmaLCConfig( + topLevelParams = { + "target": "log", + "log type": "wel", + }, + preConditions = None, + fieldMappings = _windowsEventLogFieldName, + isAllStringValues = True, + keywordField = None, + postOpMapper = None + ), + "windows_defender//": SigmaLCConfig( + topLevelParams = { + "target": "log", + "log type": "wel", + }, + preConditions = None, + fieldMappings = _windowsEventLogFieldName, + isAllStringValues = True, + keywordField = None, + postOpMapper = None + ), + "dns//": SigmaLCConfig( + topLevelParams = { + "event": "DNS_REQUEST", + }, + preConditions = None, + fieldMappings = { + "query": "event/DOMAIN_NAME", + }, + isAllStringValues = False, + keywordField = None, + postOpMapper = None + ), + "linux//": SigmaLCConfig( + topLevelParams = { + "events": [ + "NEW_PROCESS", + "EXISTING_PROCESS", + ] + }, + preConditions = { + "op": "is linux", + }, + fieldMappings = { + "exe": "event/FILE_PATH", + "type": None, + }, + isAllStringValues = False, + keywordField = 'event/COMMAND_LINE', + postOpMapper = None + ), + "unix//": SigmaLCConfig( + topLevelParams = { + "events": [ + "NEW_PROCESS", + "EXISTING_PROCESS", + ] + }, + preConditions = { + "op": "is linux", + }, + fieldMappings = { + "exe": "event/FILE_PATH", + "type": None, + }, + isAllStringValues = False, + keywordField = 'event/COMMAND_LINE', + postOpMapper = None + ), + "netflow//": SigmaLCConfig( + topLevelParams = { + "event": "NETWORK_CONNECTIONS", + }, + preConditions = None, + fieldMappings = { + "destination.port": "event/NETWORK_ACTIVITY/DESTINATION/PORT", + "source.port": "event/NETWORK_ACTIVITY/SOURCE/PORT", + }, + isAllStringValues = False, + keywordField = None, + postOpMapper = None + ), + "/proxy/": SigmaLCConfig( + topLevelParams = { + "event": "HTTP_REQUEST", + }, + preConditions = None, + fieldMappings = { + "c-uri|contains": "event/URL", + "c-uri": "event/URL", + "URL": "event/URL", + "cs-uri-query": "event/URL", + "cs-uri-stem": "event/URL", + }, + isAllStringValues = False, + keywordField = None, + postOpMapper = None + ), +} + +class LimaCharlieBackend(BaseBackend): + """Converts Sigma rule into LimaCharlie D&R rules. Contributed by LimaCharlie. https://limacharlie.io""" + identifier = "limacharlie" + active = True + config_required = False + default_config = ["limacharlie"] + + def generate(self, sigmaparser): + # Take the log source information and figure out which set of mappings to use. + ruleConfig = sigmaparser.parsedyaml + ls_rule = ruleConfig['logsource'] + try: + category = ls_rule['category'] + except KeyError: + category = "" + try: + product = ls_rule['product'] + except KeyError: + product = "" + # try: + # service = ls_rule['service'] + # except KeyError: + # service = "" + + # If there is a timeframe component, we do not currently + # support it for now. + if ruleConfig.get( 'detection', {} ).get( 'timeframe', None ) is not None: + raise NotImplementedError("Timeframes are not supported by backend.") + + # Don't use service for now, most Windows Event Logs + # uses a different service with no category, since we + # treat all Windows Event Logs together we can ignore + # the service. + service = "" + + # See if we have a definition for the source combination. + mappingKey = "%s/%s/%s" % (product, category, service) + topFilter, preCond, mappings, isAllStringValues, keywordField, postOpMapper = _allFieldMappings.get(mappingKey, tuple([None, None, None, None, None, None])) + if mappings is None: + raise NotImplementedError("Log source %s/%s/%s not supported by backend." % (product, category, service)) + + # Field name conversions. + self._fieldMappingInEffect = mappings + + # LC event type pre-selector for the type of data. + self._preCondition = preCond + + # Are all the values treated as strings? + self._isAllStringValues = isAllStringValues + + # Are we supporting keywords full text search? + self._keywordField = keywordField + + # Call to fixup all operations after the fact. + self._postOpMapper = postOpMapper + + # Call the original generation code. + detectComponent = super().generate(sigmaparser) + + # We expect a string (yaml) as output, so if + # we get anything else we assume it's a core + # library value and just return it as-is. + if not isinstance( detectComponent, str): + return detectComponent + + # This redundant to deserialize it right after + # generating the yaml, but we try to use the parent + # official class code as much as possible for future + # compatibility. + detectComponent = yaml.safe_load(detectComponent) + + # Check that we got a proper node and not just a string + # which we don't really know what to do with. + if not isinstance(detectComponent, dict): + raise NotImplementedError("Selection combination not supported.") + + # Apply top level filter. + detectComponent.update(topFilter) + + # Now prepare the Response component. + respondComponents = [{ + "action": "report", + "name": ruleConfig["title"], + }] + + # Add a lot of the metadata available to the report. + if ruleConfig.get("tags", None) is not None: + respondComponents[0].setdefault("metadata", {})["tags"] = ruleConfig["tags"] + + if ruleConfig.get("description", None) is not None: + respondComponents[0].setdefault("metadata", {})["description"] = ruleConfig["description"] + + if ruleConfig.get("references", None) is not None: + respondComponents[0].setdefault("metadata", {})["references"] = ruleConfig["references"] + + if ruleConfig.get("level", None) is not None: + respondComponents[0].setdefault("metadata", {})["level"] = ruleConfig["level"] + + if ruleConfig.get("author", None) is not None: + respondComponents[0].setdefault("metadata", {})["author"] = ruleConfig["author"] + + if ruleConfig.get("falsepositives", None) is not None: + respondComponents[0].setdefault("metadata", {})["falsepositives"] = ruleConfig["falsepositives"] + + # Assemble it all as a single, complete D&R rule. + return yaml.safe_dump({ + "detect": detectComponent, + "respond": respondComponents, + }, default_flow_style = False) + + def generateQuery(self, parsed): + # We override the generateQuery function because + # we generate proper JSON structures internally + # and only convert to string (yaml) once the + # whole thing is assembled. + result = self.generateNode(parsed.parsedSearch) + + if self._preCondition is not None: + result = { + "op": "and", + "rules": [ + self._preCondition, + result, + ] + } + if self._postOpMapper is not None: + result = self._postOpMapper(result) + return yaml.safe_dump(result) + + def generateANDNode(self, node): + generated = [ self.generateNode(val) for val in node ] + filtered = [ g for g in generated if g is not None ] + if not filtered: + return None + + # Map any possible keywords. + filtered = self._mapKeywordVals(filtered) + + if 1 == len(filtered): + if self._postOpMapper is not None: + filtered[0] = self._postOpMapper(filtered[0]) + return filtered[0] + result = { + "op": "and", + "rules": filtered, + } + if self._postOpMapper is not None: + result = self._postOpMapper(result) + return result + + def generateORNode(self, node): + generated = [self.generateNode(val) for val in node] + filtered = [g for g in generated if g is not None] + if not filtered: + return None + + # Map any possible keywords. + filtered = self._mapKeywordVals(filtered) + + if 1 == len(filtered): + if self._postOpMapper is not None: + filtered[0] = self._postOpMapper(filtered[0]) + return filtered[0] + result = { + "op": "or", + "rules": filtered, + } + if self._postOpMapper is not None: + result = self._postOpMapper(result) + return result + + def generateNOTNode(self, node): + generated = self.generateNode(node.item) + if generated is None: + return None + if not isinstance(generated, dict): + raise NotImplementedError("Not operator not available on non-dict nodes.") + generated["not"] = not generated.get("not", False) + return generated + + def generateSubexpressionNode(self, node): + return self.generateNode(node.items) + + def generateListNode(self, node): + return [self.generateNode(value) for value in node] + + def generateMapItemNode(self, node): + fieldname, value = node + + fieldNameAndValCallback = None + + # The mapping can be a dictionary of mapping or a callable + # to get the correct value. + if callable(self._fieldMappingInEffect): + fieldname = self._fieldMappingInEffect(fieldname) + else: + try: + # The mapping can also be a callable that will + # return a mapped key AND value. + if callable(self._fieldMappingInEffect[fieldname]): + fieldNameAndValCallback = self._fieldMappingInEffect[fieldname] + else: + fieldname = self._fieldMappingInEffect[fieldname] + except: + raise NotImplementedError("Field name %s not supported by backend." % (fieldname,)) + + # If fieldname returned is None, it's a special case where we + # ignore the node. + if fieldname is None: + return None + + if isinstance(value, (int, str)): + if fieldNameAndValCallback is not None: + fieldname, value = fieldNameAndValCallback(fieldname, value) + op, newVal = self._valuePatternToLcOp(value) + newOp = { + "op": op, + "path": fieldname, + "case sensitive": False, + } + if op == "matches": + newOp["re"] = newVal + else: + newOp["value"] = newVal + if self._postOpMapper is not None: + newOp = self._postOpMapper(newOp) + return newOp + elif isinstance(value, list): + subOps = [] + for v in value: + if fieldNameAndValCallback is not None: + fieldname, v = fieldNameAndValCallback(fieldname, v) + op, newVal = self._valuePatternToLcOp(v) + newOp = { + "op": op, + "path": fieldname, + "case sensitive": False, + } + if op == "matches": + newOp["re"] = newVal + else: + newOp["value"] = newVal + if self._postOpMapper is not None: + newOp = self._postOpMapper(newOp) + subOps.append(newOp) + if 1 == len(subOps): + return subOps[0] + return { + "op": "or", + "rules": subOps + } + elif isinstance(value, SigmaTypeModifier): + if isinstance(value, SigmaRegularExpressionModifier): + if fieldNameAndValCallback is not None: + fieldname, value = fieldNameAndValCallback(fieldname, value) + result = { + "op": "matches", + "path": fieldname, + "re": re.compile(value), + } + if self._postOpMapper is not None: + result = self._postOpMapper(result) + return result + else: + raise TypeError("Backend does not support TypeModifier: %s" % (str(type(value)))) + elif value is None: + if fieldNameAndValCallback is not None: + fieldname, value = fieldNameAndValCallback(fieldname, value) + result = { + "op": "exists", + "not": True, + "path": fieldname, + } + if self._postOpMapper is not None: + result = self._postOpMapper(result) + return result + else: + raise TypeError("Backend does not support map values of type " + str(type(value))) + + def generateValueNode(self, node): + return node + + def _valuePatternToLcOp(self, val): + # Here we convert the string values supported by Sigma that + # can include wildcards into either proper values (string or int) + # or into altered values to be functionally equivalent using + # a few different LC D&R rule operators. + + # No point evaluating non-strings. + if not isinstance(val, str): + return ("is", str(val) if self._isAllStringValues else val) + + # Is there any wildcard in this string? If not, we can short circuit. + if "*" not in val and "?" not in val: + return ("is", val) + + # Now we do a small optimization for the shortcut operators + # available in LC. We try to see if the wildcards are around + # the main value, but NOT within. If that's the case we can + # use the "starts with", "ends with" or "contains" operators. + isStartsWithWildcard = False + isEndsWithWildcard = False + tmpVal = val + if tmpVal.startswith("*"): + isStartsWithWildcard = True + tmpVal = tmpVal[1:] + if tmpVal.endswith("*") and not (tmpVal.endswith("\\*") and not tmpVal.endswith("\\\\*")): + isEndsWithWildcard = True + if tmpVal.endswith("\\\\*"): + # An extra \ had to be there so it didn't escapte the + # *, but since we plan on removing the *, we can also + # remove one \. + tmpVal = tmpVal[:-2] + else: + tmpVal = tmpVal[:-1] + + # Check to see if there are any other wildcards. If there are + # we cannot use our shortcuts. + if "*" not in tmpVal and "?" not in tmpVal: + if isStartsWithWildcard and isEndsWithWildcard: + return ("contains", tmpVal) + + if isStartsWithWildcard: + return ("ends with", tmpVal) + + if isEndsWithWildcard: + return ("starts with", tmpVal) + + # This is messy, but it is accurate in generating a RE based on + # the simplified wildcard system, while also supporting the + # escaping of those wildcards. + segments = [] + tmpVal = val + while True: + nEscapes = 0 + for i in range(len(tmpVal)): + # We keep a running count of backslash escape + # characters we see so that if we meet a wildcard + # we can tell whether the wildcard is escaped + # (with odd number of escapes) or if it's just a + # backslash literal before a wildcard (even number). + if "\\" == tmpVal[i]: + nEscapes += 1 + continue + + if "*" == tmpVal[i]: + if 0 == nEscapes: + segments.append(re.escape(tmpVal[:i])) + segments.append(".*") + elif nEscapes % 2 == 0: + segments.append(re.escape(tmpVal[:i - nEscapes])) + segments.append(tmpVal[i - nEscapes:i]) + segments.append(".*") + else: + segments.append(re.escape(tmpVal[:i - nEscapes])) + segments.append(tmpVal[i - nEscapes:i + 1]) + tmpVal = tmpVal[i + 1:] + break + + if "?" == tmpVal[i]: + if 0 == nEscapes: + segments.append(re.escape(tmpVal[:i])) + segments.append(".") + elif nEscapes % 2 == 0: + segments.append(re.escape(tmpVal[:i - nEscapes])) + segments.append(tmpVal[i - nEscapes:i]) + segments.append(".") + else: + segments.append(re.escape(tmpVal[:i - nEscapes])) + segments.append(tmpVal[i - nEscapes:i + 1]) + tmpVal = tmpVal[i + 1:] + break + + nEscapes = 0 + else: + segments.append(re.escape(tmpVal)) + break + + val = ''.join(segments) + + return ("matches", val) + + def _mapKeywordVals(self, values): + # This function ensures that the list of values passed + # are proper D&R operations, if they are strings it indicates + # they were requested as keyword matches. We only support + # keyword matches when specified in the config. We generally just + # map them to the most common field in LC that makes sense. + mapped = [] + + for val in values: + # Non-keywords are just passed through. + if not isinstance(val, str): + mapped.append(val) + continue + + if self._keywordField is None: + raise NotImplementedError("Full-text keyboard searches not supported.") + + # This seems to be indicative only of "keywords" which are mostly + # representative of full-text searches. We don't suport that but + # in some data sources we can alias them to an actual field. + op, newVal = self._valuePatternToLcOp(val) + newOp = { + "op": op, + "path": self._keywordField, + } + if op == "matches": + newOp["re"] = newVal + else: + newOp["value"] = newVal + mapped.append(newOp) + + return mapped diff --git a/tools/sigma/backends/mdatp.py b/tools/sigma/backends/mdatp.py index 096ee829..f31c5c01 100644 --- a/tools/sigma/backends/mdatp.py +++ b/tools/sigma/backends/mdatp.py @@ -15,9 +15,25 @@ # along with this program. If not, see . import re +from functools import wraps from .base import SingleTextQueryBackend from .exceptions import NotSupportedError + +def wrapper(method): + @wraps(method) + def _impl(self, method_args): + key, value, *_ = method_args + if '.keyword' in key: + key = key.split('.keyword')[0] + if key not in self.skip_fields: + method_output = method(self, method_args) + return method_output + else: + return + return _impl + + class WindowsDefenderATPBackend(SingleTextQueryBackend): """Converts Sigma rule into Microsoft Defender ATP Hunting Queries.""" identifier = "mdatp" @@ -41,6 +57,16 @@ class WindowsDefenderATPBackend(SingleTextQueryBackend): mapExpression = "%s == %s" mapListsSpecialHandling = True mapListValueExpression = "%s in %s" + + skip_fields = { + "Description", + "_exists_", + "FileVersion", + "Product", + "Company", + "ParentProcessName", + "ParentCommandLine" + } def __init__(self, *args, **kwargs): """Initialize field mappings""" @@ -57,6 +83,7 @@ class WindowsDefenderATPBackend(SingleTextQueryBackend): "DestinationIp" : ("RemoteIP", self.default_value_mapping), "DestinationIsIpv6" : ("RemoteIP has \":\"", ), "DestinationPort" : ("RemotePort", self.default_value_mapping), + "Protocol" : ("RemoteProtocol", self.default_value_mapping), "Details" : ("RegistryValueData", self.default_value_mapping), "EventType" : ("ActionType", self.default_value_mapping), "Image" : ("FolderPath", self.default_value_mapping), @@ -151,6 +178,7 @@ class WindowsDefenderATPBackend(SingleTextQueryBackend): return "%s | where tostring(extractjson('$.Command', AdditionalFields)) in~ " % self.table return "%s | where " % self.table + @wrapper def generateMapItemNode(self, node): """ ATP queries refer to event tables instead of Windows logging event identifiers. This method catches conditions that refer to this field diff --git a/tools/sigma/backends/splunk.py b/tools/sigma/backends/splunk.py index 63cb8810..75658343 100644 --- a/tools/sigma/backends/splunk.py +++ b/tools/sigma/backends/splunk.py @@ -72,6 +72,7 @@ class SplunkBackend(SingleTextQueryBackend): def generate(self, sigmaparser): """Method is called for each sigma rule and receives the parsed rule (SigmaParser)""" columns = list() + mapped =None try: for field in sigmaparser.parsedyaml["fields"]: mapped = sigmaparser.config.get_fieldmapping(field).resolve_fieldname(field, sigmaparser) @@ -170,3 +171,40 @@ class SplunkXMLBackend(SingleTextQueryBackend, MultiRuleOutputMixin): def finalize(self): self.queries += self.dash_suf return self.queries + +class CrowdStrikeBackend(SplunkBackend): + """Converts Sigma rule into CrowdStrike Search Processing Language (SPL).""" + identifier = "crowdstrike" + + def generate(self, sigmaparser): + lgs = sigmaparser.parsedyaml.get("logsource") + if lgs.get("product") == "windows" and (lgs.get("service") == "sysmon" or lgs.get("category") == "process_creation"): + fieldmappings = sigmaparser.config.fieldmappings + detections = sigmaparser.definitions + all_fields = dict() + for det in detections.values(): + try: + for field, value in det.items(): + if "|" in field: + field = field.split("|")[0] + if any([item for item in fieldmappings.keys() if field == item]): + if field == "EventID" and str(value) == str(1) and lgs.get("service") == "sysmon": + all_fields.update(det) + elif field != "EventID": + all_fields.update(det) + else: + raise NotImplementedError("Not supported fields!") + else: + raise NotImplementedError("Not supported fields!") + except AttributeError: # ignore if detection is not a dict + pass + + table_fields = sigmaparser.parsedyaml.get("fields", []) + res_table_fields = [] + for fl in table_fields: + if fl in fieldmappings.keys(): + res_table_fields.append(fl) + sigmaparser.parsedyaml["fields"] = res_table_fields + return super().generate(sigmaparser) + else: + raise NotImplementedError("Not supported logsources!") diff --git a/tools/sigma/backends/sql.py b/tools/sigma/backends/sql.py index b3149c01..5b446a6f 100644 --- a/tools/sigma/backends/sql.py +++ b/tools/sigma/backends/sql.py @@ -1,5 +1,6 @@ # Output backends for sigmac # Copyright 2019 Jayden Zheng +# Copyright 2020 Jonas Hagg # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by @@ -16,7 +17,9 @@ import re import sigma -from .base import SingleTextQueryBackend +from sigma.backends.base import SingleTextQueryBackend +from sigma.parser.condition import SigmaAggregationParser, NodeSubexpression, ConditionAND, ConditionOR, ConditionNOT +from sigma.parser.exceptions import SigmaParseError class SQLBackend(SingleTextQueryBackend): """Converts Sigma rule into SQL query""" @@ -34,12 +37,16 @@ class SQLBackend(SingleTextQueryBackend): notNullExpression = "%s=*" # Expression of queries for not null values. %s is field name mapExpression = "%s = %s" # Syntax for field/value conditions. First %s is fieldname, second is value mapMulti = "%s IN %s" # Syntax for field/value conditions. First %s is fieldname, second is value - mapWildcard = "%s LIKE %s" # Syntax for swapping wildcard conditions. + mapWildcard = "%s LIKE %s ESCAPE \'\\\'"# Syntax for swapping wildcard conditions: Adding \ as escape character mapSource = "%s=%s" # Syntax for sourcetype mapListsSpecialHandling = False # Same handling for map items with list values as for normal values (strings, integers) if True, generateMapItemListNode method is called with node mapListValueExpression = "%s OR %s" # Syntax for field/value condititons where map value is a list mapLength = "(%s %s)" + def __init__(self, sigmaconfig, table): + super().__init__(sigmaconfig) + self.table = table + def generateANDNode(self, node): generated = [ self.generateNode(val) for val in node ] filtered = [ g for g in generated if g is not None ] @@ -78,29 +85,32 @@ class SQLBackend(SingleTextQueryBackend): def generateMapItemNode(self, node): fieldname, value = node transformed_fieldname = self.fieldNameMapping(fieldname, value) - if "," in self.generateNode(value) and "%" not in self.generateNode(value): + + has_wildcard = re.search(r"((\\(\*|\?|\\))|\*|\?|_|%)", self.generateNode(value)) + + if "," in self.generateNode(value) and not has_wildcard: return self.mapMulti % (transformed_fieldname, self.generateNode(value)) elif "LENGTH" in transformed_fieldname: return self.mapLength % (transformed_fieldname, value) elif type(value) == list: return self.generateMapItemListNode(transformed_fieldname, value) elif self.mapListsSpecialHandling == False and type(value) in (str, int, list) or self.mapListsSpecialHandling == True and type(value) in (str, int): - if "%" in self.generateNode(value): + if has_wildcard: return self.mapWildcard % (transformed_fieldname, self.generateNode(value)) else: return self.mapExpression % (transformed_fieldname, self.generateNode(value)) elif "sourcetype" in transformed_fieldname: return self.mapSource % (transformed_fieldname, self.generateNode(value)) - elif "*" in str(value): + elif has_wildcard: return self.mapWildcard % (transformed_fieldname, self.generateNode(value)) else: raise TypeError("Backend does not support map values of type " + str(type(value))) def generateMapItemListNode(self, key, value): - return "(" + (" OR ".join(['%s LIKE %s' % (key, self.generateValueNode(item)) for item in value])) + ")" - + return "(" + (" OR ".join([self.mapWildcard % (key, self.generateValueNode(item)) for item in value])) + ")" + def generateValueNode(self, node): - return self.valueExpression % (self.cleanValue(str(node))) + return self.valueExpression % (self.cleanValue(str(node))) def generateNULLValueNode(self, node): return self.nullExpression % (node.item) @@ -117,10 +127,97 @@ class SQLBackend(SingleTextQueryBackend): return fieldname def cleanValue(self, val): - if "*" == val: - pass - elif "*.*.*" in val: - val = val.replace("*.*.*", "%") - elif re.search(r'\*', val): - val = re.sub(r'\*', '%', val) + if not isinstance(val, str): + return str(val) + + #Single backlashes which are not in front of * or ? are doulbed + val = re.sub(r"(? full text search + #False: no subexpression found, where a full text search is needed + + def _evaluateCondition(condition): + #Helper function to evaulate condtions + if type(condition) not in [ConditionAND, ConditionOR, ConditionNOT]: + raise NotImplementedError("Error in recursive Search logic") + + results = [] + for elem in condition.items: + if isinstance(elem, NodeSubexpression): + results.append(self._recursiveFtsSearch(elem)) + if isinstance(elem, ConditionNOT): + results.append(_evaluateCondition(elem)) + if isinstance(elem, tuple): + results.append(False) + if type(elem) in (str, int, list): + return True + return any(results) + + if type(subexpression) in [str, int, list]: + return True + elif type(subexpression) in [tuple]: + return False + + if not isinstance(subexpression, NodeSubexpression): + raise NotImplementedError("Error in recursive Search logic") + + if isinstance(subexpression.items, NodeSubexpression): + return self._recursiveFtsSearch(subexpression.items) + elif type(subexpression.items) in [ConditionAND, ConditionOR, ConditionNOT]: + return _evaluateCondition(subexpression.items) \ No newline at end of file diff --git a/tools/sigma/backends/sqlite.py b/tools/sigma/backends/sqlite.py new file mode 100644 index 00000000..8eec13ea --- /dev/null +++ b/tools/sigma/backends/sqlite.py @@ -0,0 +1,123 @@ +# Output backends for sigmac +# Copyright 2020 Jonas Hagg + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +from sigma.backends.sql import SQLBackend +from sigma.parser.condition import NodeSubexpression, ConditionAND, ConditionOR, ConditionNOT +import re + + +class SQLiteBackend(SQLBackend): + """Converts Sigma rule into SQL query for SQLite""" + identifier = "sqlite" + active = True + + mapFullTextSearch = "%s MATCH ('\"%s\"')" + + def __init__(self, sigmaconfig, table): + super().__init__(sigmaconfig, table) + self.mappingItem = False + + def requireFTS(self, node): + return (not self.mappingItem and + (type(node) in (int, str) or all(isinstance(val, str) for val in node) or all(isinstance(val, int) for val in node))) + + def generateFTS(self, value): + if re.search(r"((\\(\*|\?|\\))|\*|\?|_|%)", value): + raise NotImplementedError( + "Wildcards in SQlite Full Text Search not implemented") + self.countFTS += 1 + return self.mapFullTextSearch % (self.table, value) + + def generateANDNode(self, node): + + if self.requireFTS(node): + fts = str('"' + self.andToken + '"').join(self.cleanValue(val) + for val in node) + return self.generateFTS(fts) + + generated = [self.generateNode(val) for val in node] + filtered = [g for g in generated if g is not None] + if filtered: + return self.andToken.join(filtered) + else: + return None + + def generateORNode(self, node): + + if self.requireFTS(node): + fts = str('"' + self.orToken + '"').join(self.cleanValue(val) + for val in node) + return self.generateFTS(fts) + + generated = [self.generateNode(val) for val in node] + filtered = [g for g in generated if g is not None] + if filtered: + return self.orToken.join(filtered) + else: + return None + + def generateMapItemNode(self, node): + try: + self.mappingItem = True + fieldname, value = node + transformed_fieldname = self.fieldNameMapping(fieldname, value) + + has_wildcard = re.search( + r"((\\(\*|\?|\\))|\*|\?|_|%)", self.generateNode(value)) + + if "," in self.generateNode(value) and not has_wildcard: + return self.mapMulti % (transformed_fieldname, self.generateNode(value)) + elif "LENGTH" in transformed_fieldname: + return self.mapLength % (transformed_fieldname, value) + elif type(value) == list: + return self.generateMapItemListNode(transformed_fieldname, value) + elif self.mapListsSpecialHandling == False and type(value) in (str, int, list) or self.mapListsSpecialHandling == True and type(value) in (str, int): + + if has_wildcard: + return self.mapWildcard % (transformed_fieldname, self.generateNode(value)) + else: + return self.mapExpression % (transformed_fieldname, self.generateNode(value)) + + elif "sourcetype" in transformed_fieldname: + return self.mapSource % (transformed_fieldname, self.generateNode(value)) + elif has_wildcard: + return self.mapWildcard % (transformed_fieldname, self.generateNode(value)) + else: + raise TypeError( + "Backend does not support map values of type " + str(type(value))) + finally: + self.mappingItem = False + + def generateValueNode(self, node): + if self.mappingItem: + return self.valueExpression % (self.cleanValue(str(node))) + else: + return self.generateFTS(self.cleanValue(str(node))) + + def generateQuery(self, parsed): + self.countFTS = 0 + result = self.generateNode(parsed.parsedSearch) + if self.countFTS > 1: + raise NotImplementedError( + "Match operator ({}) is allowed only once in SQLite, parse rule in a different way:\n{}".format(self.countFTS, result)) + self.countFTS = 0 + + if parsed.parsedAgg: + # Handle aggregation + fro, whe = self.generateAggregation(parsed.parsedAgg, result) + return "SELECT * FROM {} WHERE {}".format(fro, whe) + + return "SELECT * FROM {} WHERE {}".format(self.table, result) diff --git a/tools/tests/test_backend_sql.py b/tools/tests/test_backend_sql.py new file mode 100644 index 00000000..b4bd8202 --- /dev/null +++ b/tools/tests/test_backend_sql.py @@ -0,0 +1,334 @@ +# Test output backends for sigmac +# Copyright 2020 Jonas Hagg + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +import unittest +from unittest.mock import patch + +from sigma.backends.sql import SQLBackend + +from sigma.parser.collection import SigmaCollectionParser +from sigma.config.mapping import FieldMapping +from sigma.configuration import SigmaConfiguration + +class TestGenerateQuery(unittest.TestCase): + + def setUp(self): + self.basic_rule = {"title": "Test", "level": "testing"} + self.table = "eventlog" + + def test_regular_queries(self): + # Test regular queries + detection = {"selection": {"fieldname": "test1"}, + "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE fieldname = "test1"'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": 4}, "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE fieldname = "4"'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": [ + "test1", "test2"]}, "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE fieldname IN ("test1", "test2")'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": { + "fieldname": [3, 4]}, "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE fieldname IN ("3", "4")'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname1": "test1", "fieldname2": [ + "test2", "test3"]}, "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE (fieldname1 = "test1" AND fieldname2 IN ("test2", "test3"))'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": "test1"}, "filter": { + "fieldname2": "whatever"}, "condition": "selection and filter"} + expected_result = 'SELECT * FROM {} WHERE (fieldname = "test1" AND fieldname2 = "whatever")'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": "test1"}, "filter": { + "fieldname2": "whatever"}, "condition": "selection or filter"} + expected_result = 'SELECT * FROM {} WHERE (fieldname = "test1" OR fieldname2 = "whatever")'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": "test1"}, "filter": { + "fieldname2": "whatever"}, "condition": "selection and not filter"} + expected_result = 'SELECT * FROM {} WHERE (fieldname = "test1" AND NOT (fieldname2 = "whatever"))'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname1": "test1"}, "filter": { + "fieldname2": "test2"}, "condition": "1 of them"} + expected_result = 'SELECT * FROM {} WHERE (fieldname1 = "test1" OR fieldname2 = "test2")'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname1": "test1"}, "filter": { + "fieldname2": "test2"}, "condition": "all of them"} + expected_result = 'SELECT * FROM {} WHERE (fieldname1 = "test1" AND fieldname2 = "test2")'.format( + self.table) + self.validate(detection, expected_result) + + def test_modifiers(self): + + # contains + detection = {"selection": {"fieldname|contains": "test"}, + "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE "%test%" ESCAPE \'\\\''.format( + self.table) + self.validate(detection, expected_result) + + # all + detection = {"selection": {"fieldname|all": [ + "test1", "test2"]}, "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE (fieldname = "test1" AND fieldname = "test2")'.format( + self.table) + self.validate(detection, expected_result) + + # endswith + detection = {"selection": {"fieldname|endswith": "test"}, + "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE "%test" ESCAPE \'\\\''.format( + self.table) + self.validate(detection, expected_result) + + # startswith + detection = {"selection": {"fieldname|startswith": "test"}, + "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE "test%" ESCAPE \'\\\''.format( + self.table) + self.validate(detection, expected_result) + + def test_aggregations(self): + + # count + detection = {"selection": {"fieldname": "test"}, + "condition": "selection | count() > 5"} + inner_query = 'SELECT count(*) AS agg FROM {} WHERE fieldname = "test"'.format( + self.table) + expected_result = 'SELECT * FROM ({}) WHERE agg > 5'.format(inner_query) + self.validate(detection, expected_result) + + # min + detection = {"selection": {"fieldname1": "test"}, + "condition": "selection | min(fieldname2) > 5"} + inner_query = 'SELECT min(fieldname2) AS agg FROM {} WHERE fieldname1 = "test"'.format( + self.table) + expected_result = 'SELECT * FROM ({}) WHERE agg > 5'.format(inner_query) + self.validate(detection, expected_result) + + # max + detection = {"selection": {"fieldname1": "test"}, + "condition": "selection | max(fieldname2) > 5"} + inner_query = 'SELECT max(fieldname2) AS agg FROM {} WHERE fieldname1 = "test"'.format( + self.table) + expected_result = 'SELECT * FROM ({}) WHERE agg > 5'.format(inner_query) + self.validate(detection, expected_result) + + # avg + detection = {"selection": {"fieldname1": "test"}, + "condition": "selection | avg(fieldname2) > 5"} + inner_query = 'SELECT avg(fieldname2) AS agg FROM {} WHERE fieldname1 = "test"'.format( + self.table) + expected_result = 'SELECT * FROM ({}) WHERE agg > 5'.format(inner_query) + self.validate(detection, expected_result) + + # sum + detection = {"selection": {"fieldname1": "test"}, + "condition": "selection | sum(fieldname2) > 5"} + inner_query = 'SELECT sum(fieldname2) AS agg FROM {} WHERE fieldname1 = "test"'.format( + self.table) + expected_result = 'SELECT * FROM ({}) WHERE agg > 5'.format(inner_query) + self.validate(detection, expected_result) + + # < + detection = {"selection": {"fieldname1": "test"}, + "condition": "selection | sum(fieldname2) < 5"} + inner_query = 'SELECT sum(fieldname2) AS agg FROM {} WHERE fieldname1 = "test"'.format( + self.table) + expected_result = 'SELECT * FROM ({}) WHERE agg < 5'.format(inner_query) + self.validate(detection, expected_result) + + # == + detection = {"selection": {"fieldname1": "test"}, + "condition": "selection | sum(fieldname2) == 5"} + inner_query = 'SELECT sum(fieldname2) AS agg FROM {} WHERE fieldname1 = "test"'.format( + self.table) + expected_result = 'SELECT * FROM ({}) WHERE agg == 5'.format(inner_query) + self.validate(detection, expected_result) + + # group by + detection = {"selection": {"fieldname1": "test"}, + "condition": "selection | sum(fieldname2) by fieldname3 == 5"} + inner_query = 'SELECT sum(fieldname2) AS agg FROM {} WHERE fieldname1 = "test" GROUP BY fieldname3'.format( + self.table) + expected_result = 'SELECT * FROM ({}) WHERE agg == 5'.format(inner_query) + self.validate(detection, expected_result) + + # multiple conditions + detection = {"selection": {"fieldname1": "test"}, "filter": { + "fieldname2": "tessst"}, "condition": "selection OR filter | sum(fieldname2) == 5"} + inner_query = 'SELECT sum(fieldname2) AS agg FROM {} WHERE (fieldname1 = "test" OR fieldname2 = "tessst")'.format( + self.table) + expected_result = 'SELECT * FROM ({}) WHERE agg == 5'.format(inner_query) + self.validate(detection, expected_result) + + def test_wildcards(self): + + # wildcard: * + detection = {"selection": {"fieldname": "test*"}, + "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test%"' + r" ESCAPE '\'" + self.validate(detection, expected_result) + + # wildcard: ? + detection = {"selection": {"fieldname": "test?"}, + "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test_"' + r" ESCAPE '\'" + self.validate(detection, expected_result) + + # escaping: + detection = {"selection": {"fieldname": r"test\?"}, + "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test\?"' + r" ESCAPE '\'" + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": r"test\\*"}, + "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test\\%"' + r" ESCAPE '\'" + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": r"test\*"}, + "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test\*"' + r" ESCAPE '\'" + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": r"test\\"}, + "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test\\"' + r" ESCAPE '\'" + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": r"test\abc"}, + "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test\\abc"' + r" ESCAPE '\'" + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": r"test%"}, + "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test\%"' + r" ESCAPE '\'" + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname": r"test_"}, + "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE fieldname LIKE '.format( + self.table) + r'"test\_"' + r" ESCAPE '\'" + self.validate(detection, expected_result) + + # multiple options + detection = {"selection": {"fieldname": [ + "test*", "*test"]}, "condition": "selection"} + opt1 = 'fieldname LIKE ' + r'"test%"' + r" ESCAPE '\'" + opt2 = 'fieldname LIKE ' + r'"%test"' + r" ESCAPE '\'" + expected_result = 'SELECT * FROM {} WHERE ({} OR {})'.format( + self.table, opt1, opt2) + self.validate(detection, expected_result) + + detection = {"selection": {"fieldname|all": [ + "test*", "*test"]}, "condition": "selection"} + opt1 = 'fieldname LIKE ' + r'"test%"' + r" ESCAPE '\'" + opt2 = 'fieldname LIKE ' + r'"%test"' + r" ESCAPE '\'" + expected_result = 'SELECT * FROM {} WHERE ({} AND {})'.format( + self.table, opt1, opt2) + self.validate(detection, expected_result) + + def test_fieldname_mapping(self): + detection = {"selection": {"fieldname": "test1"}, + "condition": "selection"} + expected_result = 'SELECT * FROM {} WHERE mapped_fieldname = "test1"'.format( + self.table) + + # configure mapping + config = SigmaConfiguration() + config.fieldmappings["fieldname"] = FieldMapping( + "fieldname", "mapped_fieldname") + + self.basic_rule["detection"] = detection + + with patch("yaml.safe_load_all", return_value=[self.basic_rule]): + parser = SigmaCollectionParser("any sigma io", config, None) + backend = SQLBackend(config, self.table) + + assert len(parser.parsers) == 1 + + for p in parser.parsers: + self.assertEqual(expected_result, backend.generate(p)) + + def test_not_implemented(self): + # near aggregation not implemented + detection = {"selection": {"fieldname": "test"}, "filter": { + "fieldname": "test2"}, "condition": "selection | near selection and filter"} + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + # re modifier is not implemented + detection = {"selection": {"fieldname|re": "test"}, + "condition": "selection"} + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + #Full Text Search is not implemented + detection = {"selection": ["test1"], "condition": "selection"} + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + + def validate(self, detection, expectation): + + config = SigmaConfiguration() + + self.basic_rule["detection"] = detection + + with patch("yaml.safe_load_all", return_value=[self.basic_rule]): + parser = SigmaCollectionParser("any sigma io", config, None) + backend = SQLBackend(config, self.table) + + assert len(parser.parsers) == 1 + + for p in parser.parsers: + if isinstance(expectation, str): + self.assertEqual(expectation, backend.generate(p)) + elif isinstance(expectation, Exception): + self.assertRaises(type(expectation), backend.generate, p) + + +if __name__ == '__main__': + unittest.main() diff --git a/tools/tests/test_backend_sqlite.py b/tools/tests/test_backend_sqlite.py new file mode 100644 index 00000000..66fc6812 --- /dev/null +++ b/tools/tests/test_backend_sqlite.py @@ -0,0 +1,148 @@ +# Test output backends for sigmac +# Copyright 2020 Jonas Hagg + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +import unittest +from unittest.mock import patch + +from sigma.backends.sqlite import SQLiteBackend + +from sigma.parser.collection import SigmaCollectionParser +from sigma.config.mapping import FieldMapping +from sigma.configuration import SigmaConfiguration + +class TestFullTextSearch(unittest.TestCase): + + def setUp(self): + self.basic_rule = {"title": "Test", "level": "testing"} + self.table = "eventlog" + + def test_full_text_search(self): + detection = {"selection": ["test1"], "condition": "selection"} + expected_result = 'SELECT * FROM {0} WHERE {0} MATCH (\'"test1"\')'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": [5], "condition": "selection"} + expected_result = 'SELECT * FROM {0} WHERE {0} MATCH (\'"5"\')'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": ["test1", "test2"], "condition": "selection"} + expected_result = 'SELECT * FROM {0} WHERE ({0} MATCH (\'"test1" OR "test2"\'))'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": ["test1"], "filter":["test2"], "condition": "selection and filter"} + expected_result = 'SELECT * FROM {0} WHERE ({0} MATCH (\'"test1" AND "test2"\'))'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": [5, 6], "condition": "selection"} + expected_result = 'SELECT * FROM {0} WHERE ({0} MATCH (\'"5" OR "6"\'))'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": ["test1"], "filter": [ + "test2"], "condition": "selection or filter"} + expected_result = 'SELECT * FROM {0} WHERE ({0} MATCH (\'"test1" OR "test2"\'))'.format( + self.table) + self.validate(detection, expected_result) + + detection = {"selection": ["test1"], "filter": [ + "test2"], "condition": "selection and filter"} + expected_result = 'SELECT * FROM {0} WHERE ({0} MATCH (\'"test1" AND "test2"\'))'.format( + self.table) + self.validate(detection, expected_result) + + def test_full_text_search_aggregation(self): + # aggregation with fts + detection = {"selection": ["test"], + "condition": "selection | count() > 5"} + inner_query = 'SELECT count(*) AS agg FROM {0} WHERE {0} MATCH (\'"test"\')'.format( + self.table) + expected_result = 'SELECT * FROM ({}) WHERE agg > 5'.format(inner_query) + self.validate(detection, expected_result) + + detection = {"selection": ["test1", "test2"], + "condition": "selection | count() > 5"} + inner_query = 'SELECT count(*) AS agg FROM {0} WHERE ({0} MATCH (\'"test1" OR "test2"\'))'.format( + self.table) + expected_result = 'SELECT * FROM ({}) WHERE agg > 5'.format(inner_query) + self.validate(detection, expected_result) + + # aggregation + group by + fts + detection = {"selection": ["test1", "test2"], + "condition": "selection | count() by fieldname > 5"} + inner_query = 'SELECT count(*) AS agg FROM {0} WHERE ({0} MATCH (\'"test1" OR "test2"\')) GROUP BY fieldname'.format( + self.table) + expected_result = 'SELECT * FROM ({}) WHERE agg > 5'.format(inner_query) + self.validate(detection, expected_result) + + def test_not_implemented(self): + # fts not implemented with wildcards + detection = {"selection": ["test*"], "condition": "selection"} + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + detection = {"selection": ["test?"], "condition": "selection"} + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + detection = {"selection": ["test\\"], "condition": "selection"} + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + + # fts is not implemented for nested condtions + detection = {"selection": ["test"], "filter": [ + "test2"], "condition": "selection and filter"} # this is ok + detection = {"selection": ["test"], "filter": [ + "test2"], "condition": "selection or filter"} # this is ok + detection = {"selection": ["test"], "filter": [ + "test2"], "condition": "selection and not filter"} # this is already nested + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + detection = {"selection": ["test"], "filter": [ + "test2"], "condition": "selection and filter and filter"} # this is nested + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + detection = {"selection": ["test"], "filter": [ + "test2"], "condition": "selection and filter or filter"} # this is nested + expected_result = NotImplementedError() + self.validate(detection, expected_result) + + def validate(self, detection, expectation): + + config = SigmaConfiguration() + + self.basic_rule["detection"] = detection + + with patch("yaml.safe_load_all", return_value=[self.basic_rule]): + parser = SigmaCollectionParser("any sigma io", config, None) + backend = SQLiteBackend(config, self.table) + + assert len(parser.parsers) == 1 + + for p in parser.parsers: + if isinstance(expectation, str): + self.assertEqual(expectation, backend.generate(p)) + elif isinstance(expectation, Exception): + self.assertRaises(type(expectation), backend.generate, p) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file From c992dc52156ce2278d196fa031600d3b3368c57e Mon Sep 17 00:00:00 2001 From: Thomas Patzke Date: Fri, 5 Jun 2020 23:33:51 +0200 Subject: [PATCH 49/94] Improved test coverage --- tools/sigma/backends/mdatp.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/tools/sigma/backends/mdatp.py b/tools/sigma/backends/mdatp.py index e82e4c2c..f373c042 100644 --- a/tools/sigma/backends/mdatp.py +++ b/tools/sigma/backends/mdatp.py @@ -32,7 +32,6 @@ def wrapper(method): return return _impl - class WindowsDefenderATPBackend(SingleTextQueryBackend): """Converts Sigma rule into Microsoft Defender ATP Hunting Queries.""" identifier = "mdatp" @@ -188,14 +187,9 @@ class WindowsDefenderATPBackend(SingleTextQueryBackend): def generate(self, sigmaparser): self.table = None - try: - self.category = sigmaparser.parsedyaml['logsource'].setdefault('category', None) - self.product = sigmaparser.parsedyaml['logsource'].setdefault('product', None) - self.service = sigmaparser.parsedyaml['logsource'].setdefault('service', None) - except KeyError: - self.category = None - self.product = None - self.service = None + self.category = sigmaparser.parsedyaml['logsource'].get('category') + self.product = sigmaparser.parsedyaml['logsource'].get('product') + self.service = sigmaparser.parsedyaml['logsource'].get('service') if (self.category, self.product, self.service) == ("process_creation", "windows", None): self.table = "DeviceProcessEvents" From 1d211565fcc6d0e9f34a5ba003f60758c3358271 Mon Sep 17 00:00:00 2001 From: Thomas Patzke Date: Sat, 6 Jun 2020 00:49:57 +0200 Subject: [PATCH 50/94] Moved backend options list to --backend-help --- CHANGELOG.md | 4 ++++ Makefile | 1 + tools/sigmac | 22 +++++++++++----------- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d1966ef..52f02ad2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ from version 0.14.0. * LOGIQ Backend (logiq) +### Changed + +* Moved backend option list to --help-backend + ### Fixed * Splunx XML rule name is now set to rule title diff --git a/Makefile b/Makefile index e4968975..695842ca 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,7 @@ test-sigmac: $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -h $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -l + $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac --backend-help es-qs ! $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvd -t es-qs rules/ > /dev/null ! $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t es-qs rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t es-qs --shoot-yourself-in-the-foot rules/ > /dev/null diff --git a/tools/sigmac b/tools/sigmac index 89129e7b..3b338f2d 100755 --- a/tools/sigmac +++ b/tools/sigmac @@ -74,22 +74,21 @@ def get_inputs(paths, recursive): else: return [pathlib.Path(p) for p in paths] -class SigmacArgumentParser(argparse.ArgumentParser): - def format_help(self): - helptext = super().format_help() + "\nBackend options:\n" +class ActionBackendHelp(argparse.Action): + def __call__(self, parser, ns, vals, opt): + backend = backends.getBackend(vals) + if len(backend.options) > 0: + helptext = "Backend options for " + backend.identifier + "\n" + for option, default, help, _ in backend.options: + helptext += " {:10}: {} (default: {})".format(option, help, default) + "\n" - for backend in backends.getBackendList(): - if len(backend.options) > 0: - helptext += " " + backend.identifier + "\n" - for option, default, help, _ in backend.options: - helptext += " {:10}: {} (default: {})".format(option, help, default) + "\n" - - return helptext + print(helptext) + exit(0) def set_argparser(): """Sets up and parses the command line arguments for Sigmac. Returns the argparser""" - argparser = SigmacArgumentParser(description="Convert Sigma rules into SIEM signatures.") + argparser = argparse.ArgumentParser(description="Convert Sigma rules into SIEM signatures.") argparser.add_argument("--recurse", "-r", action="store_true", help="Use directory as input (recurse into subdirectories is not implemented yet)") argparser.add_argument("--filter", "-f", help=""" Define comma-separated filters that must match (AND-linked) to rule to be processed. @@ -106,6 +105,7 @@ def set_argparser(): argparser.add_argument("--output", "-o", default=None, help="Output file or filename prefix if multiple files are generated") argparser.add_argument("--backend-option", "-O", action="append", help="Options and switches that are passed to the backend") argparser.add_argument("--backend-config", "-C", help="Configuration file (YAML format) containing options to pass to the backend") + argparser.add_argument("--backend-help", action=ActionBackendHelp, help="Print backend options") argparser.add_argument("--defer-abort", "-d", action="store_true", help="Don't abort on parse or conversion errors, proceed with next rule. The exit code from the last error is returned") argparser.add_argument("--ignore-backend-errors", "-I", action="store_true", help="Only return error codes for parse errors and ignore errors for rules that cause backend errors. Useful, when you want to get as much queries as possible.") argparser.add_argument("--shoot-yourself-in-the-foot", action="store_true", help=argparse.SUPPRESS) From fb9855bd3bd7cfb695dc75d0855e5d77e542cda6 Mon Sep 17 00:00:00 2001 From: Thomas Patzke Date: Sat, 6 Jun 2020 01:02:44 +0200 Subject: [PATCH 51/94] Added description to es-rule backend --- tools/sigma/backends/elasticsearch.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/sigma/backends/elasticsearch.py b/tools/sigma/backends/elasticsearch.py index 88cdd9c6..d476fc93 100644 --- a/tools/sigma/backends/elasticsearch.py +++ b/tools/sigma/backends/elasticsearch.py @@ -1175,6 +1175,7 @@ class ElastalertBackendQs(ElastalertBackend, ElasticsearchQuerystringBackend): return [{ 'query' : { 'query_string' : { 'query' : super().generateQuery(parsed) } } }] class ElasticSearchRuleBackend(ElasticsearchQuerystringBackend): + """Elasticsearch detection rule backend""" identifier = "es-rule" active = True From 7d70cd95a492ac3f0633a142e4f77b7b10bc42bc Mon Sep 17 00:00:00 2001 From: Thomas Patzke Date: Sat, 6 Jun 2020 01:03:02 +0200 Subject: [PATCH 52/94] Deduplicated backend list --- CHANGELOG.md | 1 + tools/sigma/tools.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52f02ad2..161c66de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ from version 0.14.0. ### Fixed * Splunx XML rule name is now set to rule title +* Backend list deduplicated ## 0.16.0 - 2020-02-25 diff --git a/tools/sigma/tools.py b/tools/sigma/tools.py index c60c8dcd..1bdce530 100644 --- a/tools/sigma/tools.py +++ b/tools/sigma/tools.py @@ -19,12 +19,12 @@ import importlib def getAllSubclasses(path, import_base, base_class): """Return list of all classes derived from a superclass contained in a module.""" - classes = list() + classes = set() for finder, name, ispkg in pkgutil.iter_modules([ path ]): module = importlib.import_module(".{}.{}".format(import_base, name), __package__) for name, cls in vars(module).items(): if type(cls) == type and issubclass(cls, base_class) and cls.active: - classes.append(cls) + classes.add(cls) return classes def getClassDict(clss): From 8688e8a2a192d72661b1b93f28a5a465f66d078a Mon Sep 17 00:00:00 2001 From: Thomas Patzke Date: Sun, 7 Jun 2020 00:22:59 +0200 Subject: [PATCH 53/94] Script entrypoint stubs --- tools/merge_sigma | 5 +++++ tools/sigma2misp | 5 +++++ tools/sigma_similarity | 5 +++++ tools/sigma_uuid | 5 +++++ tools/sigmac | 5 +++++ 5 files changed, 25 insertions(+) create mode 100755 tools/merge_sigma create mode 100755 tools/sigma2misp create mode 100755 tools/sigma_similarity create mode 100755 tools/sigma_uuid create mode 100755 tools/sigmac diff --git a/tools/merge_sigma b/tools/merge_sigma new file mode 100755 index 00000000..4bbf3cb3 --- /dev/null +++ b/tools/merge_sigma @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 + +from sigma.merge_sigma import main + +main() diff --git a/tools/sigma2misp b/tools/sigma2misp new file mode 100755 index 00000000..b8510166 --- /dev/null +++ b/tools/sigma2misp @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 + +from sigma.sigma2misp import main + +main() diff --git a/tools/sigma_similarity b/tools/sigma_similarity new file mode 100755 index 00000000..782531b5 --- /dev/null +++ b/tools/sigma_similarity @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 + +from sigma.sigmac import main + +main() diff --git a/tools/sigma_uuid b/tools/sigma_uuid new file mode 100755 index 00000000..9a28a5ed --- /dev/null +++ b/tools/sigma_uuid @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 + +from sigma.sigma_uuid import main + +main() diff --git a/tools/sigmac b/tools/sigmac new file mode 100755 index 00000000..782531b5 --- /dev/null +++ b/tools/sigmac @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 + +from sigma.sigmac import main + +main() From a7d18c7ed9afaa437b8d9eb690c52df671135e0c Mon Sep 17 00:00:00 2001 From: Thomas Patzke Date: Sun, 7 Jun 2020 00:55:36 +0200 Subject: [PATCH 54/94] Converted sigma2attack and added to entry points --- tools/setup.py | 1 + tools/sigma/sigma2attack.py | 109 ++++++++++++++++++------------------ tools/sigma2attack | 5 ++ 3 files changed, 61 insertions(+), 54 deletions(-) create mode 100755 tools/sigma2attack diff --git a/tools/setup.py b/tools/setup.py index 7f867142..98678375 100644 --- a/tools/setup.py +++ b/tools/setup.py @@ -82,6 +82,7 @@ setup( 'sigmac = sigma.sigmac:main', 'merge_sigma = sigma.merge_sigma:main', 'sigma2misp = sigma.sigma2misp:main', + 'sigma2attack = sigma.sigma2attack:main', 'sigma_similarity = sigma.sigma_similarity:main', 'sigma_uuid = sigma.sigma_uuid:main', ], diff --git a/tools/sigma/sigma2attack.py b/tools/sigma/sigma2attack.py index 5a5ea20a..f33f462e 100755 --- a/tools/sigma/sigma2attack.py +++ b/tools/sigma/sigma2attack.py @@ -8,62 +8,63 @@ import sys import yaml -parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) -parser.add_argument("--rules-directory", "-d", dest="rules_dir", default="rules", help="Directory to read rules from") -parser.add_argument("--out-file", "-o", dest="out_file", default="heatmap.json", help="File to write the JSON layer to") -parser.add_argument("--no-comment", dest="no_comment", action="store_true", help="Don't store rule names in comments") -args = parser.parse_args() +def main(): + parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument("--rules-directory", "-d", dest="rules_dir", default="rules", help="Directory to read rules from") + parser.add_argument("--out-file", "-o", dest="out_file", default="heatmap.json", help="File to write the JSON layer to") + parser.add_argument("--no-comment", dest="no_comment", action="store_true", help="Don't store rule names in comments") + args = parser.parse_args() -rule_files = glob.glob(os.path.join(args.rules_dir, "**/*.yml"), recursive=True) -techniques_to_rules = {} -curr_max_technique_count = 0 -num_rules_used = 0 -for rule_file in rule_files: - try: - rule = yaml.safe_load(open(rule_file).read()) - except yaml.YAMLError: - sys.stderr.write("Ignoring rule " + rule_file + " (parsing failed)\n") - continue - if "tags" not in rule: - sys.stderr.write("Ignoring rule " + rule_file + " (no tags)\n") - continue - tags = rule["tags"] - for tag in tags: - if tag.lower().startswith("attack.t"): - technique_id = tag[len("attack."):].upper() - num_rules_used += 1 - if technique_id not in techniques_to_rules: - techniques_to_rules[technique_id] = [] - techniques_to_rules[technique_id].append(os.path.basename(rule_file)) - curr_max_technique_count = max(curr_max_technique_count, len(techniques_to_rules[technique_id])) + rule_files = glob.glob(os.path.join(args.rules_dir, "**/*.yml"), recursive=True) + techniques_to_rules = {} + curr_max_technique_count = 0 + num_rules_used = 0 + for rule_file in rule_files: + try: + rule = yaml.safe_load(open(rule_file).read()) + except yaml.YAMLError: + sys.stderr.write("Ignoring rule " + rule_file + " (parsing failed)\n") + continue + if "tags" not in rule: + sys.stderr.write("Ignoring rule " + rule_file + " (no tags)\n") + continue + tags = rule["tags"] + for tag in tags: + if tag.lower().startswith("attack.t"): + technique_id = tag[len("attack."):].upper() + num_rules_used += 1 + if technique_id not in techniques_to_rules: + techniques_to_rules[technique_id] = [] + techniques_to_rules[technique_id].append(os.path.basename(rule_file)) + curr_max_technique_count = max(curr_max_technique_count, len(techniques_to_rules[technique_id])) -scores = [] -for technique in techniques_to_rules: - entry = { - "techniqueID": technique, - "score": len(techniques_to_rules[technique]), + scores = [] + for technique in techniques_to_rules: + entry = { + "techniqueID": technique, + "score": len(techniques_to_rules[technique]), + } + if not args.no_comment: + entry["comment"] = "\n".join(techniques_to_rules[technique]) + + scores.append(entry) + + output = { + "domain": "mitre-enterprise", + "name": "Sigma rules heatmap", + "gradient": { + "colors": [ + "#ffffff", + "#ff6666" + ], + "maxValue": curr_max_technique_count, + "minValue": 0 + }, + "version": "2.2", + "techniques": scores, } - if not args.no_comment: - entry["comment"] = "\n".join(techniques_to_rules[technique]) - scores.append(entry) - -output = { - "domain": "mitre-enterprise", - "name": "Sigma rules heatmap", - "gradient": { - "colors": [ - "#ffffff", - "#ff6666" - ], - "maxValue": curr_max_technique_count, - "minValue": 0 - }, - "version": "2.2", - "techniques": scores, -} - -with open(args.out_file, "w") as f: - f.write(json.dumps(output)) - print("[*] Layer file written in " + args.out_file + " (" + str(num_rules_used) + " rules)") \ No newline at end of file + with open(args.out_file, "w") as f: + f.write(json.dumps(output)) + print("[*] Layer file written in " + args.out_file + " (" + str(num_rules_used) + " rules)") diff --git a/tools/sigma2attack b/tools/sigma2attack new file mode 100755 index 00000000..622243e1 --- /dev/null +++ b/tools/sigma2attack @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 + +from sigma.sigma2attack import main + +main() From 36a7077648075cd46bba7b745002d64812ce550a Mon Sep 17 00:00:00 2001 From: Thomas Patzke Date: Sun, 7 Jun 2020 01:14:04 +0200 Subject: [PATCH 55/94] Moved tool executables to new location --- tools/{merge_sigma => sigma/merge_sigma.py} | 0 tools/{sigma-similarity => sigma/sigma-similarity.py} | 0 tools/{sigma-uuid => sigma/sigma-uuid.py} | 0 tools/{sigma2attack => sigma/sigma2attack.py} | 0 tools/{sigma2genericsigma => sigma/sigma2genericsigma.py} | 0 tools/{sigma2misp => sigma/sigma2misp.py} | 0 tools/{sigmac => sigma/sigmac.py} | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename tools/{merge_sigma => sigma/merge_sigma.py} (100%) rename tools/{sigma-similarity => sigma/sigma-similarity.py} (100%) rename tools/{sigma-uuid => sigma/sigma-uuid.py} (100%) rename tools/{sigma2attack => sigma/sigma2attack.py} (100%) rename tools/{sigma2genericsigma => sigma/sigma2genericsigma.py} (100%) rename tools/{sigma2misp => sigma/sigma2misp.py} (100%) rename tools/{sigmac => sigma/sigmac.py} (100%) diff --git a/tools/merge_sigma b/tools/sigma/merge_sigma.py similarity index 100% rename from tools/merge_sigma rename to tools/sigma/merge_sigma.py diff --git a/tools/sigma-similarity b/tools/sigma/sigma-similarity.py similarity index 100% rename from tools/sigma-similarity rename to tools/sigma/sigma-similarity.py diff --git a/tools/sigma-uuid b/tools/sigma/sigma-uuid.py similarity index 100% rename from tools/sigma-uuid rename to tools/sigma/sigma-uuid.py diff --git a/tools/sigma2attack b/tools/sigma/sigma2attack.py similarity index 100% rename from tools/sigma2attack rename to tools/sigma/sigma2attack.py diff --git a/tools/sigma2genericsigma b/tools/sigma/sigma2genericsigma.py similarity index 100% rename from tools/sigma2genericsigma rename to tools/sigma/sigma2genericsigma.py diff --git a/tools/sigma2misp b/tools/sigma/sigma2misp.py similarity index 100% rename from tools/sigma2misp rename to tools/sigma/sigma2misp.py diff --git a/tools/sigmac b/tools/sigma/sigmac.py similarity index 100% rename from tools/sigmac rename to tools/sigma/sigmac.py From 94b90adf10ac5da2142a10799b56c35b6bc2c5d3 Mon Sep 17 00:00:00 2001 From: Florian Roth Date: Sun, 7 Jun 2020 12:18:26 +0200 Subject: [PATCH 56/94] docs: move Sigmac help from Wiki to repo --- tools/README.md | 229 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 221 insertions(+), 8 deletions(-) diff --git a/tools/README.md b/tools/README.md index f5d09d1a..bc04c478 100644 --- a/tools/README.md +++ b/tools/README.md @@ -1,11 +1,224 @@ -This package contains libraries for processing of [Sigma rules](https://github.com/Neo23x0/sigma) and the following -command line tools: +# Sigma Tools -* *sigmac*: converter between Sigma rules and SIEM queries: - * Elasticsearch query strings - * Kibana JSON with searches - * Splunk SPL queries - * Elasticsearch X-Pack Watcher - * Logpoint queries +This folder contains libraries and the following command line tools: + +* *sigmac*: converter between Sigma rules and SIEM queries * *merge_sigma*: Merge Sigma collections into simple Sigma rules. * *sigma2misp*: Import Sigma rules to MISP events. + +# Sigmac + +## Configuration File + +The configuration file contains mappings for the target environments: + +* between generic Sigma field names and those used in the target environment +* between log source identifiers from Sigma and... + * ...index names from target + * ...conditions that should be added to generated expression (e.g. EventLog: Microsoft-Windows-Sysmon) with AND. +* between placeholders in sigma rules and lists that describe their values in the target environment + +The mappings are configured in a YAML file with the following format: + +```yaml +title: short description of configuration +order: numeric value +backends: + - backend_1 + - backend_2 + - ... +fieldmappings: + sigma_fieldname_1: target_fieldname # Simple mapping + sigma_fieldname_2: # Multiple mappings + - target_fieldname_1 + - target_fieldname_2 + sigma_fieldname_3: # Conditional mapping + field1=value1: + field2=value2: + - target_fieldname_1 + - target_fieldname_2 +logsources: + sigma_logsource: + category: ... + product: ... + service: ... + index: + - target_indexname1 + - target_indexname2 + conditions: + field1: value1 + field2: value2 +logsourcemerging: and/or +defaultindex: indexname +placeholders: + name1: + - value1 + - value2 + name2: value +``` + +## Metadata + +A configuration should contain the following attributes: + +* **title**: Short description of configuration shown in list printed by converter on request. +* **order**: Numeric value that determines allowed order of usage. A configuration *B* can only be applied after another configuration *A* if order of B is higher or equal to order of A. The Sigma converter enforces this. Convention: + * 10: Configurations for generic log sources + * 20: Backend-specific configuration +* **backends**: List of backend names. The configuration can't be used with backends not listed here. Don't define for generic configurations. + +## Field Mappings + +Field mappings in the *fieldmappings* section map between Sigma field names and field names used in target SIEM systems. There are three types of field mappings: + +* Simple: the source field name corresponds to exactly one target field name given as string. Exmaple: `EventID: EventCode` for translation of Windows event identifiers between Sigma and Splunk. +* Multiple: a source field corresponds to a list of target fields. Sigmac generates an OR condition that covers all field names. This can be useful in configuration change and migration scenarios, when field names change. A further use case is when the SIEM normalizes one source field name into different target field names and the exact rules are unknown. +* Conditional: a source field is translated to one or multiple target field names depending on values from other fields in specific rules. This is useful in scenarios where the SIEM maps the same Sigma field to different target field names depending on the event or log type, like Logpoint. + +While simple and multiple mapping type are quite straightforward, conditional mappings require further explanation. The mapping is provided as map where the keys have the following format: + +* field=value: condition that must be fulfilled for execution of the given translation +* default: mapping that is used if no condition matches. + +Sigmac applies conditional mappings as follows: + +1. All conditions are mapped against all field:value pairs of the rule. It merges all pairs into one table and is therefore not able to distinguish between different definitions. Matching mappings are collected in a list. +2. If the list is empty, the default mapping is used. +3. The result set of target field name mappings is translated into an OR condition, similar to multiple field mappings. If no mapping could be determined, the Sigma field name is used. + +Use the *fieldlist* backend to determine all field names used by rules. Example: + +```bash +$ tools/sigmac.py -r -t fieldlist rules/windows/ 2>/dev/null | sort -u +AccessMask +CallTrace +CommandLine +[...] +TicketOptions +Type +``` + +## Log Source Mappings + +Each log source definition must contain at least one category, product or service element that corresponds to the same fields in the logsources part of sigma rules. If more than one field is given, all must match (AND). + +The *index* field can contain a string or a list of strings. They a converted to the target expression language in a way that the rule is searched in all given index patterns. + +The conditions part can be used to define *field: value* conditions if only a subset of the given indices is relevant. All fields are linked with logical AND and the resulting expression is also lined with AND against the expression generated from the sigma rule. + +Example: a logstash configuration passes all Windows logs in one index. For Sysmon only events that match *EventLog:"Microsoft-Windows-Sysmon" are relevant. The config looks as follows: + +```yaml +... +logsources: + sysmon: + product: sysmon + index: logstash-windows-* + conditions: + EventLog: Microsoft-Windows-Sysmon +... +``` + +If multiple log source definitions match, the result is merged from all matching rules. The parameter *logsourcemerging* determines how conditions are merged. The following methods are supported: + +* and (default): merge all conditions with logical AND. +* or: merge all conditions with logical OR. + +This enables to define logsources hierarchically, e.g.: + +```yaml +logsources: + windows: + product: windows + index: logstash-windows-* + windows-application: + product: windows + service: application + conditions: + EventLog: Application + windows-security: + product: windows + service: security + conditions: + EventLog: Security +``` + +Log source windows configures an index name. Log sources windows-application and windows-security define additional conditions for matching events in the windows indices. + +The keyword defaultindex defines one or multiple index patterns that are used if the above calculation doesn't results in at least one index name. + +## Addition of Target Formats + +Addition of a target format is done by development of a backend class. A backend class gets a parse tree as input and must translate parse tree nodes into the target format. + +## Translation Process + +1. Parsing YAML +2. Parsing of Condition +3. Internal representation of condition as parse tree +4. Attachment of definitions into corresponding parse tree nodes +5. Translation of field and log source identifiers into target names +6. Translation of parse tree into target format (backend classes) + +## Backend Configuration Files + +You can also pass backend options from a configuration file, which simplifies the CLI usage. + +One can specify both individual backend options (--backend-option) and specify a configuration file as well - in this case, options are merged, and priority is given to the options passed via the CLI. + +Sample usages: + +```yaml +# Backend configuration file (here for Elastalert) +$ cat backend_config.yml +alert_methods: email +emails: alerts@mydomain.tld +smtp_host: smtp.google.com +from_addr: noreply@mydomain.tld +expo_realert_time: 10m + +# Rule to compile +$ RULE=rules/windows/builtin/win_susp_sam_dump.yml + +# Generate an elastalert rule and take options from the configuration file +$ python3 tools/sigmac $RULE -t elastalert --backend-config backend_config.yml +alert: +- email +description: Detects suspicious SAM dump activity as cause by QuarksPwDump and other + password dumpers +email: +- alerts@mydomain.tld +filter: +- query: + query_string: + query: (EventID:"16" AND "*\\AppData\\Local\\Temp\\SAM\-*.dmp\ *") +from_addr: noreply@mydomain.tld +index: logstash-* +name: SAM-Dump-to-AppData_0 +priority: 2 +realert: + minutes: 0 +smtp_host: smtp.google.com +type: any + +# Override an option from the configuration file via the CLI +$ python3 tools/sigmac $RULE -t elastalert --backend-config backend_config.yml --backend-option smtp_host=smtp.mailgun.com +alert: +- email +description: Detects suspicious SAM dump activity as cause by QuarksPwDump and other + password dumpers +email: +- alerts@mydomain.tld +filter: +- query: + query_string: + query: (EventID:"16" AND "*\\AppData\\Local\\Temp\\SAM\-*.dmp\ *") +from_addr: noreply@mydomain.tld +index: logstash-* +name: SAM-Dump-to-AppData_0 +priority: 2 +realert: + minutes: 0 +smtp_host: smtp.mailgun.com +type: any +``` From 117ceac4927fd626bd2bc8db1238705da6c43b6b Mon Sep 17 00:00:00 2001 From: Nate Guagenti Date: Tue, 9 Jun 2020 08:56:01 -0400 Subject: [PATCH 57/94] moved file to `ecs-zeek-elastic-beats-implementation.yml` --- tools/config/filebeat-zeek-ecs.yml | 468 ----------------------------- 1 file changed, 468 deletions(-) delete mode 100644 tools/config/filebeat-zeek-ecs.yml diff --git a/tools/config/filebeat-zeek-ecs.yml b/tools/config/filebeat-zeek-ecs.yml deleted file mode 100644 index 9000db4f..00000000 --- a/tools/config/filebeat-zeek-ecs.yml +++ /dev/null @@ -1,468 +0,0 @@ -title: Zeek field mappings for default collection of JSON logs with no parsing/normalization done and sending into logstash-*index -order: 20 -backends: - - es-qs - - es-dsl - - elasticsearch-rule - - kibana - - xpack-watcher - - elastalert - - elastalert-dsl -logsources: - zeek: - product: zeek - index: 'logstash*' - zeek-category-accounting: - category: accounting - rewrite: - product: zeek - service: syslog - zeek-category-firewall: - category: firewall - conditions: - '@stream': conn - zeek-category-dns: - category: dns - conditions: - '@stream': dns - zeek-category-proxy: - category: proxy - rewrite: - product: zeek - service: http - zeek-category-webserver: - category: webserver - conditions: - '@stream': http - rewrite: - product: zeek - service: http - zeek-conn: - product: zeek - service: conn - conditions: - '@stream': conn - zeek-conn_long: - product: zeek - service: conn_long - conditions: - '@stream': conn_long - zeek-dce_rpc: - product: zeek - service: dce_rpc - conditions: - '@stream': dce_rpc - zeek-dns: - product: zeek - service: dns - conditions: - '@stream': dns - zeek-dnp3: - product: zeek - service: dnp3 - conditions: - '@stream': dnp3 - zeek-dpd: - product: zeek - service: dpd - conditions: - '@stream': dpd - zeek-files: - product: zeek - service: files - conditions: - '@stream': files - zeek-ftp: - product: zeek - service: ftp - conditions: - '@stream': ftp - zeek-gquic: - product: zeek - service: gquic - conditions: - '@stream': gquic - zeek-http: - product: zeek - service: http - conditions: - '@stream': http - zeek-http2: - product: zeek - service: http2 - conditions: - '@stream': http2 - zeek-intel: - product: zeek - service: intel - conditions: - '@stream': intel - zeek-irc: - product: zeek - service: irc - conditions: - '@stream': irc - zeek-kerberos: - product: zeek - service: kerberos - conditions: - '@stream': kerberos - zeek-known_certs: - product: zeek - service: known_certs - conditions: - '@stream': known_certs - zeek-known_hosts: - product: zeek - service: known_hosts - conditions: - '@stream': known_hosts - zeek-known_modbus: - product: zeek - service: known_modbus - conditions: - '@stream': known_modbus - zeek-known_services: - product: zeek - service: known_services - conditions: - '@stream': known_services - zeek-modbus: - product: zeek - service: modbus - conditions: - '@stream': modbus - zeek-modbus_register_change: - product: zeek - service: modbus_register_change - conditions: - '@stream': modbus_register_change - zeek-mqtt_connect: - product: zeek - service: mqtt_connect - conditions: - '@stream': mqtt_connect - zeek-mqtt_publish: - product: zeek - service: mqtt_publish - conditions: - '@stream': mqtt_publish - zeek-mqtt_subscribe: - product: zeek - service: mqtt_subscribe - conditions: - '@stream': mqtt_subscribe - zeek-mysql: - product: zeek - service: mysql - conditions: - '@stream': mysql - zeek-notice: - product: zeek - service: notice - conditions: - '@stream': notice - zeek-ntlm: - product: zeek - service: ntlm - conditions: - '@stream': ntlm - zeek-ntp: - product: zeek - service: ntp - conditions: - '@stream': ntp - zeek-ocsp: - product: zeek - service: ntp - conditions: - '@stream': ocsp - zeek-pe: - product: zeek - service: pe - conditions: - '@stream': pe - zeek-pop3: - product: zeek - service: pop3 - conditions: - '@stream': pop3 - zeek-radius: - product: zeek - service: radius - conditions: - '@stream': radius - zeek-rdp: - product: zeek - service: rdp - conditions: - '@stream': rdp - zeek-rfb: - product: zeek - service: rfb - conditions: - '@stream': rfb - zeek-sip: - product: zeek - service: sip - conditions: - '@stream': sip - zeek-smb_files: - product: zeek - service: smb_files - conditions: - '@stream': smb_files - zeek-smb_mapping: - product: zeek - service: smb_mapping - conditions: - '@stream': smb_mapping - zeek-smtp: - product: zeek - service: smtp - conditions: - '@stream': smtp - zeek-smtp_links: - product: zeek - service: smtp_links - conditions: - '@stream': smtp_links - zeek-snmp: - product: zeek - service: snmp - conditions: - '@stream': snmp - zeek-socks: - product: zeek - service: socks - conditions: - '@stream': socks - zeek-software: - product: zeek - service: software - conditions: - '@stream': software - zeek-ssh: - product: zeek - service: ssh - conditions: - '@stream': ssh - zeek-ssl: - product: zeek - service: ssl - conditions: - '@stream': ssl - zeek-tls: # In case people call it TLS even though orig log is called ssl - product: zeek - service: tls - conditions: - '@stream': ssl - zeek-syslog: - product: zeek - service: syslog - conditions: - '@stream': syslog - zeek-tunnel: - product: zeek - service: tunnel - conditions: - '@stream': tunnel - zeek-traceroute: - product: zeek - service: traceroute - conditions: - '@stream': traceroute - zeek-weird: - product: zeek - service: weird - conditions: - '@stream': weird - zeek-x509: - product: zeek - service: x509 - conditions: - '@stream': x509 - zeek-ip_search: - product: zeek - service: network - conditions: - '@stream': - - conn - - conn_long - - dce_rpc - - dhcp - - dnp3 - - dns - - ftp - - gquic - - http - - irc - - kerberos - - modbus - - mqtt_connect - - mqtt_publish - - mqtt_subscribe - - mysql - - ntlm - - ntp - - radius - - rfb - - sip - - smb_files - - smb_mapping - - smtp - - smtp_links - - snmp - - socks - - ssh - - tls #SSL - - tunnel - - weird -defaultindex: 'logstash-*' -fieldmappings: - # All Logs Applied Mapping & Taxonomy - dst_ip: id.resp_h - dst_port: id.resp_p - network_protocol: proto - src_ip: id.orig_h - src_port: id.orig_p - # DNS matching Taxonomy & DNS Category - answer: answers - #question_length: # Does not exist in open source version - record_type: qtype_name - #parent_domain: # Does not exist in open source version - # HTTP matching Taxonomy & Web/Proxy Category - cs-bytes: request_body_len - cs-cookie: cookie - r-dns: host - sc-bytes: response_body_len - sc-status: status_code - c-uri: uri - c-uri-extension: uri - c-uri-query: uri - c-uri-stem: uri - c-useragent: user_agent - cs-host: host - cs-method: method - cs-referrer: referrer - cs-version: version - # Temporary one off rule name fields - agent.version: version - c-cookie: cookie - c-ip: id.orig_h - cs-uri: uri - clientip: id.orig_h - clientIP: id.orig_h - dest_domain: - - query - - host - - server_name - dest_ip: id.resp_h - dest_port: id.resp_p - #TODO:WhatShouldThisBe?==dest: - #TODO:WhatShouldThisBe?==destination: - #TODO:WhatShouldThisBe?==Destination: - destination.hostname: - - query - - host - - server_name - DestinationAddress: - DestinationHostname: - - host - - query - - server_name - DestinationIp: id.resp_h - DestinationIP: id.resp_h - DestinationPort: id.resp_p - dst-ip: id.resp_h - dstip: id.resp_h - dstport: id.resp_p - Host: - - host - - query - - server_name - HostVersion: http.version - http_host: - - host - - query - - server_name - http_uri: uri - http_url: uri - http_user_agent: user_agent - http.request.url-query-params: uri - HttpMethod: method - in_url: uri - # parent_domain: # Not in open source zeek - post_url_parameter: uri - Request Url: uri - request_url: uri - request_URL: uri - RequestUrl: uri - #response: status_code - resource.url: uri - resource.URL: uri - sc_status: status_code - sender_domain: - - query - - server_name - service.response_code: status_code - source: id.orig_h - SourceAddr: id.orig_h - SourceAddress: id.orig_h - SourceIP: id.orig_h - SourceIp: id.orig_h - SourceNetworkAddress: id.orig_h - SourcePort: id.orig_p - srcip: id.orig_h - Status: status_code - status: status_code - url: uri - URL: uri - url_query: uri - url.query: uri - uri_path: uri - user_agent: user_agent - user_agent.name: user_agent - user-agent: user_agent - User-Agent: user_agent - useragent: user_agent - UserAgent: user_agent - User Agent: user_agent - web_dest: - - host - - query - - server_name - web.dest: - - host - - query - - server_name - Web.dest: - - host - - query - - server_name - web.host: - - host - - query - - server_name - Web.host: - - host - - query - - server_name - web_method: method - Web_method: method - web.method: method - Web.method: method - web_src: id.orig_h - web_status: status_code - Web_status: status_code - web.status: status_code - Web.status: status_code - web_uri: uri - web_url: uri - # Most are in ECS, but for things not using Elastic - these need renamed - destination.ip: id.resp_h - destination.port: id.resp_p - http.request.body.content: post_body - #source.domain: - source.ip: id.orig_h - source.port: id.orig_p \ No newline at end of file From d14d391761261c6ed17b1edb1e38dd469a3762a7 Mon Sep 17 00:00:00 2001 From: Remco Hofman Date: Tue, 9 Jun 2020 16:12:05 +0200 Subject: [PATCH 58/94] Octopus Scanner malware rule --- .../malware/win_mal_octopus_scanner.yml | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 rules/windows/malware/win_mal_octopus_scanner.yml diff --git a/rules/windows/malware/win_mal_octopus_scanner.yml b/rules/windows/malware/win_mal_octopus_scanner.yml new file mode 100644 index 00000000..bcc4b998 --- /dev/null +++ b/rules/windows/malware/win_mal_octopus_scanner.yml @@ -0,0 +1,24 @@ +title: Octopus Scanner Malware +id: 805c55d9-31e6-4846-9878-c34c75054fe9 +status: experimental +description: Detects Octopus Scanner Malware. +references: + - https://securitylab.github.com/research/octopus-scanner-malware-open-source-supply-chain +tags: + - attack.t1195 +author: NVISO +date: 2020/06/09 +logsource: + product: windows + service: sysmon +detection: + filecreate: + EventID: 11 + selection: + TargetFilename|endswith: + - '\AppData\Local\Microsoft\Cache134.dat' + - '\AppData\Local\Microsoft\ExplorerSync.db' +condition: filecreate and selection +falsepositives: + - Unknown +level: high \ No newline at end of file From 4ce3ea735e6308bebb554a4fab7286e964ae465e Mon Sep 17 00:00:00 2001 From: Remco Hofman Date: Tue, 9 Jun 2020 16:21:46 +0200 Subject: [PATCH 59/94] TA410 FlowCloud malware detection --- rules/windows/malware/win_mal_flowcloud.yml | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 rules/windows/malware/win_mal_flowcloud.yml diff --git a/rules/windows/malware/win_mal_flowcloud.yml b/rules/windows/malware/win_mal_flowcloud.yml new file mode 100644 index 00000000..566fce0d --- /dev/null +++ b/rules/windows/malware/win_mal_flowcloud.yml @@ -0,0 +1,28 @@ +title: FlowCloud Malware +id: 5118765f-6657-4ddb-a487-d7bd673abbf1 +status: experimental +description: Detects FlowCloud malware from threat group TA410. +references: + - https://www.proofpoint.com/us/blog/threat-insight/ta410-group-behind-lookback-attacks-against-us-utilities-sector-returns-new +author: NVISO +tags: + - attack.persistence + - attack.t1112 +date: 2020/06/09 +logsource: + product: windows + service: sysmon +detection: + selection: + EventID: + - 12 # key create + - 13 # value set + TargetObject: + - 'HKLM\HARDWARE\{804423C2-F490-4ac3-BFA5-13DEDE63A71A}' + - 'HKLM\HARDWARE\{A5124AF5-DF23-49bf-B0ED-A18ED3DEA027}' + - 'HKLM\HARDWARE\{2DB80286-1784-48b5-A751-B6ED1F490303}' + - 'HKLM\SYSTEM\Setup\PrintResponsor\*' + condition: selection +falsepositives: + - Unknown +level: critical From a9bf22750ab73f80a4edb47fc90a1c5365690b29 Mon Sep 17 00:00:00 2001 From: Remco Hofman Date: Tue, 9 Jun 2020 16:30:17 +0200 Subject: [PATCH 60/94] Fixed bad indentation --- rules/windows/malware/win_mal_octopus_scanner.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/windows/malware/win_mal_octopus_scanner.yml b/rules/windows/malware/win_mal_octopus_scanner.yml index bcc4b998..4e7a5888 100644 --- a/rules/windows/malware/win_mal_octopus_scanner.yml +++ b/rules/windows/malware/win_mal_octopus_scanner.yml @@ -18,7 +18,7 @@ detection: TargetFilename|endswith: - '\AppData\Local\Microsoft\Cache134.dat' - '\AppData\Local\Microsoft\ExplorerSync.db' -condition: filecreate and selection + condition: filecreate and selection falsepositives: - Unknown level: high \ No newline at end of file From 04913a4b957697816988fffaa44eaf40a375c944 Mon Sep 17 00:00:00 2001 From: Florian Roth Date: Tue, 9 Jun 2020 17:20:25 +0200 Subject: [PATCH 61/94] Aligned indentation --- .../sysmon_apt_muddywater_dnstunnel.yml | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml index 32004f6e..3cf7b309 100644 --- a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml +++ b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml @@ -5,23 +5,23 @@ author: '@caliskanfurkan_' status: experimental date: 2020/06/04 references: -- https://www.virustotal.com/gui/file/5ad401c3a568bd87dd13f8a9ddc4e450ece61cd9ce4d1b23f68ce0b1f3c190b7/ -- https://www.vmray.com/analyses/5ad401c3a568/report/overview.html + - https://www.virustotal.com/gui/file/5ad401c3a568bd87dd13f8a9ddc4e450ece61cd9ce4d1b23f68ce0b1f3c190b7/ + - https://www.vmray.com/analyses/5ad401c3a568/report/overview.html tags: -- attack.command_and_control -- attack.t1071 + - attack.command_and_control + - attack.t1071 logsource: - category: process_creation - product: windows + category: process_creation + product: windows detection: - selection: - Image|endswith: - - '\powershell.exe' - ParentImage|endswith: - - '\excel.exe' - CommandLine|contains: - - 'DataExchange.dll' + selection: + Image|endswith: + - '\powershell.exe' + ParentImage|endswith: + - '\excel.exe' + CommandLine|contains: + - 'DataExchange.dll' condition: selection falsepositives: -- Unkown -level: medium + - Unkown +level: critical From 7a334a8d8a33d9d2aeeaca34816c4e52b0a87274 Mon Sep 17 00:00:00 2001 From: Florian Roth Date: Tue, 9 Jun 2020 17:30:54 +0200 Subject: [PATCH 62/94] fix: missed line --- rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml index 3cf7b309..3bb4c1aa 100644 --- a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml +++ b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml @@ -21,7 +21,7 @@ detection: - '\excel.exe' CommandLine|contains: - 'DataExchange.dll' - condition: selection + condition: selection falsepositives: - Unkown level: critical From f4fe425fa7a14086e07f743ead4d6dd2b43fab13 Mon Sep 17 00:00:00 2001 From: Nate Guagenti Date: Tue, 9 Jun 2020 16:53:50 -0400 Subject: [PATCH 63/94] update readme for some analyzed field and keyword field examples --- tools/README.md | 108 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/tools/README.md b/tools/README.md index bc04c478..1caf7ae6 100644 --- a/tools/README.md +++ b/tools/README.md @@ -8,6 +8,9 @@ This folder contains libraries and the following command line tools: # Sigmac +The Sigmac is one of the most important files, as this is what sets the correct fields that your backend/database will use after being translated from the (original) log source's field names. +Please read below to understand how a SIGMAC is constructed. Additionally, see [Choosing the Right Sigmac](#choosing-the-right-sigmac) for an idea of which file and command line options (if applicable) that will best suite your environment. + ## Configuration File The configuration file contains mappings for the target environments: @@ -222,3 +225,108 @@ realert: smtp_host: smtp.mailgun.com type: any ``` + + +## Choosing the right SIGMAC + +The section will show you which `-c` option (the Sigmac) and which `--backend-option`(s) to use. The rest of SIGMA should be run as normal. +For example, run the rest of the command as you normally would, regarding the `-t` (target backend) and which rule(s) you are performing SIGMA on. + +If the target backend/database does not do a lot of field renaming/normalization than the selection of which Sigmac to use is easier to determine. +However, this section will help guide you in this decision. + +### Elasticsearch or ELK + +For this backend, there are two very important components. One is the field name and the other is the the way the value for the field name are analyzed AKA searchable in the Elasticsearch database. If you are interested in understand how this is important, you can read more [here](https://socprime.com/blog/elastic-for-security-analysts-part-1-searching-strings/) to understand the impact between `keyword` types and `text` types. +You have a few different variations of what could be the correct Sigmac to use. Based on the version of Elasticsearch, using ECS or not, using certain Beat's settings enabled or not, and so on. + +In order to aide in the decision of the correct Sigmac there are a few quick questions to ask yourself and based on those answers will be which one to use. +Please not the answer to each question. It is OK to not know the answer to each question and in fact is very common (that's OK). +1. What version of filebeat are you using (you may not be using this at all). +2. Are you using Elastic Common Schema (ECS)? +3. What index do your store the log source's data in? Some examples: + - Window's logs are most likely in `winlogbeat-*` + - Linux logs are most likely in `filebeat-*` + - Zeek/Bro data is most likely in `filebeat-*` + - If you are using logstash, data is most likely in `logstash-*` +4. If you are using filebeat, are you using the module enabled? Here is link showing the description for Windows log [Security Channel](https://www.elastic.co/guide/en/beats/winlogbeat/current/winlogbeat-module-security.html) + + +Now choose your data source: +- [Windows Event Logs](#elastic-windows-event-log--sysmon-data-configurations) +- [Zeek](#elastic---zeek-fka-bro--corelight-data) + + +### + +#### Elastic - Zeek (FKA Bro) / Corelight Data + +- Corelight's implementation of ECS: +`-c tools/config/ecs-zeek-corelight.yml --backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text" --backend-option keyword_whitelist="event.dataset,source.ip,destination.ip,source.port,destination.port,*bytes*"` +example of the full command running on all the proxy rules converting to a Kibana (lucene) query: +`tools/sigmac -t es-qs -c tools/config/ecs-zeek-corelight.yml --backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text" --backend-option keyword_whitelist="event.dataset,source.ip,destination.ip,source.port,destination.port,*bytes*" rules/proxy/*` + +- Filebeat version 7 or higher and or Elastic's implementation: +`-c tools/config/ecs-zeek-elastic-beats-implementation.yml --backend-option keyword_base_fields="*"` + +- Using logstash and NOT using ECS: +`-c tools/config/logstash-zeek-default-json.yml` + + + +#### Elastic Windows Event Log / Sysmon Data Configurations + +**index templates** +If you are able, because this will be one of the best ways to dermine which options to use - run the following command. Take the output from question 3 and replace in the example command `winlogbeat` with index. You can run this from the CLI against your Elasticsearch instance or from Kibana Dev Tools. +You will only need to use the first index template pattern. Look under the section `dynamic_templates` and then look for `strings_as_keyword`. Under that section, is there a `strings_as_keyword` ? If so take note. + +`curl -XGET "http://127.0.0.1:9200/winlogbeat-*/_mapping/?filter_path=*.mappings.dynamic_templates*,*.index_patterns"` + +The next question to ask yourself, is do you want easily bypassable queries due to case sensitive searches? Take note of yes/no. + +Now lets determine which options and Sigmac to use. + +**Sigmac's `-c` option** + +1. Using winlogbeat version 6 or less + `-c tools/config/winlogbeat-old.yml` +1. Using winlogbeat version 7 or higher without modules enabled (answer from **question 4**) and `strings_as_keyword` does not contain `text` + `-c tools/config/winlogbeat-old.yml` +2. Using winlogbeat version 7 or higher with modules enabled (answer from **question 4**) +`-c tools/config/winlogbeat-modules-enabled.yml` + +**Backend options `--backend-option`** +You can add the following depending on additional information from your answers/input above. + + +1. If you are using ECS, your data is going to `winlogbeat-*` index, or your default field is a keyword type then add the following to your SIGMA command: + `--backend-option keyword_field="" ` + - If you want to prevent case sensitive bypasses you can add the following to your command: + `--backend-option case_insensitive_whitelist""` + - If you want to prevent case sensitive bypasses but only for certain fields, you can use an option like this: + ``-backend-option keyword_field="" --backend-option case_insensitive_whitelist="*CommandLine*, *ProcessName*, *Image*, process.*, *FileName*, *Path*, *ServiceName*, *ShareName*, file.*, *Directory*, *directory*, *hash*, *Hash*, *Object*, ComputerName, *Subject*, *Target*, *Service*"`` + + + +1. If you are using analyzed (text) fields or your index template portion of `strings_as_keyword` contains `text` then you can add the following: +`--backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text"` + + +1. If you only have some analyzed fields then you would use an example like this: +`--backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text" --backend-option analyzed_sub_fields="TargetUserName, SourceUserName, TargetHostName, CommandLine, ProcessName, ParentProcessName, ParentImage, Image"` + + +#### Elastic - Some Final Examples +So putting it all together to help show everything from above, here are some "full" examples: + +- base field keyword & no analyzed field w/ case insensitivity (covers elastic 7 with beats/ecs (default)mappings) and using winlogbeat with modules enabled + `sigma -t es-qs -c tools/config/winlogbeat-modules-enabled.yml --backend-option keyword_field="" --backend-option case_insensitive_whitelist"" rules/windows/process_creation/win_office_shell.yml` + +- base field keyword & subfield is analyzed(.text) and winlogbeat with modules enabled + `sigma -t es-qs -c tools/config/winlogbeat-modules-enabled.yml --backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text" rules/windows/process_creation/win_office_shell.yml` + + - base field keyword & only some analyzed fields and winlogbeat without modules enabled + `tools/sigmac -t es-dsl -c tools/config/winlogbeat.yml --backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text" --backend-option analyzed_sub_fields="TargetUserName, SourceUserName, TargetHostName, CommandLine, ProcessName, ParentProcessName, ParentImage, Image" rules/windows/process_creation/win_office_shell.yml` + +- using beats/ecs Elastic 7 with case insensitive and some .text fields and winlogbeat without modules enabled + `tools/sigmac -t es-dsl -c tools/config/winlogbeat.yml --backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text" --backend-option keyword_whitelist="winlog.channel,winlog.event_id" --backend-option case_insensitive_whitelist="*" --backend-option analyzed_sub_fields="TargetUserName, SourceUserName, TargetHostName, CommandLine, ProcessName, ParentProcessName, ParentImage, Image" rules/windows/process_creation/win_office_shell.yml` \ No newline at end of file From 565febd39d14f3592064443557d6598647dbcd72 Mon Sep 17 00:00:00 2001 From: Florian Roth Date: Tue, 9 Jun 2020 23:25:09 +0200 Subject: [PATCH 64/94] README updated --- README.md | 6 +-- tools/README.md | 100 ++++++++++++++++++++++++------------------------ 2 files changed, 53 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index ebc0f2b6..b1fc8d06 100644 --- a/README.md +++ b/README.md @@ -88,9 +88,9 @@ Sysmon: Web Shell Detection Windows 'Security' Eventlog: Suspicious Number of Failed Logons from a Single Source Workstation ![sigma_rule example5](./images/Sigma_rule_example5.png) -# Sigma Tools +# Sigma Tools -## Sigmac +## Sigmac Sigmac converts sigma rules into queries or inputs of the supported targets listed below. It acts as a frontend to the Sigma library that may be used to integrate Sigma support in other projects. Further, there's `merge_sigma.py` which @@ -98,7 +98,7 @@ merges multiple YAML documents of a Sigma rule collection into simple Sigma rule ### Usage -``` +```bash usage: sigmac [-h] [--recurse] [--filter FILTER] [--target {arcsight,es-qs,es-dsl,kibana,xpack-watcher,elastalert,graylog,limacharlie,logpoint,grep,netwitness,powershell,qradar,qualys,splunk,splunkxml,sumologic,fieldlist,mdatp,ee-outliers}] [--target-list] [--config CONFIG] [--output OUTPUT] diff --git a/tools/README.md b/tools/README.md index 1caf7ae6..145fdb1a 100644 --- a/tools/README.md +++ b/tools/README.md @@ -226,14 +226,12 @@ smtp_host: smtp.mailgun.com type: any ``` - ## Choosing the right SIGMAC The section will show you which `-c` option (the Sigmac) and which `--backend-option`(s) to use. The rest of SIGMA should be run as normal. For example, run the rest of the command as you normally would, regarding the `-t` (target backend) and which rule(s) you are performing SIGMA on. -If the target backend/database does not do a lot of field renaming/normalization than the selection of which Sigmac to use is easier to determine. -However, this section will help guide you in this decision. +If the target backend/database does not do a lot of field renaming/normalization than the selection of which Sigmac to use is easier to determine. However, this section will help guide you in this decision. ### Elasticsearch or ELK @@ -242,43 +240,37 @@ You have a few different variations of what could be the correct Sigmac to use. In order to aide in the decision of the correct Sigmac there are a few quick questions to ask yourself and based on those answers will be which one to use. Please not the answer to each question. It is OK to not know the answer to each question and in fact is very common (that's OK). + 1. What version of filebeat are you using (you may not be using this at all). 2. Are you using Elastic Common Schema (ECS)? 3. What index do your store the log source's data in? Some examples: - - Window's logs are most likely in `winlogbeat-*` - - Linux logs are most likely in `filebeat-*` - - Zeek/Bro data is most likely in `filebeat-*` - - If you are using logstash, data is most likely in `logstash-*` + * Window's logs are most likely in `winlogbeat-*` + * Linux logs are most likely in `filebeat-*` + * Zeek/Bro data is most likely in `filebeat-*` + * If you are using logstash, data is most likely in `logstash-*` 4. If you are using filebeat, are you using the module enabled? Here is link showing the description for Windows log [Security Channel](https://www.elastic.co/guide/en/beats/winlogbeat/current/winlogbeat-module-security.html) - Now choose your data source: -- [Windows Event Logs](#elastic-windows-event-log--sysmon-data-configurations) -- [Zeek](#elastic---zeek-fka-bro--corelight-data) +* [Windows Event Logs](#elastic-windows-event-log--sysmon-data-configurations) +* [Zeek](#elastic---zeek-fka-bro--corelight-data) +### Elastic - Zeek (FKA Bro) / Corelight Data -### - -#### Elastic - Zeek (FKA Bro) / Corelight Data - -- Corelight's implementation of ECS: +* Corelight's implementation of ECS: `-c tools/config/ecs-zeek-corelight.yml --backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text" --backend-option keyword_whitelist="event.dataset,source.ip,destination.ip,source.port,destination.port,*bytes*"` example of the full command running on all the proxy rules converting to a Kibana (lucene) query: `tools/sigmac -t es-qs -c tools/config/ecs-zeek-corelight.yml --backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text" --backend-option keyword_whitelist="event.dataset,source.ip,destination.ip,source.port,destination.port,*bytes*" rules/proxy/*` - -- Filebeat version 7 or higher and or Elastic's implementation: +* Filebeat version 7 or higher and or Elastic's implementation: `-c tools/config/ecs-zeek-elastic-beats-implementation.yml --backend-option keyword_base_fields="*"` - -- Using logstash and NOT using ECS: +* Using logstash and NOT using ECS: `-c tools/config/logstash-zeek-default-json.yml` - - -#### Elastic Windows Event Log / Sysmon Data Configurations +### Elastic Windows Event Log / Sysmon Data Configurations **index templates** + If you are able, because this will be one of the best ways to dermine which options to use - run the following command. Take the output from question 3 and replace in the example command `winlogbeat` with index. You can run this from the CLI against your Elasticsearch instance or from Kibana Dev Tools. -You will only need to use the first index template pattern. Look under the section `dynamic_templates` and then look for `strings_as_keyword`. Under that section, is there a `strings_as_keyword` ? If so take note. +You will only need to use the first index template pattern. Look under the section `dynamic_templates` and then look for `strings_as_keyword`. Under that section, is there a `strings_as_keyword` ? If so take note. `curl -XGET "http://127.0.0.1:9200/winlogbeat-*/_mapping/?filter_path=*.mappings.dynamic_templates*,*.index_patterns"` @@ -288,45 +280,53 @@ Now lets determine which options and Sigmac to use. **Sigmac's `-c` option** -1. Using winlogbeat version 6 or less - `-c tools/config/winlogbeat-old.yml` -1. Using winlogbeat version 7 or higher without modules enabled (answer from **question 4**) and `strings_as_keyword` does not contain `text` - `-c tools/config/winlogbeat-old.yml` -2. Using winlogbeat version 7 or higher with modules enabled (answer from **question 4**) -`-c tools/config/winlogbeat-modules-enabled.yml` +1. Using winlogbeat version 6 or less `-c tools/config/winlogbeat-old.yml` +2. Using winlogbeat version 7 or higher without modules enabled (answer from **question 4**) and `strings_as_keyword` does not contain `text` `-c tools/config/winlogbeat-old.yml` +3. Using winlogbeat version 7 or higher with modules enabled (answer from **question 4**) `-c tools/config/winlogbeat-modules-enabled.yml` **Backend options `--backend-option`** You can add the following depending on additional information from your answers/input above. +1. If you are using ECS, your data is going to `winlogbeat-*` index, or your default field is a keyword type then add the following to your SIGMA command: `--backend-option keyword_field="" ` + * If you want to prevent case sensitive bypasses you can add the following to your command: `--backend-option case_insensitive_whitelist""` + * If you want to prevent case sensitive bypasses but only for certain fields, you can use an option like this: `-backend-option keyword_field="" --backend-option case_insensitive_whitelist="*CommandLine*, *ProcessName*, *Image*, process.*, *FileName*, *Path*, *ServiceName*, *ShareName*, file.*, *Directory*, *directory*, *hash*, *Hash*, *Object*, ComputerName, *Subject*, *Target*, *Service*"` -1. If you are using ECS, your data is going to `winlogbeat-*` index, or your default field is a keyword type then add the following to your SIGMA command: - `--backend-option keyword_field="" ` - - If you want to prevent case sensitive bypasses you can add the following to your command: - `--backend-option case_insensitive_whitelist""` - - If you want to prevent case sensitive bypasses but only for certain fields, you can use an option like this: - ``-backend-option keyword_field="" --backend-option case_insensitive_whitelist="*CommandLine*, *ProcessName*, *Image*, process.*, *FileName*, *Path*, *ServiceName*, *ShareName*, file.*, *Directory*, *directory*, *hash*, *Hash*, *Object*, ComputerName, *Subject*, *Target*, *Service*"`` +2. If you are using analyzed (text) fields or your index template portion of `strings_as_keyword` contains `text` then you can add the following: +```bash +--backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text" +``` +3. If you only have some analyzed fields then you would use an example like this: -1. If you are using analyzed (text) fields or your index template portion of `strings_as_keyword` contains `text` then you can add the following: -`--backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text"` +```bash +--backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text" --backend-option analyzed_sub_fields="TargetUserName, SourceUserName, TargetHostName, CommandLine, ProcessName, ParentProcessName, ParentImage, Image" +``` +### Elastic - Some Final Examples -1. If you only have some analyzed fields then you would use an example like this: -`--backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text" --backend-option analyzed_sub_fields="TargetUserName, SourceUserName, TargetHostName, CommandLine, ProcessName, ParentProcessName, ParentImage, Image"` - - -#### Elastic - Some Final Examples So putting it all together to help show everything from above, here are some "full" examples: -- base field keyword & no analyzed field w/ case insensitivity (covers elastic 7 with beats/ecs (default)mappings) and using winlogbeat with modules enabled - `sigma -t es-qs -c tools/config/winlogbeat-modules-enabled.yml --backend-option keyword_field="" --backend-option case_insensitive_whitelist"" rules/windows/process_creation/win_office_shell.yml` +* base field keyword & no analyzed field w/ case insensitivity (covers elastic 7 with beats/ecs (default)mappings) and using winlogbeat with modules enabled -- base field keyword & subfield is analyzed(.text) and winlogbeat with modules enabled - `sigma -t es-qs -c tools/config/winlogbeat-modules-enabled.yml --backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text" rules/windows/process_creation/win_office_shell.yml` +```bash +sigma -t es-qs -c tools/config/winlogbeat-modules-enabled.yml --backend-option keyword_field="" --backend-option case_insensitive_whitelist"" rules/windows/process_creation/win_office_shell.yml +``` - - base field keyword & only some analyzed fields and winlogbeat without modules enabled - `tools/sigmac -t es-dsl -c tools/config/winlogbeat.yml --backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text" --backend-option analyzed_sub_fields="TargetUserName, SourceUserName, TargetHostName, CommandLine, ProcessName, ParentProcessName, ParentImage, Image" rules/windows/process_creation/win_office_shell.yml` +* base field keyword & subfield is analyzed(.text) and winlogbeat with modules enabled -- using beats/ecs Elastic 7 with case insensitive and some .text fields and winlogbeat without modules enabled - `tools/sigmac -t es-dsl -c tools/config/winlogbeat.yml --backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text" --backend-option keyword_whitelist="winlog.channel,winlog.event_id" --backend-option case_insensitive_whitelist="*" --backend-option analyzed_sub_fields="TargetUserName, SourceUserName, TargetHostName, CommandLine, ProcessName, ParentProcessName, ParentImage, Image" rules/windows/process_creation/win_office_shell.yml` \ No newline at end of file +```bash +sigma -t es-qs -c tools/config/winlogbeat-modules-enabled.yml --backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text" rules/windows/process_creation/win_office_shell.yml +``` + +* base field keyword & only some analyzed fields and winlogbeat without modules enabled + +```bash +tools/sigmac -t es-dsl -c tools/config/winlogbeat.yml --backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text" --backend-option analyzed_sub_fields="TargetUserName, SourceUserName, TargetHostName, CommandLine, ProcessName, ParentProcessName, ParentImage, Image" rules/windows/process_creation/win_office_shell.yml +``` + +* using beats/ecs Elastic 7 with case insensitive and some .text fields and winlogbeat without modules enabled + +```bash +tools/sigmac -t es-dsl -c tools/config/winlogbeat.yml --backend-option keyword_base_fields="*" --backend-option analyzed_sub_field_name=".text" --backend-option keyword_whitelist="winlog.channel,winlog.event_id" --backend-option case_insensitive_whitelist="*" --backend-option analyzed_sub_fields="TargetUserName, SourceUserName, TargetHostName, CommandLine, ProcessName, ParentProcessName, ParentImage, Image" rules/windows/process_creation/win_office_shell.yml +``` \ No newline at end of file From cb8e478ac1c0d4af334002640624ba77b7bc2add Mon Sep 17 00:00:00 2001 From: Remco Hofman Date: Wed, 10 Jun 2020 14:52:13 +0200 Subject: [PATCH 65/94] Sigma rule to detect Office persistence via addin. --- .../sysmon/sysmon_office_persistence.yml | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 rules/windows/sysmon/sysmon_office_persistence.yml diff --git a/rules/windows/sysmon/sysmon_office_persistence.yml b/rules/windows/sysmon/sysmon_office_persistence.yml new file mode 100644 index 00000000..71db0b36 --- /dev/null +++ b/rules/windows/sysmon/sysmon_office_persistence.yml @@ -0,0 +1,32 @@ +title: Microsoft Office Add-In Loading +id: 8e1cb247-6cf6-42fa-b440-3f27d57e9936 +status: experimental +description: Detects add-ins that load when Microsoft Word or Excel starts (.wll/.xll are simply .dll fit for Word or Excel). +references: + - Internal research +tags: + - attack.persistence + - attack.t1137 +author: NVISO +date: 2020/05/11 +logsource: + product: windows + service: sysmon +detection: + selection: + EventID: 11 #FileCreate + wlldropped: + TargetFilename|contains: \Microsoft\Word\Startup\ + TargetFilename|endswith: .wll + xlldropped: + TargetFilename|contains: \Microsoft\Excel\Startup\ + TargetFilename|endswith: .xll + generic: + TargetFilename|contains: \Microsoft\Addins\ + TargetFilename|endswith: + - .xlam + - .xla +condition: selection and (wlldropped or xlldropped or generic) +falsepositives: + - Legitimate add-ins +level: high From 83a6e25bcbc8de58a25ef991c2c349df36bc50d0 Mon Sep 17 00:00:00 2001 From: Remco Hofman Date: Wed, 10 Jun 2020 15:01:07 +0200 Subject: [PATCH 66/94] Fax Service DLL search order hijacking --- rules/windows/sysmon/sysmon_susp_fax_dll.yml | 31 ++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 rules/windows/sysmon/sysmon_susp_fax_dll.yml diff --git a/rules/windows/sysmon/sysmon_susp_fax_dll.yml b/rules/windows/sysmon/sysmon_susp_fax_dll.yml new file mode 100644 index 00000000..58fe49ee --- /dev/null +++ b/rules/windows/sysmon/sysmon_susp_fax_dll.yml @@ -0,0 +1,31 @@ +title: Fax Service DLL Search Order Hijack +id: 828af599-4c53-4ed2-ba4a-a9f835c434ea +status: experimental +description: The Fax service attempts to load ualapi.dll, which is non-existent. An attacker can then (side)load their own malicious DLL using this service. +references: + - https://windows-internals.com/faxing-your-way-to-system/ +author: NVISO +date: 2020/05/04 +tags: + - attack.persistence + - attack.defense_evasion + - attack.t1073 + - attack.t1038 + - attack.t1112 +logsource: + product: windows + service: sysmon +detection: + selection: + EventID: 7 #ImageLoaded + Image|endswith: + - fxssvc.exe + ImageLoaded|endswith: + - ualapi.dll + filter: + ImageLoaded|startswith: + - C:\Windows\WinSxS\ + condition: selection and not filter +falsepositives: + - Unlikely +level: high From 8adaa2d6724185bdf09dd0bbfbaef57b737d9441 Mon Sep 17 00:00:00 2001 From: Remco Hofman Date: Wed, 10 Jun 2020 15:02:41 +0200 Subject: [PATCH 67/94] Fixed bad indentation --- rules/windows/sysmon/sysmon_office_persistence.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/windows/sysmon/sysmon_office_persistence.yml b/rules/windows/sysmon/sysmon_office_persistence.yml index 71db0b36..813929a0 100644 --- a/rules/windows/sysmon/sysmon_office_persistence.yml +++ b/rules/windows/sysmon/sysmon_office_persistence.yml @@ -26,7 +26,7 @@ detection: TargetFilename|endswith: - .xlam - .xla -condition: selection and (wlldropped or xlldropped or generic) + condition: selection and (wlldropped or xlldropped or generic) falsepositives: - Legitimate add-ins level: high From f553fb2e33a5fc1681fbd7cb7a0cf3d9b22ce5fe Mon Sep 17 00:00:00 2001 From: Florian Roth Date: Wed, 10 Jun 2020 16:35:14 +0200 Subject: [PATCH 68/94] Cosmetics --- rules/windows/sysmon/sysmon_reg_office_security.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rules/windows/sysmon/sysmon_reg_office_security.yml b/rules/windows/sysmon/sysmon_reg_office_security.yml index e9f00dda..31fa9e19 100644 --- a/rules/windows/sysmon/sysmon_reg_office_security.yml +++ b/rules/windows/sysmon/sysmon_reg_office_security.yml @@ -17,14 +17,14 @@ logsource: detection: sec_settings: EventID: - - 12 - - 13 + - 12 + - 13 TargetObject|endswith: - '*\Security\Trusted Documents\TrustRecords' - '*\Security\AccessVBOM' - '*\Security\VBAWarnings' EventType: - - SetValue - - DeleteValue - - CreateValue + - SetValue + - DeleteValue + - CreateValue condition: sec_settings From 13c7d40a22f41fb2e4c8022ad42e87f9b4545050 Mon Sep 17 00:00:00 2001 From: Florian Roth Date: Wed, 10 Jun 2020 16:35:41 +0200 Subject: [PATCH 69/94] Cosmetics --- .../windows/process_creation/win_susp_findstr_lnk.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rules/windows/process_creation/win_susp_findstr_lnk.yml b/rules/windows/process_creation/win_susp_findstr_lnk.yml index 657d47ff..dd594f67 100644 --- a/rules/windows/process_creation/win_susp_findstr_lnk.yml +++ b/rules/windows/process_creation/win_susp_findstr_lnk.yml @@ -3,15 +3,15 @@ id: 33339be3-148b-4e16-af56-ad16ec6c7e7b description: Detects usage of findstr to identify and execute a lnk file as seen within the HHS redirect attack status: experimental references: - - https://www.bleepingcomputer.com/news/security/hhsgov-open-redirect-used-by-coronavirus-phishing-to-spread-malware/ + - https://www.bleepingcomputer.com/news/security/hhsgov-open-redirect-used-by-coronavirus-phishing-to-spread-malware/ tags: - - attack.defense_evasion - - attack.t1202 + - attack.defense_evasion + - attack.t1202 author: Trent Liffick date: 2020/05/01 logsource: - category: process_creation - product: windows + category: process_creation + product: windows detection: selection: Image: '*\findstr.exe' From 6e4aa01baa5eab743896e9be29ff8307e09b1cec Mon Sep 17 00:00:00 2001 From: Florian Roth Date: Wed, 10 Jun 2020 16:36:17 +0200 Subject: [PATCH 70/94] Cosmetics --- .../win_apt_lazarus_session_highjack.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/rules/windows/process_creation/win_apt_lazarus_session_highjack.yml b/rules/windows/process_creation/win_apt_lazarus_session_highjack.yml index a9fc5185..7eb8c3a3 100644 --- a/rules/windows/process_creation/win_apt_lazarus_session_highjack.yml +++ b/rules/windows/process_creation/win_apt_lazarus_session_highjack.yml @@ -3,7 +3,7 @@ id: 3f7f5b0b-5b16-476c-a85f-ab477f6dd24b description: Detects executables launched outside their default directories as used by Lazarus Group (Bluenoroff) status: experimental references: - - https://media.kasperskycontenthub.com/wp-content/uploads/sites/43/2018/03/07180244/Lazarus_Under_The_Hood_PDF_final.pdf + - https://media.kasperskycontenthub.com/wp-content/uploads/sites/43/2018/03/07180244/Lazarus_Under_The_Hood_PDF_final.pdf tags: - attack.defense_evasion - attack.t1036 @@ -14,14 +14,14 @@ logsource: product: windows detection: selection: - Image: - - '*\mstdc.exe' - - '*\gpvc.exe' + Image: + - '*\mstdc.exe' + - '*\gpvc.exe' filter: - Image: - - 'C:\Windows\System32\\*' - - 'C:\Windows\SysWOW64\\*' + Image: + - 'C:\Windows\System32\\*' + - 'C:\Windows\SysWOW64\\*' condition: selection and not filter falsepositives: - - unknown + - unknown level: high From 96309d247bcd65221b4c7c4b8844b8f12d1c695b Mon Sep 17 00:00:00 2001 From: Florian Roth Date: Wed, 10 Jun 2020 16:41:03 +0200 Subject: [PATCH 71/94] fix: cosmetic fault --- .../process_creation/win_apt_lazarus_session_highjack.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/windows/process_creation/win_apt_lazarus_session_highjack.yml b/rules/windows/process_creation/win_apt_lazarus_session_highjack.yml index 7eb8c3a3..7f074637 100644 --- a/rules/windows/process_creation/win_apt_lazarus_session_highjack.yml +++ b/rules/windows/process_creation/win_apt_lazarus_session_highjack.yml @@ -20,7 +20,7 @@ detection: filter: Image: - 'C:\Windows\System32\\*' - - 'C:\Windows\SysWOW64\\*' + - 'C:\Windows\SysWOW64\\*' condition: selection and not filter falsepositives: - unknown From f56e2599b1768a95ce36d36de2c99749d498734b Mon Sep 17 00:00:00 2001 From: Iveco Date: Thu, 11 Jun 2020 15:48:48 +0200 Subject: [PATCH 72/94] Cmd.exe Path Traversal Detection --- .../sysmon_cmd_commandline_path_traversal.yml | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 rules/windows/sysmon/sysmon_cmd_commandline_path_traversal.yml diff --git a/rules/windows/sysmon/sysmon_cmd_commandline_path_traversal.yml b/rules/windows/sysmon/sysmon_cmd_commandline_path_traversal.yml new file mode 100644 index 00000000..d6b0b507 --- /dev/null +++ b/rules/windows/sysmon/sysmon_cmd_commandline_path_traversal.yml @@ -0,0 +1,26 @@ +title: Cmd.exe CommandLine Path Traversal +id: 087790e3-3287-436c-bccf-cbd0184a7db1 +description: detects the usage of path traversal in cmd.exe indicating possible command/argument confusion/hijacking +status: experimental +date: 2020/06/11 +author: xknow @xknow_infosec +references: + - https://hackingiscool.pl/cmdhijack-command-argument-confusion-with-path-traversal-in-cmd-exe/ + - https://twitter.com/Oddvarmoe/status/1270633613449723905 +tags: + - attack.t1059 + - attack.execution +logsource: + product: windows + service: sysmon +detection: + selection_1: + EventID: 1 + ParentCommandLine|contains: 'cmd*/c' + CommandLine|contains: '/../../' + selection_2: + ParentCommandLine|contains: '/../../' + condition: selection_1 AND selection_2 +falsepositives: + - (not much) some benign Java tools may product false-positive commandlines for loading libraries +level: high \ No newline at end of file From 2081baafe584d0a45fc2869567b4e28d7630e56a Mon Sep 17 00:00:00 2001 From: Iveco Date: Thu, 11 Jun 2020 15:58:05 +0200 Subject: [PATCH 73/94] updated to process_creation --- rules/windows/sysmon/sysmon_cmd_commandline_path_traversal.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rules/windows/sysmon/sysmon_cmd_commandline_path_traversal.yml b/rules/windows/sysmon/sysmon_cmd_commandline_path_traversal.yml index d6b0b507..b47b08e1 100644 --- a/rules/windows/sysmon/sysmon_cmd_commandline_path_traversal.yml +++ b/rules/windows/sysmon/sysmon_cmd_commandline_path_traversal.yml @@ -11,11 +11,10 @@ tags: - attack.t1059 - attack.execution logsource: + category: process_creation product: windows - service: sysmon detection: selection_1: - EventID: 1 ParentCommandLine|contains: 'cmd*/c' CommandLine|contains: '/../../' selection_2: From 34d7ea2974f14e1dd0812b4b297d1d3796fd91d6 Mon Sep 17 00:00:00 2001 From: Iveco Date: Thu, 11 Jun 2020 16:23:15 +0200 Subject: [PATCH 74/94] removed one field --- .../sysmon/sysmon_cmd_commandline_path_traversal.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/rules/windows/sysmon/sysmon_cmd_commandline_path_traversal.yml b/rules/windows/sysmon/sysmon_cmd_commandline_path_traversal.yml index b47b08e1..772a615c 100644 --- a/rules/windows/sysmon/sysmon_cmd_commandline_path_traversal.yml +++ b/rules/windows/sysmon/sysmon_cmd_commandline_path_traversal.yml @@ -14,12 +14,10 @@ logsource: category: process_creation product: windows detection: - selection_1: + selection: ParentCommandLine|contains: 'cmd*/c' CommandLine|contains: '/../../' - selection_2: - ParentCommandLine|contains: '/../../' - condition: selection_1 AND selection_2 + condition: selection falsepositives: - (not much) some benign Java tools may product false-positive commandlines for loading libraries level: high \ No newline at end of file From 40f0fd989da959b3f825b6b8e8f6d8ebff7714a9 Mon Sep 17 00:00:00 2001 From: Iveco Date: Thu, 11 Jun 2020 19:21:17 +0200 Subject: [PATCH 75/94] - moved to "process_creation" folder instead of "sysmon" - renamed .yml file --- .../win_commandline_path_traversal.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename rules/windows/{sysmon/sysmon_cmd_commandline_path_traversal.yml => process_creation/win_commandline_path_traversal.yml} (100%) diff --git a/rules/windows/sysmon/sysmon_cmd_commandline_path_traversal.yml b/rules/windows/process_creation/win_commandline_path_traversal.yml similarity index 100% rename from rules/windows/sysmon/sysmon_cmd_commandline_path_traversal.yml rename to rules/windows/process_creation/win_commandline_path_traversal.yml From db0292afd2b3f1d5e7155ac705370b9a1e1cfddd Mon Sep 17 00:00:00 2001 From: Nate Guagenti Date: Fri, 12 Jun 2020 11:36:19 -0400 Subject: [PATCH 76/94] typo, was missing the `=` and `*`. also, show option when using case insensitive for everything, how to "exclude" a field from that regex. --- tools/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/README.md b/tools/README.md index 145fdb1a..a17967f9 100644 --- a/tools/README.md +++ b/tools/README.md @@ -288,7 +288,7 @@ Now lets determine which options and Sigmac to use. You can add the following depending on additional information from your answers/input above. 1. If you are using ECS, your data is going to `winlogbeat-*` index, or your default field is a keyword type then add the following to your SIGMA command: `--backend-option keyword_field="" ` - * If you want to prevent case sensitive bypasses you can add the following to your command: `--backend-option case_insensitive_whitelist""` + * If you want to prevent case sensitive bypasses you can add the following to your command: `--backend-option case_insensitive_whitelist="*"` * If you want to prevent case sensitive bypasses but only for certain fields, you can use an option like this: `-backend-option keyword_field="" --backend-option case_insensitive_whitelist="*CommandLine*, *ProcessName*, *Image*, process.*, *FileName*, *Path*, *ServiceName*, *ShareName*, file.*, *Directory*, *directory*, *hash*, *Hash*, *Object*, ComputerName, *Subject*, *Target*, *Service*"` 2. If you are using analyzed (text) fields or your index template portion of `strings_as_keyword` contains `text` then you can add the following: @@ -307,10 +307,10 @@ You can add the following depending on additional information from your answers/ So putting it all together to help show everything from above, here are some "full" examples: -* base field keyword & no analyzed field w/ case insensitivity (covers elastic 7 with beats/ecs (default)mappings) and using winlogbeat with modules enabled +* base field keyword & no analyzed field w/ case insensitivity (covers elastic 7 with beats/ecs (default)mappings) and using winlogbeat with modules enabled. Also, keeps `winlog.channel` from making case insensitive as is not necessary (ie: the `keyword_whitelist` option) ```bash -sigma -t es-qs -c tools/config/winlogbeat-modules-enabled.yml --backend-option keyword_field="" --backend-option case_insensitive_whitelist"" rules/windows/process_creation/win_office_shell.yml +sigma -t es-qs -c tools/config/winlogbeat-modules-enabled.yml --backend-option keyword_field="" --backend-option case_insensitive_whitelist="*" keyword_whitelist="winlog.channel" rules/windows/process_creation/win_office_shell.yml ``` * base field keyword & subfield is analyzed(.text) and winlogbeat with modules enabled From aac1af1832384f4e8fe8d65c9c7966a6364a9d3c Mon Sep 17 00:00:00 2001 From: Nate Guagenti Date: Fri, 12 Jun 2020 11:36:19 -0400 Subject: [PATCH 77/94] typo, was missing the `=` and `*`. also, show option when using case insensitive for everything, how to "exclude" a field from that regex. Signed-off-by: Nate Guagenti --- tools/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/README.md b/tools/README.md index 145fdb1a..fef6ce16 100644 --- a/tools/README.md +++ b/tools/README.md @@ -288,7 +288,7 @@ Now lets determine which options and Sigmac to use. You can add the following depending on additional information from your answers/input above. 1. If you are using ECS, your data is going to `winlogbeat-*` index, or your default field is a keyword type then add the following to your SIGMA command: `--backend-option keyword_field="" ` - * If you want to prevent case sensitive bypasses you can add the following to your command: `--backend-option case_insensitive_whitelist""` + * If you want to prevent case sensitive bypasses you can add the following to your command: `--backend-option case_insensitive_whitelist="*"` * If you want to prevent case sensitive bypasses but only for certain fields, you can use an option like this: `-backend-option keyword_field="" --backend-option case_insensitive_whitelist="*CommandLine*, *ProcessName*, *Image*, process.*, *FileName*, *Path*, *ServiceName*, *ShareName*, file.*, *Directory*, *directory*, *hash*, *Hash*, *Object*, ComputerName, *Subject*, *Target*, *Service*"` 2. If you are using analyzed (text) fields or your index template portion of `strings_as_keyword` contains `text` then you can add the following: @@ -307,10 +307,10 @@ You can add the following depending on additional information from your answers/ So putting it all together to help show everything from above, here are some "full" examples: -* base field keyword & no analyzed field w/ case insensitivity (covers elastic 7 with beats/ecs (default)mappings) and using winlogbeat with modules enabled +* base field keyword & no analyzed field w/ case insensitivity (covers elastic 7 with beats/ecs (default)mappings) and using winlogbeat with modules enabled. Also, keeps `winlog.channel` from making case insensitive as is not necessary (ie: the `keyword_whitelist` option) ```bash -sigma -t es-qs -c tools/config/winlogbeat-modules-enabled.yml --backend-option keyword_field="" --backend-option case_insensitive_whitelist"" rules/windows/process_creation/win_office_shell.yml +sigma -t es-qs -c tools/config/winlogbeat-modules-enabled.yml --backend-option keyword_field="" --backend-option case_insensitive_whitelist="*" --backend-option keyword_whitelist="winlog.channel" rules/windows/process_creation/win_office_shell.yml ``` * base field keyword & subfield is analyzed(.text) and winlogbeat with modules enabled From bba0b2d85158bcf97f5d9b95a9ed158a8b0d5a16 Mon Sep 17 00:00:00 2001 From: Eric Beahan Date: Fri, 12 Jun 2020 13:22:13 -0500 Subject: [PATCH 78/94] Elastic documentation improvements --- tools/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/README.md b/tools/README.md index fef6ce16..55bf887e 100644 --- a/tools/README.md +++ b/tools/README.md @@ -239,16 +239,16 @@ For this backend, there are two very important components. One is the field name You have a few different variations of what could be the correct Sigmac to use. Based on the version of Elasticsearch, using ECS or not, using certain Beat's settings enabled or not, and so on. In order to aide in the decision of the correct Sigmac there are a few quick questions to ask yourself and based on those answers will be which one to use. -Please not the answer to each question. It is OK to not know the answer to each question and in fact is very common (that's OK). +Please note the answer to each question. It is OK to not know the answer to each question and in fact is very common (that's OK). -1. What version of filebeat are you using (you may not be using this at all). -2. Are you using Elastic Common Schema (ECS)? +1. What version of [Filebeat](https://www.elastic.co/beats/filebeat) are you using (you may not be using this at all). +2. Are you using [Elastic Common Schema (ECS)](https://www.elastic.co/guide/en/ecs/current/index.html)? 3. What index do your store the log source's data in? Some examples: * Window's logs are most likely in `winlogbeat-*` * Linux logs are most likely in `filebeat-*` * Zeek/Bro data is most likely in `filebeat-*` * If you are using logstash, data is most likely in `logstash-*` -4. If you are using filebeat, are you using the module enabled? Here is link showing the description for Windows log [Security Channel](https://www.elastic.co/guide/en/beats/winlogbeat/current/winlogbeat-module-security.html) +4. If you are using Filebeat, are you using the module enabled? Here is link showing the description for Windows log [Security Channel](https://www.elastic.co/guide/en/beats/winlogbeat/current/winlogbeat-module-security.html) Now choose your data source: * [Windows Event Logs](#elastic-windows-event-log--sysmon-data-configurations) @@ -269,7 +269,7 @@ example of the full command running on all the proxy rules converting to a Kiban **index templates** -If you are able, because this will be one of the best ways to dermine which options to use - run the following command. Take the output from question 3 and replace in the example command `winlogbeat` with index. You can run this from the CLI against your Elasticsearch instance or from Kibana Dev Tools. +If you are able, because this will be one of the best ways to determine which options to use - run the following command. Take the output from question 3 and replace in the example command `winlogbeat` with index. You can run this from the CLI against your Elasticsearch instance or from Kibana Dev Tools. You will only need to use the first index template pattern. Look under the section `dynamic_templates` and then look for `strings_as_keyword`. Under that section, is there a `strings_as_keyword` ? If so take note. `curl -XGET "http://127.0.0.1:9200/winlogbeat-*/_mapping/?filter_path=*.mappings.dynamic_templates*,*.index_patterns"` From 80e8f0e5fad4a26b6642b62cf1b35a0d4e2b4d67 Mon Sep 17 00:00:00 2001 From: Thomas Patzke Date: Fri, 12 Jun 2020 23:52:06 +0200 Subject: [PATCH 79/94] Release 0.17.0 --- CHANGELOG.md | 21 ++++++++++++++++++++- tools/setup.py | 3 ++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 161c66de..1c170825 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,20 +6,39 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) from version 0.14.0. -## Unreleased +## 0.17.0 - 2020-06-12 ### Added * LOGIQ Backend (logiq) +* CarbonBlack backend (carbonblack) and field mappings +* Elasticsearch detection rule backend (es-rule) +* ee-outliers backend +* CrowdStrike backend (crowdstrike) +* Humio backend (humio) +* Aggregations in SQL backend +* SQLite backend (sqlite) +* AWS Cloudtrail ECS mappings +* Overrides +* Zeek configurations for various backends +* Case-insensitive matching for Elasticsearch +* ECS proxy mappings +* RuleName field mapping for Winlogbeat +* sigma2attack tool ### Changed +* Improved usage of keyword fields for Elasticsearch-based backends +* Splunk XML backend rule titles from sigma rule instead of file name * Moved backend option list to --help-backend +* Microsoft Defender ATP schema improvements ### Fixed * Splunx XML rule name is now set to rule title * Backend list deduplicated +* Wrong escaping of wildcard at end of value when startswith modifier is used. +* Direct execution of tools on Windows systems by addition of script entry points ## 0.16.0 - 2020-02-25 diff --git a/tools/setup.py b/tools/setup.py index 98678375..0a60cae0 100644 --- a/tools/setup.py +++ b/tools/setup.py @@ -22,7 +22,7 @@ setup( author_email='thomas@patzke.org', license='LGPLv3', classifiers=[ - 'Development Status :: 4 - Beta', + 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'Intended Audience :: Information Technology', 'Intended Audience :: System Administrators', @@ -31,6 +31,7 @@ setup( 'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', 'Environment :: Console', ], keywords='security monitoring siem logging signatures elasticsearch splunk ids sysmon', From b1295563882e29a5581942a869c6bec712711aa7 Mon Sep 17 00:00:00 2001 From: Thomas Patzke Date: Sat, 13 Jun 2020 00:04:45 +0200 Subject: [PATCH 80/94] Automatic inclusion of all configuration files --- tools/setup.py | 33 +++------------------------------ 1 file changed, 3 insertions(+), 30 deletions(-) diff --git a/tools/setup.py b/tools/setup.py index 0a60cae0..2fe63655 100644 --- a/tools/setup.py +++ b/tools/setup.py @@ -4,6 +4,7 @@ from setuptools import setup, find_packages # To use a consistent encoding from codecs import open from os import path +from pathlib import Path here = path.abspath(path.dirname(__file__)) @@ -48,36 +49,8 @@ setup( 'test': ['coverage', 'yamllint'], }, data_files=[ - ('etc/sigma', [ - "config/arcsight.yml", - "config/carbon-black.yml", - "config/ecs-proxy.yml", - "config/filebeat-defaultindex.yml", - "config/helk.yml", - "config/limacharlie.yml", - "config/logpoint-windows.yml", - "config/logstash-defaultindex.yml", - "config/logstash-linux.yml", - "config/logstash-windows.yml", - "config/mitre/tactics.json", - "config/mitre/techniques.json", - "config/netwitness.yml", - "config/powershell.yml", - "config/qradar.yml", - "config/qualys.yml", - "config/splunk-windows-index.yml", - "config/splunk-windows.yml", - "config/splunk-zeek.yml", - "config/sumologic.yml", - "config/thor.yml", - "config/winlogbeat-modules-enabled.yml", - "config/winlogbeat-old.yml", - "config/winlogbeat.yml", - ]), - ('etc/sigma/generic', [ - 'config/generic/sysmon.yml', - 'config/generic/windows-audit.yml', - ])], + ('etc/sigma', [ str(p) for p in Path('config/').glob('*.yml') ]), + ('etc/sigma/generic', [ str(p) for p in Path('config/generic/').glob('*.yml') ])], entry_points={ 'console_scripts': [ 'sigmac = sigma.sigmac:main', From 05ced1a3d526f72a8b20e67b3aab4fcf7e8ec3cd Mon Sep 17 00:00:00 2001 From: Thomas Patzke Date: Sat, 13 Jun 2020 00:05:57 +0200 Subject: [PATCH 81/94] Exclude heatmap.json from versioning --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 13186372..00a05562 100644 --- a/.gitignore +++ b/.gitignore @@ -95,3 +95,6 @@ settings.json # VisualStudio .vs/ .vscode/launch.json + +# sigma2attack +heatmap.json From f907c49ab5a51fe78188422af6c92ba8b4bd1572 Mon Sep 17 00:00:00 2001 From: Thomas Patzke Date: Sat, 13 Jun 2020 01:11:08 +0200 Subject: [PATCH 82/94] Improved test coverage * Added test case * Removed unused code --- Makefile | 7 ++++--- tools/sigma/backends/ala.py | 24 +----------------------- 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/Makefile b/Makefile index 6b142005..f981a239 100644 --- a/Makefile +++ b/Makefile @@ -32,9 +32,10 @@ test-sigmac: $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t elastalert -c tools/config/winlogbeat.yml -O alert_methods=http_post,email -O emails=test@test.invalid -O http_post_url=http://test.invalid rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t elastalert-dsl -c tools/config/winlogbeat.yml -O alert_methods=http_post,email -O emails=test@test.invalid -O http_post_url=http://test.invalid rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t ee-outliers -c tools/config/winlogbeat.yml rules/ > /dev/null - $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t es-qs -c tools/config/ecs-cloudtrail.yml rules/ > /dev/null - $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t es-rule -c tools/config/ecs-cloudtrail.yml rules/ > /dev/null - $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t kibana -c tools/config/ecs-cloudtrail.yml rules/ > /dev/null + $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t es-qs -c sysmon -c winlogbeat -O case_insensitive_whitelist=* rules/windows/process_creation > /dev/null + $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t es-qs -c tools/config/ecs-cloudtrail.yml rules/ > /dev/null + $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t es-rule -c tools/config/ecs-cloudtrail.yml rules/ > /dev/null + $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t kibana -c tools/config/ecs-cloudtrail.yml rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t xpack-watcher -c tools/config/ecs-cloudtrail.yml rules/ > /dev/null $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t elastalert -c tools/config/ecs-cloudtrail.yml rules/ > /dev/null ! $(COVERAGE) run -a --include=$(COVSCOPE) tools/sigmac -rvdI -t splunk rules/ > /dev/null diff --git a/tools/sigma/backends/ala.py b/tools/sigma/backends/ala.py index bffd4ebf..3bbbec54 100644 --- a/tools/sigma/backends/ala.py +++ b/tools/sigma/backends/ala.py @@ -33,29 +33,7 @@ from sigma.parser.modifiers.transform import SigmaContainsModifier, SigmaStartsw from .data import sysmon_schema from .exceptions import NotSupportedError -class DeepFieldMappingMixin(object): - - def fieldNameMapping(self, fieldname, value): - if isinstance(fieldname, str): - get_config = self.sigmaconfig.fieldmappings.get(fieldname) - if not get_config and '|' in fieldname: - fieldname = fieldname.split('|', 1)[0] - get_config = self.sigmaconfig.fieldmappings.get(fieldname) - if isinstance(get_config, ConditionalFieldMapping): - condition = self.sigmaconfig.fieldmappings.get(fieldname).conditions - for key, item in self.logsource.items(): - if condition.get(key) and condition.get(key, {}).get(item): - new_fieldname = condition.get(key, {}).get(item) - if any(new_fieldname): - return super().fieldNameMapping(new_fieldname[0], value) - return super().fieldNameMapping(fieldname, value) - - - def generate(self, sigmaparser): - self.logsource = sigmaparser.parsedyaml.get("logsource", {}) - return super().generate(sigmaparser) - -class AzureLogAnalyticsBackend(DeepFieldMappingMixin, SingleTextQueryBackend): +class AzureLogAnalyticsBackend(SingleTextQueryBackend): """Converts Sigma rule into Azure Log Analytics Queries.""" identifier = "ala" active = True From f5aa871e5d3c5826f0929c452ceb9696fce35df6 Mon Sep 17 00:00:00 2001 From: Brad Kish Date: Mon, 15 Jun 2020 13:14:31 -0400 Subject: [PATCH 83/94] Identifiers shared between global document and rule gets overwritten The global document defines a "selection" identifier which is also defined the individual rules. The rule identifier is getting overwritten by the global identifier. Fix by giving unique names to the global identifier. --- .../win_invoke_obfuscation_obfuscated_iex_services.yml | 4 ++-- ...rpreter_or_cobaltstrike_getsystem_service_installation.yml | 4 ++-- rules/windows/builtin/win_tap_driver_installation.yml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/rules/windows/builtin/win_invoke_obfuscation_obfuscated_iex_services.yml b/rules/windows/builtin/win_invoke_obfuscation_obfuscated_iex_services.yml index 6874d23e..e02bb5d0 100644 --- a/rules/windows/builtin/win_invoke_obfuscation_obfuscated_iex_services.yml +++ b/rules/windows/builtin/win_invoke_obfuscation_obfuscated_iex_services.yml @@ -12,7 +12,7 @@ falsepositives: - Unknown level: high detection: - selection: + selection_1: - ImagePath|re: '\$PSHome\[\s*\d{1,3}\s*\]\s*\+\s*\$PSHome\[' - ImagePath|re: '\$ShellId\[\s*\d{1,3}\s*\]\s*\+\s*\$ShellId\[' - ImagePath|re: '\$env:Public\[\s*\d{1,3}\s*\]\s*\+\s*\$env:Public\[' @@ -20,7 +20,7 @@ detection: - ImagePath|re: '\*mdr\*\W\s*\)\.Name' - ImagePath|re: '\$VerbosePreference\.ToString\(' - ImagePath|re: '\String\]\s*\$VerbosePreference' - condition: selection + condition: selection and selection_1 --- logsource: product: windows diff --git a/rules/windows/builtin/win_meterpreter_or_cobaltstrike_getsystem_service_installation.yml b/rules/windows/builtin/win_meterpreter_or_cobaltstrike_getsystem_service_installation.yml index e177530f..b230163f 100644 --- a/rules/windows/builtin/win_meterpreter_or_cobaltstrike_getsystem_service_installation.yml +++ b/rules/windows/builtin/win_meterpreter_or_cobaltstrike_getsystem_service_installation.yml @@ -12,7 +12,7 @@ tags: - attack.privilege_escalation - attack.t1134 detection: - selection: + selection_1: # meterpreter getsystem technique 1: cmd.exe /c echo 559891bb017 > \\.\pipe\5e120a - ServiceFileName|contains|all: - 'cmd' @@ -30,7 +30,7 @@ detection: - 'rundll32' - '.dll,a' - '/p:' - condition: selection + condition: selection and selection_1 fields: - ComputerName - SubjectDomainName diff --git a/rules/windows/builtin/win_tap_driver_installation.yml b/rules/windows/builtin/win_tap_driver_installation.yml index d2fbb562..42d05509 100644 --- a/rules/windows/builtin/win_tap_driver_installation.yml +++ b/rules/windows/builtin/win_tap_driver_installation.yml @@ -12,9 +12,9 @@ falsepositives: - Legitimate OpenVPN TAP insntallation level: medium detection: - selection: + selection_1: ImagePath|contains: 'tap0901' - condition: selection + condition: selection and selection_1 --- logsource: product: windows From 8d58c8f5c85ccc20c37cdbb2631e0f8c30adcb43 Mon Sep 17 00:00:00 2001 From: Brad Kish Date: Mon, 15 Jun 2020 13:18:05 -0400 Subject: [PATCH 84/94] Fix logsource field name from service->category The rule win_invoke_obfuscation_obfuscated_iex_commandline has the wrong field name for the "process_creation" tag. Rename from "service" to "category" --- .../win_invoke_obfuscation_obfuscated_iex_commandline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/windows/process_creation/win_invoke_obfuscation_obfuscated_iex_commandline.yml b/rules/windows/process_creation/win_invoke_obfuscation_obfuscated_iex_commandline.yml index 9557a02f..0ac9132e 100644 --- a/rules/windows/process_creation/win_invoke_obfuscation_obfuscated_iex_commandline.yml +++ b/rules/windows/process_creation/win_invoke_obfuscation_obfuscated_iex_commandline.yml @@ -8,8 +8,8 @@ tags: - attack.defense_evasion - attack.t1027 logsource: + category: process_creation product: windows - service: process_creation detection: selection: - CommandLine|re: '\$PSHome\[\s*\d{1,3}\s*\]\s*\+\s*\$PSHome\[' From 422b2bffd77b217e6cec9a67c496b0aa44711ece Mon Sep 17 00:00:00 2001 From: Brad Kish Date: Mon, 15 Jun 2020 13:38:18 -0400 Subject: [PATCH 85/94] Fix rules with incorrect escaping of wildcars A backslash before a wildcard needs to be escaped with another backslash. --- rules/windows/malware/win_mal_flowcloud.yml | 2 +- rules/windows/process_creation/win_apt_mustangpanda.yml | 2 +- rules/windows/process_creation/win_apt_wocao.yml | 2 +- rules/windows/sysmon/sysmon_susp_adsi_cache_usage.yml | 2 +- .../sysmon/sysmon_susp_office_dotnet_assembly_dll_load.yml | 2 +- .../sysmon_susp_procexplorer_driver_created_in_tmp_folder.yml | 2 +- .../windows/sysmon/sysmon_suspicious_keyboard_layout_load.yml | 4 ++-- .../windows/sysmon/sysmon_svchost_dll_search_order_hijack.yml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/rules/windows/malware/win_mal_flowcloud.yml b/rules/windows/malware/win_mal_flowcloud.yml index 566fce0d..37e315f9 100644 --- a/rules/windows/malware/win_mal_flowcloud.yml +++ b/rules/windows/malware/win_mal_flowcloud.yml @@ -21,7 +21,7 @@ detection: - 'HKLM\HARDWARE\{804423C2-F490-4ac3-BFA5-13DEDE63A71A}' - 'HKLM\HARDWARE\{A5124AF5-DF23-49bf-B0ED-A18ED3DEA027}' - 'HKLM\HARDWARE\{2DB80286-1784-48b5-A751-B6ED1F490303}' - - 'HKLM\SYSTEM\Setup\PrintResponsor\*' + - 'HKLM\SYSTEM\Setup\PrintResponsor\\*' condition: selection falsepositives: - Unknown diff --git a/rules/windows/process_creation/win_apt_mustangpanda.yml b/rules/windows/process_creation/win_apt_mustangpanda.yml index 57990579..28fa6692 100644 --- a/rules/windows/process_creation/win_apt_mustangpanda.yml +++ b/rules/windows/process_creation/win_apt_mustangpanda.yml @@ -16,7 +16,7 @@ detection: CommandLine: - '*Temp\wtask.exe /create*' - '*%windir:~-3,1%%PUBLIC:~-9,1%*' - - '*/E:vbscript * C:\Users\*.txt" /F' + - '*/E:vbscript * C:\Users\\*.txt" /F' - '*/tn "Security Script *' - '*%windir:~-1,1%*' selection2: diff --git a/rules/windows/process_creation/win_apt_wocao.yml b/rules/windows/process_creation/win_apt_wocao.yml index e0332f64..57b7dc9d 100644 --- a/rules/windows/process_creation/win_apt_wocao.yml +++ b/rules/windows/process_creation/win_apt_wocao.yml @@ -37,5 +37,5 @@ detection: - ' -exec bypass -enc JgAg' - 'type *keepass\KeePass.config.xml' - 'iie.exe iie.txt' - - 'reg query HKEY_CURRENT_USER\Software\*\PuTTY\Sessions\' + - 'reg query HKEY_CURRENT_USER\Software\\*\PuTTY\Sessions\' condition: selection \ No newline at end of file diff --git a/rules/windows/sysmon/sysmon_susp_adsi_cache_usage.yml b/rules/windows/sysmon/sysmon_susp_adsi_cache_usage.yml index 884e53c3..e91cd537 100644 --- a/rules/windows/sysmon/sysmon_susp_adsi_cache_usage.yml +++ b/rules/windows/sysmon/sysmon_susp_adsi_cache_usage.yml @@ -17,7 +17,7 @@ logsource: detection: selection_1: EventID: 11 - TargetFilename: '*\Local\Microsoft\Windows\SchCache\*.sch' + TargetFilename: '*\Local\Microsoft\Windows\SchCache\\*.sch' selection_2: Image|contains: - 'C:\windows\system32\svchost.exe' diff --git a/rules/windows/sysmon/sysmon_susp_office_dotnet_assembly_dll_load.yml b/rules/windows/sysmon/sysmon_susp_office_dotnet_assembly_dll_load.yml index 1c63a4c5..47036525 100644 --- a/rules/windows/sysmon/sysmon_susp_office_dotnet_assembly_dll_load.yml +++ b/rules/windows/sysmon/sysmon_susp_office_dotnet_assembly_dll_load.yml @@ -21,7 +21,7 @@ detection: - '*\excel.exe' - '*\outlook.exe' ImageLoaded: - - 'C:\Windows\assembly\*' + - 'C:\Windows\assembly\\*' condition: selection falsepositives: - Alerts on legitimate macro usage as well, will need to filter as appropriate diff --git a/rules/windows/sysmon/sysmon_susp_procexplorer_driver_created_in_tmp_folder.yml b/rules/windows/sysmon/sysmon_susp_procexplorer_driver_created_in_tmp_folder.yml index 982cf835..b73320b3 100644 --- a/rules/windows/sysmon/sysmon_susp_procexplorer_driver_created_in_tmp_folder.yml +++ b/rules/windows/sysmon/sysmon_susp_procexplorer_driver_created_in_tmp_folder.yml @@ -15,7 +15,7 @@ logsource: detection: selection_1: EventID: 11 - TargetFilename: '*\AppData\Local\Temp\*\PROCEXP152.sys' + TargetFilename: '*\AppData\Local\Temp\\*\PROCEXP152.sys' selection_2: Image|contains: - '*\procexp64.exe' diff --git a/rules/windows/sysmon/sysmon_suspicious_keyboard_layout_load.yml b/rules/windows/sysmon/sysmon_suspicious_keyboard_layout_load.yml index 35ffca37..0016d157 100644 --- a/rules/windows/sysmon/sysmon_suspicious_keyboard_layout_load.yml +++ b/rules/windows/sysmon/sysmon_suspicious_keyboard_layout_load.yml @@ -16,8 +16,8 @@ detection: selection_registry: EventID: 13 TargetObject: - - '*\Keyboard Layout\Preload\*' - - '*\Keyboard Layout\Substitutes\*' + - '*\Keyboard Layout\Preload\\*' + - '*\Keyboard Layout\Substitutes\\*' Details|contains: - 00000429 # Persian (Iran) - 00050429 # Persian (Iran) diff --git a/rules/windows/sysmon/sysmon_svchost_dll_search_order_hijack.yml b/rules/windows/sysmon/sysmon_svchost_dll_search_order_hijack.yml index 9dbbf96a..f06a1e20 100644 --- a/rules/windows/sysmon/sysmon_svchost_dll_search_order_hijack.yml +++ b/rules/windows/sysmon/sysmon_svchost_dll_search_order_hijack.yml @@ -28,7 +28,7 @@ detection: - '*\wlbsctrl.dll' filter: ImageLoaded: - - 'C:\Windows\WinSxS\*' + - 'C:\Windows\WinSxS\\*' condition: selection and not filter falsepositives: - Pentest From f196046b3d366774b8f96c4d7d26120d2d0667ce Mon Sep 17 00:00:00 2001 From: Brad Kish Date: Mon, 15 Jun 2020 13:39:50 -0400 Subject: [PATCH 86/94] Fix match for double-backslash To match a double-backslash you actually need three backslashes, since two backslashes gets reduced to one. --- rules/windows/process_creation/win_net_enum.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/windows/process_creation/win_net_enum.yml b/rules/windows/process_creation/win_net_enum.yml index 5df7c054..7cc35686 100644 --- a/rules/windows/process_creation/win_net_enum.yml +++ b/rules/windows/process_creation/win_net_enum.yml @@ -21,7 +21,7 @@ detection: - '\net1.exe' CommandLine|contains: 'view' filter: - CommandLine|contains: '\\' + CommandLine|contains: \\\ condition: selection and not filter fields: - ComputerName From a9c6fa904f56415d568918553353ee26ed6eccb3 Mon Sep 17 00:00:00 2001 From: Brad Kish Date: Mon, 15 Jun 2020 13:52:12 -0400 Subject: [PATCH 87/94] Rule lists extra Sysmon ID (11). Should just match registry events (12-14) Remove extraneous event ID 11. It will never match. --- .../sysmon/sysmon_logon_scripts_userinitmprlogonscript.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/rules/windows/sysmon/sysmon_logon_scripts_userinitmprlogonscript.yml b/rules/windows/sysmon/sysmon_logon_scripts_userinitmprlogonscript.yml index 3aaa7490..4efaaca3 100644 --- a/rules/windows/sysmon/sysmon_logon_scripts_userinitmprlogonscript.yml +++ b/rules/windows/sysmon/sysmon_logon_scripts_userinitmprlogonscript.yml @@ -44,7 +44,6 @@ logsource: detection: create_selection_reg: EventID: - - 11 - 12 - 13 - 14 From dfae2a6df6f5bbc90a7b476c22fc9c8fedab47e9 Mon Sep 17 00:00:00 2001 From: Brad Kish Date: Mon, 15 Jun 2020 13:54:02 -0400 Subject: [PATCH 88/94] Rule needs endwith, not exact match. Fix ImageLoaded filter to match with endswith, rather than exact match. --- .../sysmon_wmi_persistence_commandline_event_consumer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/windows/sysmon/sysmon_wmi_persistence_commandline_event_consumer.yml b/rules/windows/sysmon/sysmon_wmi_persistence_commandline_event_consumer.yml index 9349ff72..c87d2af6 100644 --- a/rules/windows/sysmon/sysmon_wmi_persistence_commandline_event_consumer.yml +++ b/rules/windows/sysmon/sysmon_wmi_persistence_commandline_event_consumer.yml @@ -16,7 +16,7 @@ detection: selection: EventID: 7 Image: 'C:\Windows\System32\wbem\WmiPrvSE.exe' - ImageLoaded: 'wbemcons.dll' + ImageLoaded|endswith: '\wbemcons.dll' condition: selection falsepositives: - Unknown (data set is too small; further testing needed) From 0fbfcc6ba9a1b5c3c90447767e7b7446de2e39b0 Mon Sep 17 00:00:00 2001 From: Ivan Kirillov Date: Tue, 16 Jun 2020 14:46:08 -0600 Subject: [PATCH 89/94] Initial round of subtechnique updates --- .../cloud/aws_cloudtrail_disable_logging.yml | 23 +++--- rules/cloud/aws_config_disable_recording.yml | 19 ++--- rules/cloud/aws_ec2_startup_script_change.yml | 1 + rules/cloud/aws_guardduty_disruption.yml | 1 + .../auditd/lnx_auditd_alter_bash_profile.yml | 1 + .../lnx_auditd_auditing_config_change.yml | 1 + .../lnx_auditd_logging_config_change.yml | 1 + rules/linux/auditd/lnx_auditd_web_rce.yml | 1 + rules/linux/auditd/lnx_data_compressed.yml | 4 +- rules/linux/lnx_pers_systemd_reload.yml | 1 + rules/linux/lnx_shell_clear_cmd_history.yml | 3 +- .../cisco/aaa/cisco_cli_clear_logs.yml | 2 + .../cisco/aaa/cisco_cli_collect_data.yml | 1 + .../cisco/aaa/cisco_cli_crypto_actions.yml | 2 + .../cisco/aaa/cisco_cli_disable_logging.yml | 1 + .../cisco/aaa/cisco_cli_file_deletion.yml | 3 + .../cisco/aaa/cisco_cli_input_capture.yml | 1 + .../cisco/aaa/cisco_cli_modify_config.yml | 3 + .../cisco/aaa/cisco_cli_moving_data.yml | 2 + .../network/net_susp_dns_txt_exec_strings.yml | 11 +-- .../zeek_dce_rpc_mitre_bzar_execution.yml | 78 ++++++++++--------- .../zeek_dce_rpc_mitre_bzar_persistence.yml | 45 +++++------ ...k_http_executable_download_from_webdav.yml | 7 +- .../zeek_smb_converted_win_atsvc_task.yml | 1 + ..._smb_converted_win_impacket_secretdump.yml | 11 ++- .../zeek_smb_converted_win_lm_namedpipe.yml | 40 +++++----- .../zeek_smb_converted_win_susp_psexec.yml | 7 +- ...ransferring_files_with_credential_data.yml | 37 +++++---- rules/network/zeek/zeek_susp_kerberos_rc4.yml | 1 + .../web_cve_2018_2894_weblogic_exploit.yml | 3 +- .../builtin/win_GPO_scheduledtasks.yml | 1 + .../builtin/win_admin_share_access.yml | 1 + .../win_alert_enable_weak_encryption.yml | 7 +- .../builtin/win_alert_lsass_access.yml | 1 + .../builtin/win_alert_mimikatz_keywords.yml | 27 ++++--- rules/windows/builtin/win_alert_ruler.yml | 9 ++- .../builtin/win_apt_carbonpaper_turla.yml | 1 + rules/windows/builtin/win_apt_stonedrill.yml | 1 + .../builtin/win_apt_turla_service_png.yml | 1 + rules/windows/builtin/win_atsvc_task.yml | 1 + rules/windows/builtin/win_dcsync.yml | 5 +- .../builtin/win_disable_event_logging.yml | 7 +- .../win_dpapi_domain_backupkey_extraction.yml | 5 +- ..._dpapi_domain_masterkey_backup_attempt.yml | 3 +- rules/windows/builtin/win_hack_smbexec.yml | 4 +- .../builtin/win_impacket_secretdump.yml | 3 + rules/windows/builtin/win_lm_namedpipe.yml | 38 ++++----- .../win_lsass_access_non_system_account.yml | 3 +- .../builtin/win_mal_service_installs.yml | 4 +- .../builtin/win_mmc20_lateral_movement.yml | 28 +++---- .../windows/builtin/win_overpass_the_hash.yml | 1 + rules/windows/builtin/win_pass_the_hash.yml | 17 ++-- rules/windows/builtin/win_pass_the_hash_2.yml | 13 ++-- ...rkspwdump_clearing_hive_access_history.yml | 1 + .../builtin/win_rare_schtasks_creations.yml | 1 + .../builtin/win_rare_service_installs.yml | 1 + .../builtin/win_rdp_localhost_login.yml | 1 + .../builtin/win_rdp_reverse_tunnel.yml | 1 + ...n_register_new_logon_process_by_rubeus.yml | 3 +- .../builtin/win_remote_powershell_session.yml | 3 +- .../builtin/win_susp_add_sid_history.yml | 3 +- .../builtin/win_susp_backup_delete.yml | 1 + .../win_susp_codeintegrity_check_failure.yml | 1 + .../windows/builtin/win_susp_dhcp_config.yml | 3 +- .../builtin/win_susp_dhcp_config_failed.yml | 7 +- rules/windows/builtin/win_susp_dns_config.yml | 5 +- .../builtin/win_susp_eventlog_cleared.yml | 1 + rules/windows/builtin/win_susp_lsass_dump.yml | 1 + .../builtin/win_susp_lsass_dump_generic.yml | 3 +- .../builtin/win_susp_msmpeng_crash.yml | 1 + rules/windows/builtin/win_susp_ntlm_auth.yml | 1 + rules/windows/builtin/win_susp_psexec.yml | 10 +-- .../windows/builtin/win_susp_rc4_kerberos.yml | 1 + .../windows/builtin/win_susp_rottenpotato.yml | 1 + rules/windows/builtin/win_susp_sam_dump.yml | 1 + rules/windows/builtin/win_susp_sdelete.yml | 2 + .../win_susp_security_eventlog_cleared.yml | 1 + .../builtin/win_susp_time_modification.yml | 1 + ...uspicious_outbound_kerberos_connection.yml | 3 +- ...ith_credential_data_via_network_shares.yml | 3 + ...ileged_service_lsaregisterlogonprocess.yml | 8 +- .../builtin/win_user_driver_loaded.yml | 1 + rules/windows/malware/av_password_dumper.yml | 5 +- rules/windows/malware/av_webshell.yml | 3 +- rules/windows/other/win_defender_bypass.yml | 5 +- .../other/win_rare_schtask_creation.yml | 4 +- .../powershell_alternate_powershell_hosts.yml | 3 +- .../powershell_clear_powershell_history.yml | 1 + .../powershell_create_local_user.yml | 11 +-- .../powershell/powershell_data_compressed.yml | 6 +- .../powershell_downgrade_attack.yml | 3 +- .../powershell/powershell_exe_calling_ps.yml | 1 + .../powershell_malicious_commandlets.yml | 1 + .../powershell_malicious_keywords.yml | 1 + ...wershell_nishang_malicious_commandlets.yml | 1 + .../powershell/powershell_ntfs_ads_access.yml | 1 + .../powershell_prompt_credentials.yml | 1 + .../powershell/powershell_psattack.yml | 1 + .../powershell_remote_powershell_session.yml | 3 +- .../powershell/powershell_shellcode_b64.yml | 5 +- .../powershell_suspicious_download.yml | 1 + ...wershell_suspicious_invocation_generic.yml | 1 + ...ershell_suspicious_invocation_specific.yml | 1 + .../powershell_suspicious_keywords.yml | 1 + .../powershell_winlogon_helper_dll.yml | 10 +-- .../win_apt_apt29_thinktanks.yml | 3 +- .../process_creation/win_apt_babyshark.yml | 3 + .../win_apt_bear_activity_gtr19.yml | 1 + .../process_creation/win_apt_bluemashroom.yml | 3 +- .../process_creation/win_apt_cloudhopper.yml | 1 + .../win_apt_equationgroup_dll_u_load.yml | 1 + .../win_apt_judgement_panda_gtr19.yml | 1 + .../process_creation/win_apt_sofacy.yml | 1 + .../win_apt_tropictrooper.yml | 1 + .../win_apt_turla_comrat_may20.yml | 1 + .../win_apt_winnti_mal_hk_jan20.yml | 7 +- .../process_creation/win_apt_zxshell.yml | 1 + .../win_attrib_hiding_files.yml | 1 + .../win_change_default_file_association.yml | 11 ++- .../process_creation/win_cmdkey_recon.yml | 1 + .../win_cmstp_com_object_access.yml | 2 + .../win_control_panel_item.yml | 1 + ...g_sensitive_files_with_credential_data.yml | 4 +- .../process_creation/win_crime_fireball.yml | 1 + .../win_data_compressed_with_rar.yml | 3 +- .../win_encoded_frombase64string.yml | 1 + .../process_creation/win_encoded_iex.yml | 11 +-- .../win_etw_trace_evasion.yml | 5 +- .../win_grabbing_sensitive_hives_via_reg.yml | 5 +- .../process_creation/win_hack_koadic.yml | 3 +- .../process_creation/win_hack_rubeus.yml | 2 + rules/windows/process_creation/win_hh_chm.yml | 1 + .../process_creation/win_html_help_spawn.yml | 1 + .../process_creation/win_hwp_exploits.yml | 1 + .../win_impacket_lateralization.yml | 1 + .../win_install_reg_debugger_backdoor.yml | 3 +- .../process_creation/win_interactive_at.yml | 1 + .../process_creation/win_lethalhta.yml | 1 + .../process_creation/win_lsass_dump.yml | 4 +- .../process_creation/win_malware_notpetya.yml | 5 +- .../win_malware_script_dropper.yml | 1 + .../win_mimikatz_command_line.yml | 7 +- .../process_creation/win_mmc_spawn_shell.yml | 4 + .../process_creation/win_mshta_javascript.yml | 1 + .../win_mshta_spawn_shell.yml | 1 + .../win_netsh_allow_port_rdp.yml | 3 +- .../win_new_service_creation.yml | 5 +- .../win_non_interactive_powershell.yml | 3 +- .../process_creation/win_office_shell.yml | 1 + .../win_plugx_susp_exe_locations.yml | 6 +- .../win_possible_applocker_bypass.yml | 1 + .../win_powershell_amsi_bypass.yml | 1 + .../win_powershell_dll_execution.yml | 1 + .../win_powershell_downgrade_attack.yml | 7 +- .../win_powershell_download.yml | 1 + ...ershell_suspicious_parameter_variation.yml | 1 + .../win_powershell_xor_commandline.yml | 1 + .../win_powersploit_empire_schtasks.yml | 2 + .../win_process_dump_rundll32_comsvcs.yml | 1 + .../process_creation/win_psexesvc_start.yml | 3 +- .../win_remote_powershell_session_process.yml | 1 + .../win_run_powershell_script_from_ads.yml | 7 +- .../win_sdbinst_shim_persistence.yml | 1 + .../win_service_execution.yml | 3 +- .../win_shadow_copies_access_symlink.yml | 8 +- .../win_shadow_copies_creation.yml | 2 + .../win_shadow_copies_deletion.yml | 1 + .../win_shell_spawn_susp_program.yml | 2 + .../windows/process_creation/win_spn_enum.yml | 1 + .../process_creation/win_susp_bcdedit.yml | 2 + .../win_susp_cmd_http_appdata.yml | 5 +- .../win_susp_compression_params.yml | 1 + .../win_susp_comsvcs_procdump.yml | 1 + .../win_susp_control_dll_load.yml | 2 + .../win_susp_copy_lateral_movement.yml | 11 +-- .../win_susp_crackmapexec_execution.yml | 2 + ...sp_crackmapexec_powershell_obfuscation.yml | 1 + .../process_creation/win_susp_csc_folder.yml | 5 +- ...susp_direct_asep_reg_keys_modification.yml | 1 + .../win_susp_double_extension.yml | 8 +- .../win_susp_eventlog_clear.yml | 5 +- .../win_susp_execution_path_webserver.yml | 1 + .../win_susp_file_characteristics.yml | 1 + .../win_susp_fsutil_usage.yml | 3 +- .../windows/process_creation/win_susp_gup.yml | 1 + .../win_susp_iss_module_install.yml | 1 + .../win_susp_net_execution.yml | 1 + .../win_susp_netsh_dll_persistence.yml | 3 +- .../process_creation/win_susp_ntdsutil.yml | 1 + .../win_susp_outlook_temp.yml | 1 + .../win_susp_powershell_empire_launch.yml | 5 +- .../win_susp_powershell_empire_uac_bypass.yml | 1 + .../win_susp_powershell_enc_cmd.yml | 5 +- .../win_susp_powershell_hidden_b64_cmd.yml | 1 + .../win_susp_powershell_parent_combo.yml | 1 + .../process_creation/win_susp_procdump.yml | 1 + .../process_creation/win_susp_ps_appdata.yml | 1 + .../win_susp_ps_downloadfile.yml | 3 +- .../win_susp_rasdial_activity.yml | 1 + .../win_susp_regsvr32_anomalies.yml | 1 + .../win_susp_rundll32_activity.yml | 1 + .../win_susp_rundll32_by_ordinal.yml | 1 + .../win_susp_schtask_creation.yml | 1 + .../win_susp_script_execution.yml | 1 + .../win_susp_service_path_modification.yml | 1 + .../win_susp_tscon_rdp_redirect.yml | 1 + .../win_task_folder_evasion.yml | 5 +- .../process_creation/win_uac_cmstp.yml | 4 +- .../process_creation/win_uac_fodhelper.yml | 1 + .../process_creation/win_uac_wsreset.yml | 1 + .../win_webshell_detection.yml | 1 + .../process_creation/win_webshell_spawn.yml | 1 + .../win_win10_sched_task_0day.yml | 1 + ..._wmi_backdoor_exchange_transport_agent.yml | 3 +- .../win_wmi_spwns_powershell.yml | 1 + .../win_wsreset_uac_bypass.yml | 3 +- ...sysmon_alternate_powershell_hosts_pipe.yml | 7 +- .../sysmon_asep_reg_keys_modification.yml | 1 + .../sysmon/sysmon_cred_dump_lsass_access.yml | 4 +- .../sysmon_cred_dump_tools_dropped_files.yml | 7 +- .../sysmon_cred_dump_tools_named_pipes.yml | 3 + .../windows/sysmon/sysmon_dhcp_calloutdll.yml | 4 +- ...y_events_logging_adding_reg_key_minint.yml | 5 +- .../sysmon/sysmon_ghostpack_safetykatz.yml | 1 + .../sysmon/sysmon_in_memory_powershell.yml | 1 + .../windows/sysmon/sysmon_invoke_phantom.yml | 3 +- rules/windows/sysmon/sysmon_lsass_memdump.yml | 5 +- ...sysmon_lsass_memory_dump_file_creation.yml | 1 + .../sysmon_malware_backconnect_ports.yml | 3 +- .../sysmon_mimikatz_inmemory_detection.yml | 4 + .../sysmon/sysmon_mimikatz_trough_winrm.yml | 2 + .../sysmon_narrator_feedback_persistance.yml | 1 + ..._dll_added_to_appcertdlls_registry_key.yml | 8 +- ...dll_added_to_appinit_dlls_registry_key.yml | 13 ++-- .../sysmon/sysmon_password_dumper_lsass.yml | 6 +- .../sysmon/sysmon_possible_dns_rebinding.yml | 10 +-- ..._service_registry_permissions_weakness.yml | 1 + ...sysmon_powershell_execution_moduleload.yml | 3 +- .../sysmon_powershell_exploit_scripts.yml | 5 +- .../sysmon_powershell_network_connection.yml | 4 +- .../sysmon/sysmon_quarkspw_filedump.yml | 5 +- .../sysmon/sysmon_rdp_reverse_tunnel.yml | 1 + ...ysmon_registry_persistence_key_linking.yml | 1 + ...smon_registry_persistence_search_order.yml | 1 + ...mon_registry_trust_record_modification.yml | 1 + .../sysmon_regsvr32_network_activity.yml | 5 +- ...smon_remote_powershell_session_network.yml | 3 +- .../sysmon_rundll32_net_connections.yml | 3 +- .../sysmon/sysmon_susp_desktop_ini.yml | 1 + .../sysmon/sysmon_susp_download_run_key.yml | 5 +- .../sysmon/sysmon_susp_driver_load.yml | 1 + .../windows/sysmon/sysmon_susp_image_load.yml | 1 + .../sysmon/sysmon_susp_lsass_dll_load.yml | 5 +- ...n_susp_office_dotnet_assembly_dll_load.yml | 1 + ...sysmon_susp_office_dotnet_clr_dll_load.yml | 1 + ...sysmon_susp_office_dotnet_gac_dll_load.yml | 1 + .../sysmon_susp_office_dsparse_dll_load.yml | 1 + .../sysmon_susp_office_kerberos_dll_load.yml | 1 + .../sysmon_susp_powershell_rundll32.yml | 2 + ...cexplorer_driver_created_in_tmp_folder.yml | 1 + .../sysmon_susp_reg_persist_explorer_run.yml | 3 +- .../sysmon/sysmon_susp_run_key_img_folder.yml | 3 +- .../sysmon/sysmon_susp_service_installed.yml | 1 + .../sysmon_susp_winword_vbadll_load.yml | 1 + ...sysmon_suspicious_dbghelp_dbgcore_load.yml | 7 +- ...uspicious_outbound_kerberos_connection.yml | 3 +- ...sysmon_svchost_dll_search_order_hijack.yml | 8 +- .../sysmon/sysmon_uac_bypass_eventvwr.yml | 1 + .../sysmon/sysmon_uac_bypass_sdclt.yml | 1 + ...ysmon_unsigned_image_loaded_into_lsass.yml | 1 + .../sysmon_webshell_creation_detect.yml | 1 + .../sysmon/sysmon_win_reg_persistence.yml | 1 + .../sysmon/sysmon_wmi_event_subscription.yml | 1 + ...persistence_commandline_event_consumer.yml | 3 +- ...ersistence_script_event_consumer_write.yml | 3 +- .../sysmon/sysmon_wmi_susp_scripting.yml | 5 +- 276 files changed, 695 insertions(+), 398 deletions(-) diff --git a/rules/cloud/aws_cloudtrail_disable_logging.yml b/rules/cloud/aws_cloudtrail_disable_logging.yml index 61b4cdb2..e7df801d 100644 --- a/rules/cloud/aws_cloudtrail_disable_logging.yml +++ b/rules/cloud/aws_cloudtrail_disable_logging.yml @@ -5,20 +5,21 @@ author: vitaliy0x1 date: 2020/01/21 description: Detects disabling, deleting and updating of a Trail references: - - https://docs.aws.amazon.com/awscloudtrail/latest/userguide/best-practices-security.html + - https://docs.aws.amazon.com/awscloudtrail/latest/userguide/best-practices-security.html logsource: - service: cloudtrail + service: cloudtrail detection: - selection_source: - - eventSource: cloudtrail.amazonaws.com - events: - - eventName: - - StopLogging - - UpdateTrail - - DeleteTrail - condition: selection_source AND events + selection_source: + - eventSource: cloudtrail.amazonaws.com + events: + - eventName: + - StopLogging + - UpdateTrail + - DeleteTrail + condition: selection_source AND events level: medium falsepositives: - Valid change in a Trail tags: - - attack.t1089 + - attack.t1089 + - attack.t1562.001 diff --git a/rules/cloud/aws_config_disable_recording.yml b/rules/cloud/aws_config_disable_recording.yml index cb0fc0a7..8eebaa67 100644 --- a/rules/cloud/aws_config_disable_recording.yml +++ b/rules/cloud/aws_config_disable_recording.yml @@ -5,17 +5,18 @@ author: vitaliy0x1 date: 2020/01/21 description: Detects AWS Config Service disabling logsource: - service: cloudtrail + service: cloudtrail detection: - selection_source: - - eventSource: config.amazonaws.com - events: - - eventName: - - DeleteDeliveryChannel - - StopConfigurationRecorder - condition: selection_source AND events + selection_source: + - eventSource: config.amazonaws.com + events: + - eventName: + - DeleteDeliveryChannel + - StopConfigurationRecorder + condition: selection_source AND events level: high falsepositives: - Valid change in AWS Config Service tags: - - attack.t1089 + - attack.t1089 + - attack.t1562.001 diff --git a/rules/cloud/aws_ec2_startup_script_change.yml b/rules/cloud/aws_ec2_startup_script_change.yml index dccb22f0..7edcff0b 100644 --- a/rules/cloud/aws_ec2_startup_script_change.yml +++ b/rules/cloud/aws_ec2_startup_script_change.yml @@ -21,3 +21,4 @@ falsepositives: - Valid changes to the startup script tags: - attack.t1064 + - attack.t1059 diff --git a/rules/cloud/aws_guardduty_disruption.yml b/rules/cloud/aws_guardduty_disruption.yml index 61664662..7491d4b2 100644 --- a/rules/cloud/aws_guardduty_disruption.yml +++ b/rules/cloud/aws_guardduty_disruption.yml @@ -19,3 +19,4 @@ falsepositives: - Valid change in the GuardDuty (e.g. to ignore internal scanners) tags: - attack.t1089 + - attack.t1562.001 diff --git a/rules/linux/auditd/lnx_auditd_alter_bash_profile.yml b/rules/linux/auditd/lnx_auditd_alter_bash_profile.yml index 9094ded8..dff6bbf3 100644 --- a/rules/linux/auditd/lnx_auditd_alter_bash_profile.yml +++ b/rules/linux/auditd/lnx_auditd_alter_bash_profile.yml @@ -9,6 +9,7 @@ tags: - attack.s0003 - attack.t1156 - attack.persistence + - attack.t1546.004 author: Peter Matkovski logsource: product: linux diff --git a/rules/linux/auditd/lnx_auditd_auditing_config_change.yml b/rules/linux/auditd/lnx_auditd_auditing_config_change.yml index 1aaa844e..d9fb2e40 100644 --- a/rules/linux/auditd/lnx_auditd_auditing_config_change.yml +++ b/rules/linux/auditd/lnx_auditd_auditing_config_change.yml @@ -11,6 +11,7 @@ references: tags: - attack.defense_evasion - attack.t1054 + - attack.t1562.006 author: Mikhail Larin, oscd.community status: experimental date: 2019/10/25 diff --git a/rules/linux/auditd/lnx_auditd_logging_config_change.yml b/rules/linux/auditd/lnx_auditd_logging_config_change.yml index 4140aca7..b456805b 100644 --- a/rules/linux/auditd/lnx_auditd_logging_config_change.yml +++ b/rules/linux/auditd/lnx_auditd_logging_config_change.yml @@ -10,6 +10,7 @@ references: tags: - attack.defense_evasion - attack.t1054 + - attack.t1562.006 author: Mikhail Larin, oscd.community status: experimental date: 2019/10/25 diff --git a/rules/linux/auditd/lnx_auditd_web_rce.yml b/rules/linux/auditd/lnx_auditd_web_rce.yml index 28068f7a..2c537ddf 100644 --- a/rules/linux/auditd/lnx_auditd_web_rce.yml +++ b/rules/linux/auditd/lnx_auditd_web_rce.yml @@ -5,6 +5,7 @@ description: Detects posible command execution by web application/web shell tags: - attack.persistence - attack.t1100 + - attack.t1505.003 references: - personal experience author: Ilyas Ochkov, Beyu Denis, oscd.community diff --git a/rules/linux/auditd/lnx_data_compressed.yml b/rules/linux/auditd/lnx_data_compressed.yml index e22fc0d4..e923e8ec 100644 --- a/rules/linux/auditd/lnx_data_compressed.yml +++ b/rules/linux/auditd/lnx_data_compressed.yml @@ -1,8 +1,7 @@ title: Data Compressed id: a3b5e3e9-1b49-4119-8b8e-0344a01f21ee status: experimental -description: An adversary may compress data (e.g., sensitive documents) that is collected prior to exfiltration in order to make it portable and minimize the amount - of data sent over the network +description: An adversary may compress data (e.g., sensitive documents) that is collected prior to exfiltration in order to make it portable and minimize the amount of data sent over the network author: Timur Zinniatullin, oscd.community date: 2019/10/21 modified: 2019/11/04 @@ -30,3 +29,4 @@ level: low tags: - attack.exfiltration - attack.t1002 + - attack.t1560 diff --git a/rules/linux/lnx_pers_systemd_reload.yml b/rules/linux/lnx_pers_systemd_reload.yml index 3cb5c916..326b28b3 100644 --- a/rules/linux/lnx_pers_systemd_reload.yml +++ b/rules/linux/lnx_pers_systemd_reload.yml @@ -5,6 +5,7 @@ status: experimental tags: - attack.persistence - attack.t1501 + - attack.t1543.002 author: Jakob Weinzettl, oscd.community date: 2019/09/23 logsource: diff --git a/rules/linux/lnx_shell_clear_cmd_history.yml b/rules/linux/lnx_shell_clear_cmd_history.yml index 97379f6a..68e9773c 100644 --- a/rules/linux/lnx_shell_clear_cmd_history.yml +++ b/rules/linux/lnx_shell_clear_cmd_history.yml @@ -22,7 +22,7 @@ detection: keywords: - 'rm *bash_history' - 'echo "" > *bash_history' - - 'cat /dev/null > *bash_history' + - 'cat /dev/null > *bash_history' - 'ln -sf /dev/null *bash_history' - 'truncate -s0 *bash_history' # - 'unset HISTFILE' # prone to false positives @@ -38,3 +38,4 @@ level: high tags: - attack.defense_evasion - attack.t1146 + - attack.t1551.003 diff --git a/rules/network/cisco/aaa/cisco_cli_clear_logs.yml b/rules/network/cisco/aaa/cisco_cli_clear_logs.yml index 457744c3..244bdead 100644 --- a/rules/network/cisco/aaa/cisco_cli_clear_logs.yml +++ b/rules/network/cisco/aaa/cisco_cli_clear_logs.yml @@ -11,6 +11,8 @@ tags: - attack.defense_evasion - attack.t1146 - attack.t1070 + - attack.t1551.003 + - attack.t1551 logsource: product: cisco service: aaa diff --git a/rules/network/cisco/aaa/cisco_cli_collect_data.yml b/rules/network/cisco/aaa/cisco_cli_collect_data.yml index 99a6378a..9944274b 100644 --- a/rules/network/cisco/aaa/cisco_cli_collect_data.yml +++ b/rules/network/cisco/aaa/cisco_cli_collect_data.yml @@ -17,6 +17,7 @@ tags: - attack.t1003 - attack.t1081 - attack.t1005 + - attack.t1552.001 logsource: product: cisco service: aaa diff --git a/rules/network/cisco/aaa/cisco_cli_crypto_actions.yml b/rules/network/cisco/aaa/cisco_cli_crypto_actions.yml index a032c9d4..81e1a3a1 100644 --- a/rules/network/cisco/aaa/cisco_cli_crypto_actions.yml +++ b/rules/network/cisco/aaa/cisco_cli_crypto_actions.yml @@ -12,6 +12,8 @@ tags: - attack.defense_evasion - attack.t1130 - attack.t1145 + - attack.t1553.004 + - attack.t1552.004 logsource: product: cisco service: aaa diff --git a/rules/network/cisco/aaa/cisco_cli_disable_logging.yml b/rules/network/cisco/aaa/cisco_cli_disable_logging.yml index b81e265b..4bc95584 100644 --- a/rules/network/cisco/aaa/cisco_cli_disable_logging.yml +++ b/rules/network/cisco/aaa/cisco_cli_disable_logging.yml @@ -9,6 +9,7 @@ date: 2019/08/11 tags: - attack.defense_evasion - attack.t1089 + - attack.t1562.001 logsource: product: cisco service: aaa diff --git a/rules/network/cisco/aaa/cisco_cli_file_deletion.yml b/rules/network/cisco/aaa/cisco_cli_file_deletion.yml index cc6155e1..ec6b4e1e 100644 --- a/rules/network/cisco/aaa/cisco_cli_file_deletion.yml +++ b/rules/network/cisco/aaa/cisco_cli_file_deletion.yml @@ -14,6 +14,9 @@ tags: - attack.t1107 - attack.t1488 - attack.t1487 + - attack.t1561.002 + - attack.t1551.004 + - attack.t1561.001 logsource: product: cisco service: aaa diff --git a/rules/network/cisco/aaa/cisco_cli_input_capture.yml b/rules/network/cisco/aaa/cisco_cli_input_capture.yml index 51467f57..d1bc266a 100644 --- a/rules/network/cisco/aaa/cisco_cli_input_capture.yml +++ b/rules/network/cisco/aaa/cisco_cli_input_capture.yml @@ -12,6 +12,7 @@ tags: - attack.credential_access - attack.t1139 - attack.t1056 + - attack.t1552.003 logsource: product: cisco service: aaa diff --git a/rules/network/cisco/aaa/cisco_cli_modify_config.yml b/rules/network/cisco/aaa/cisco_cli_modify_config.yml index bc11ecaf..6f98513e 100644 --- a/rules/network/cisco/aaa/cisco_cli_modify_config.yml +++ b/rules/network/cisco/aaa/cisco_cli_modify_config.yml @@ -16,6 +16,9 @@ tags: - attack.t1100 - attack.t1168 - attack.t1490 + - attack.t1565.002 + - attack.t1505 + - attack.t1053 logsource: product: cisco service: aaa diff --git a/rules/network/cisco/aaa/cisco_cli_moving_data.yml b/rules/network/cisco/aaa/cisco_cli_moving_data.yml index f9aa4c84..924588a6 100644 --- a/rules/network/cisco/aaa/cisco_cli_moving_data.yml +++ b/rules/network/cisco/aaa/cisco_cli_moving_data.yml @@ -19,6 +19,8 @@ tags: - attack.t1105 - attack.t1492 - attack.t1002 + - attack.t1560 + - attack.t1565.001 logsource: product: cisco service: aaa diff --git a/rules/network/net_susp_dns_txt_exec_strings.yml b/rules/network/net_susp_dns_txt_exec_strings.yml index 42ee5e22..95492f1b 100644 --- a/rules/network/net_susp_dns_txt_exec_strings.yml +++ b/rules/network/net_susp_dns_txt_exec_strings.yml @@ -7,17 +7,18 @@ references: - https://github.com/samratashok/nishang/blob/master/Backdoors/DNS_TXT_Pwnage.ps1 tags: - attack.t1071 + - attack.t1071.004 author: Markus Neis date: 2018/08/08 logsource: category: dns detection: selection: - record_type: 'TXT' - answer: - - '*IEX*' - - '*Invoke-Expression*' - - '*cmd.exe*' + record_type: 'TXT' + answer: + - '*IEX*' + - '*Invoke-Expression*' + - '*cmd.exe*' condition: selection falsepositives: - Unknown diff --git a/rules/network/zeek/zeek_dce_rpc_mitre_bzar_execution.yml b/rules/network/zeek/zeek_dce_rpc_mitre_bzar_execution.yml index 4e79ed02..141a67dd 100644 --- a/rules/network/zeek/zeek_dce_rpc_mitre_bzar_execution.yml +++ b/rules/network/zeek/zeek_dce_rpc_mitre_bzar_execution.yml @@ -6,46 +6,48 @@ date: 2020/03/19 references: - https://github.com/mitre-attack/bzar#indicators-for-attck-execution tags: - - attack.execution - - attack.t1035 - - attack.t1047 - - attack.t1053 + - attack.execution + - attack.t1035 + - attack.t1047 + - attack.t1053 + - attack.t1053.002 + - attack.t1569.002 logsource: - product: zeek - service: dce_rpc + product: zeek + service: dce_rpc detection: - op1: - endpoint: 'JobAdd' - operation: 'atsvc' - op2: - endpoint: 'ITaskSchedulerService' - operation: 'SchRpcEnableTask' - op3: - endpoint: 'ITaskSchedulerService' - operation: 'SchRpcRegisterTask' - op4: - endpoint: 'ITaskSchedulerService' - operation: 'SchRpcRun' - op5: - endpoint: 'IWbemServices' - operation: 'ExecMethod' - op6: - endpoint: 'IWbemServices' - operation: 'ExecMethodAsync' - op7: - endpoint: 'svcctl' - operation: 'CreateServiceA' - op8: - endpoint: 'svcctl' - operation: 'CreateServiceW' - op9: - endpoint: 'svcctl' - operation: 'StartServiceA' - op10: - endpoint: 'svcctl' - operation: 'StartServiceW' - condition: 1 of them + op1: + endpoint: 'JobAdd' + operation: 'atsvc' + op2: + endpoint: 'ITaskSchedulerService' + operation: 'SchRpcEnableTask' + op3: + endpoint: 'ITaskSchedulerService' + operation: 'SchRpcRegisterTask' + op4: + endpoint: 'ITaskSchedulerService' + operation: 'SchRpcRun' + op5: + endpoint: 'IWbemServices' + operation: 'ExecMethod' + op6: + endpoint: 'IWbemServices' + operation: 'ExecMethodAsync' + op7: + endpoint: 'svcctl' + operation: 'CreateServiceA' + op8: + endpoint: 'svcctl' + operation: 'CreateServiceW' + op9: + endpoint: 'svcctl' + operation: 'StartServiceA' + op10: + endpoint: 'svcctl' + operation: 'StartServiceW' + condition: 1 of them falsepositives: - 'Windows administrator tasks or troubleshooting' - 'Windows management scripts or software' -level: medium \ No newline at end of file +level: medium diff --git a/rules/network/zeek/zeek_dce_rpc_mitre_bzar_persistence.yml b/rules/network/zeek/zeek_dce_rpc_mitre_bzar_persistence.yml index 3cce80d4..4dd5fc5d 100644 --- a/rules/network/zeek/zeek_dce_rpc_mitre_bzar_persistence.yml +++ b/rules/network/zeek/zeek_dce_rpc_mitre_bzar_persistence.yml @@ -8,30 +8,31 @@ references: tags: - attack.persistence - attack.t1004 + - attack.t1547.004 logsource: - product: zeek - service: dce_rpc + product: zeek + service: dce_rpc detection: - op1: - endpoint: 'spoolss' - operation: 'RpcAddMonitor' - op2: - endpoint: 'spoolss' - operation: 'RpcAddPrintProcessor' - op3: - endpoint: 'IRemoteWinspool' - operation: 'RpcAsyncAddMonitor' - op4: - endpoint: 'IRemoteWinspool' - operation: 'RpcAsyncAddPrintProcessor' - op5: - endpoint: 'ISecLogon' - operation: 'SeclCreateProcessWithLogonW' - op6: - endpoint: 'ISecLogon' - operation: 'SeclCreateProcessWithLogonExW' - condition: 1 of them + op1: + endpoint: 'spoolss' + operation: 'RpcAddMonitor' + op2: + endpoint: 'spoolss' + operation: 'RpcAddPrintProcessor' + op3: + endpoint: 'IRemoteWinspool' + operation: 'RpcAsyncAddMonitor' + op4: + endpoint: 'IRemoteWinspool' + operation: 'RpcAsyncAddPrintProcessor' + op5: + endpoint: 'ISecLogon' + operation: 'SeclCreateProcessWithLogonW' + op6: + endpoint: 'ISecLogon' + operation: 'SeclCreateProcessWithLogonExW' + condition: 1 of them falsepositives: - 'Windows administrator tasks or troubleshooting' - 'Windows management scripts or software' -level: medium \ No newline at end of file +level: medium diff --git a/rules/network/zeek/zeek_http_executable_download_from_webdav.yml b/rules/network/zeek/zeek_http_executable_download_from_webdav.yml index 47cfdcbf..55bc7898 100644 --- a/rules/network/zeek/zeek_http_executable_download_from_webdav.yml +++ b/rules/network/zeek/zeek_http_executable_download_from_webdav.yml @@ -8,9 +8,10 @@ references: tags: - attack.command_and_control - attack.t1043 + - attack.t1571 logsource: - product: zeek - service: http + product: zeek + service: http date: 2020/05/01 detection: selection_webdav: @@ -23,4 +24,4 @@ detection: falsepositives: - unknown level: medium -status: experimental \ No newline at end of file +status: experimental diff --git a/rules/network/zeek/zeek_smb_converted_win_atsvc_task.yml b/rules/network/zeek/zeek_smb_converted_win_atsvc_task.yml index 17a3704f..12e1eb4d 100644 --- a/rules/network/zeek/zeek_smb_converted_win_atsvc_task.yml +++ b/rules/network/zeek/zeek_smb_converted_win_atsvc_task.yml @@ -11,6 +11,7 @@ tags: - attack.t1053 - car.2013-05-004 - car.2015-04-001 + - attack.t1053.002 logsource: product: zeek service: smb_files diff --git a/rules/network/zeek/zeek_smb_converted_win_impacket_secretdump.yml b/rules/network/zeek/zeek_smb_converted_win_impacket_secretdump.yml index 16e2f318..4a7fe93a 100644 --- a/rules/network/zeek/zeek_smb_converted_win_impacket_secretdump.yml +++ b/rules/network/zeek/zeek_smb_converted_win_impacket_secretdump.yml @@ -8,14 +8,17 @@ references: tags: - attack.credential_access - attack.t1003 + - attack.t1003.002 + - attack.t1003.004 + - attack.t1003.003 logsource: product: zeek service: smb_files detection: - selection: - path: '\\*ADMIN$' - name: '*SYSTEM32\\*.tmp' - condition: selection + selection: + path: '\\*ADMIN$' + name: '*SYSTEM32\\*.tmp' + condition: selection falsepositives: - 'unknown' level: high diff --git a/rules/network/zeek/zeek_smb_converted_win_lm_namedpipe.yml b/rules/network/zeek/zeek_smb_converted_win_lm_namedpipe.yml index eecef7a9..34b90aa1 100644 --- a/rules/network/zeek/zeek_smb_converted_win_lm_namedpipe.yml +++ b/rules/network/zeek/zeek_smb_converted_win_lm_namedpipe.yml @@ -1,14 +1,14 @@ title: First Time Seen Remote Named Pipe - Zeek id: 52d8b0c6-53d6-439a-9e41-52ad442ad9ad -description: This detection excludes known namped pipes accessible remotely and notify on newly observed ones, may help to detect lateral movement and remote exec - using named pipes +description: This detection excludes known namped pipes accessible remotely and notify on newly observed ones, may help to detect lateral movement and remote exec using named pipes author: 'Samir Bousseaden, @neu5ron' date: 2020/04/02 references: - https://github.com/neo23x0/sigma/blob/d42e87edd741dd646db946f30964f331f92f50e6/rules/windows/builtin/win_lm_namedpipe.yml -tags: +tags: - attack.lateral_movement - attack.t1077 + - attack.t1021.002 logsource: product: zeek service: smb_files @@ -18,23 +18,23 @@ detection: selection2: path: \\*\IPC$ name: - - 'atsvc' - - 'samr' - - 'lsarpc' - - 'winreg' - - 'netlogon' - - 'srvsvc' - - 'protected_storage' - - 'wkssvc' - - 'browser' - - 'netdfs' - - 'svcctl' - - 'spoolss' - - 'ntsvcs' - - 'LSM_API_service' - - 'HydraLsPipe' - - 'TermSrv_API_service' - - 'MsFteWds' + - 'atsvc' + - 'samr' + - 'lsarpc' + - 'winreg' + - 'netlogon' + - 'srvsvc' + - 'protected_storage' + - 'wkssvc' + - 'browser' + - 'netdfs' + - 'svcctl' + - 'spoolss' + - 'ntsvcs' + - 'LSM_API_service' + - 'HydraLsPipe' + - 'TermSrv_API_service' + - 'MsFteWds' condition: selection1 and not selection2 falsepositives: - update the excluded named pipe to filter out any newly observed legit named pipe diff --git a/rules/network/zeek/zeek_smb_converted_win_susp_psexec.yml b/rules/network/zeek/zeek_smb_converted_win_susp_psexec.yml index 044d6f96..79bd5115 100644 --- a/rules/network/zeek/zeek_smb_converted_win_susp_psexec.yml +++ b/rules/network/zeek/zeek_smb_converted_win_susp_psexec.yml @@ -8,6 +8,7 @@ references: tags: - attack.lateral_movement - attack.t1077 + - attack.t1021.002 logsource: product: zeek service: smb_files @@ -15,9 +16,9 @@ detection: selection1: path: \\*\IPC$ name: - - '*-stdin' - - '*-stdout' - - '*-stderr' + - '*-stdin' + - '*-stdout' + - '*-stderr' selection2: name: \\*\IPC$ path: 'PSEXESVC*' diff --git a/rules/network/zeek/zeek_smb_converted_win_transferring_files_with_credential_data.yml b/rules/network/zeek/zeek_smb_converted_win_transferring_files_with_credential_data.yml index 060189f4..503c9c8f 100644 --- a/rules/network/zeek/zeek_smb_converted_win_transferring_files_with_credential_data.yml +++ b/rules/network/zeek/zeek_smb_converted_win_transferring_files_with_credential_data.yml @@ -4,26 +4,29 @@ description: Transferring files with well-known filenames (sensitive files with author: '@neu5ron, Teymur Kheirkhabarov, oscd.community' date: 2020/04/02 references: - - https://github.com/neo23x0/sigma/blob/373424f14574facf9e261d5c822345a282b91479/rules/windows/builtin/win_transferring_files_with_credential_data_via_network_shares.yml + - https://github.com/neo23x0/sigma/blob/373424f14574facf9e261d5c822345a282b91479/rules/windows/builtin/win_transferring_files_with_credential_data_via_network_shares.yml tags: - - attack.credential_access - - attack.t1003 + - attack.credential_access + - attack.t1003 + - attack.t1003.002 + - attack.t1003.001 + - attack.t1003.003 logsource: - product: zeek - service: smb_files + product: zeek + service: smb_files detection: - selection: - name: - - '\mimidrv' - - '\lsass' - - '\windows\minidump\' - - '\hiberfil' - - '\sqldmpr' - - '\sam' - - '\ntds.dit' - - '\security' - condition: selection + selection: + name: + - '\mimidrv' + - '\lsass' + - '\windows\minidump\' + - '\hiberfil' + - '\sqldmpr' + - '\sam' + - '\ntds.dit' + - '\security' + condition: selection falsepositives: - Transferring sensitive files for legitimate administration work by legitimate administrator level: medium -status: experimental \ No newline at end of file +status: experimental diff --git a/rules/network/zeek/zeek_susp_kerberos_rc4.yml b/rules/network/zeek/zeek_susp_kerberos_rc4.yml index 456f8278..30b134ff 100644 --- a/rules/network/zeek/zeek_susp_kerberos_rc4.yml +++ b/rules/network/zeek/zeek_susp_kerberos_rc4.yml @@ -8,6 +8,7 @@ references: tags: - attack.credential_access - attack.t1208 + - attack.t1558.003 logsource: product: zeek service: kerberos diff --git a/rules/web/web_cve_2018_2894_weblogic_exploit.yml b/rules/web/web_cve_2018_2894_weblogic_exploit.yml index 5bc8b193..d086a2c4 100644 --- a/rules/web/web_cve_2018_2894_weblogic_exploit.yml +++ b/rules/web/web_cve_2018_2894_weblogic_exploit.yml @@ -13,7 +13,7 @@ logsource: category: webserver detection: selection: - c-uri: + c-uri: - '*/config/keystore/*.js*' condition: selection fields: @@ -28,5 +28,6 @@ tags: - attack.persistence - attack.privilege_escalation - cve.2018-2894 + - attack.t1505 level: critical diff --git a/rules/windows/builtin/win_GPO_scheduledtasks.yml b/rules/windows/builtin/win_GPO_scheduledtasks.yml index 6403ab72..75dfa1b0 100644 --- a/rules/windows/builtin/win_GPO_scheduledtasks.yml +++ b/rules/windows/builtin/win_GPO_scheduledtasks.yml @@ -10,6 +10,7 @@ tags: - attack.persistence - attack.lateral_movement - attack.t1053 + - attack.t1053.005 logsource: product: windows service: security diff --git a/rules/windows/builtin/win_admin_share_access.yml b/rules/windows/builtin/win_admin_share_access.yml index e489b78f..a922e0e0 100644 --- a/rules/windows/builtin/win_admin_share_access.yml +++ b/rules/windows/builtin/win_admin_share_access.yml @@ -4,6 +4,7 @@ description: Detects access to $ADMIN share tags: - attack.lateral_movement - attack.t1077 + - attack.t1021.002 status: experimental author: Florian Roth date: 2017/03/04 diff --git a/rules/windows/builtin/win_alert_enable_weak_encryption.yml b/rules/windows/builtin/win_alert_enable_weak_encryption.yml index 906ac89b..5f77c777 100644 --- a/rules/windows/builtin/win_alert_enable_weak_encryption.yml +++ b/rules/windows/builtin/win_alert_enable_weak_encryption.yml @@ -9,6 +9,7 @@ date: 2017/07/30 tags: - attack.defense_evasion - attack.t1089 + - attack.t1562.001 logsource: product: windows service: security @@ -18,9 +19,9 @@ detection: EventID: 4738 keywords: Message: - - '*DES*' - - '*Preauth*' - - '*Encrypted*' + - '*DES*' + - '*Preauth*' + - '*Encrypted*' filters: Message: - '*Enabled*' diff --git a/rules/windows/builtin/win_alert_lsass_access.yml b/rules/windows/builtin/win_alert_lsass_access.yml index bcd7eae7..3ffde491 100644 --- a/rules/windows/builtin/win_alert_lsass_access.yml +++ b/rules/windows/builtin/win_alert_lsass_access.yml @@ -10,6 +10,7 @@ tags: - attack.credential_access - attack.t1003 # Defender Attack Surface Reduction + - attack.t1003.001 logsource: product: windows_defender definition: 'Requirements:Enabled Block credential stealing from the Windows local security authority subsystem (lsass.exe) from Attack Surface Reduction (GUID: 9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2)' diff --git a/rules/windows/builtin/win_alert_mimikatz_keywords.yml b/rules/windows/builtin/win_alert_mimikatz_keywords.yml index f6ad95c8..5a0783fd 100644 --- a/rules/windows/builtin/win_alert_mimikatz_keywords.yml +++ b/rules/windows/builtin/win_alert_mimikatz_keywords.yml @@ -1,7 +1,6 @@ title: Mimikatz Use id: 06d71506-7beb-4f22-8888-e2e5e2ca7fd8 -description: This method detects mimikatz keywords in different Eventlogs (some of them only appear in older Mimikatz version that are however still used by different - threat groups) +description: This method detects mimikatz keywords in different Eventlogs (some of them only appear in older Mimikatz version that are however still used by different threat groups) author: Florian Roth date: 2017/01/10 modified: 2019/10/11 @@ -12,21 +11,25 @@ tags: - attack.credential_access - car.2013-07-001 - car.2019-04-004 + - attack.t1003.002 + - attack.t1003.004 + - attack.t1003.001 + - attack.t1003.006 logsource: product: windows detection: keywords: Message: - - "* mimikatz *" - - "* mimilib *" - - "* <3 eo.oe *" - - "* eo.oe.kiwi *" - - "* privilege::debug *" - - "* sekurlsa::logonpasswords *" - - "* lsadump::sam *" - - "* mimidrv.sys *" - - "* p::d *" - - "* s::l *" + - "* mimikatz *" + - "* mimilib *" + - "* <3 eo.oe *" + - "* eo.oe.kiwi *" + - "* privilege::debug *" + - "* sekurlsa::logonpasswords *" + - "* lsadump::sam *" + - "* mimidrv.sys *" + - "* p::d *" + - "* s::l *" condition: keywords falsepositives: - Naughty administrators diff --git a/rules/windows/builtin/win_alert_ruler.yml b/rules/windows/builtin/win_alert_ruler.yml index 21a85472..603904ca 100644 --- a/rules/windows/builtin/win_alert_ruler.yml +++ b/rules/windows/builtin/win_alert_ruler.yml @@ -17,18 +17,19 @@ tags: - attack.t1075 - attack.t1114 - attack.t1059 + - attack.t1550.002 logsource: product: windows service: security detection: selection1: - EventID: - - 4776 + EventID: + - 4776 Workstation: 'RULER' selection2: EventID: - - 4624 - - 4625 + - 4624 + - 4625 WorkstationName: 'RULER' condition: (1 of selection*) falsepositives: diff --git a/rules/windows/builtin/win_apt_carbonpaper_turla.yml b/rules/windows/builtin/win_apt_carbonpaper_turla.yml index b16c0733..b819affb 100755 --- a/rules/windows/builtin/win_apt_carbonpaper_turla.yml +++ b/rules/windows/builtin/win_apt_carbonpaper_turla.yml @@ -7,6 +7,7 @@ tags: - attack.persistence - attack.g0010 - attack.t1050 + - attack.t1543.003 date: 2017/03/31 author: Florian Roth logsource: diff --git a/rules/windows/builtin/win_apt_stonedrill.yml b/rules/windows/builtin/win_apt_stonedrill.yml index 3db1bfe6..5ffa7528 100755 --- a/rules/windows/builtin/win_apt_stonedrill.yml +++ b/rules/windows/builtin/win_apt_stonedrill.yml @@ -9,6 +9,7 @@ tags: - attack.persistence - attack.g0064 - attack.t1050 + - attack.t1543.003 logsource: product: windows service: system diff --git a/rules/windows/builtin/win_apt_turla_service_png.yml b/rules/windows/builtin/win_apt_turla_service_png.yml index 642809a5..467abba2 100644 --- a/rules/windows/builtin/win_apt_turla_service_png.yml +++ b/rules/windows/builtin/win_apt_turla_service_png.yml @@ -9,6 +9,7 @@ tags: - attack.persistence - attack.g0010 - attack.t1050 + - attack.t1543.003 logsource: product: windows service: system diff --git a/rules/windows/builtin/win_atsvc_task.yml b/rules/windows/builtin/win_atsvc_task.yml index e896b3bc..bb4ce41a 100644 --- a/rules/windows/builtin/win_atsvc_task.yml +++ b/rules/windows/builtin/win_atsvc_task.yml @@ -11,6 +11,7 @@ tags: - attack.t1053 - car.2013-05-004 - car.2015-04-001 + - attack.t1053.002 logsource: product: windows service: security diff --git a/rules/windows/builtin/win_dcsync.yml b/rules/windows/builtin/win_dcsync.yml index f29e9a5f..1181f0e1 100644 --- a/rules/windows/builtin/win_dcsync.yml +++ b/rules/windows/builtin/win_dcsync.yml @@ -12,18 +12,19 @@ tags: - attack.credential_access - attack.s0002 - attack.t1003 + - attack.t1003.006 logsource: product: windows service: security detection: selection: EventID: 4662 - Properties: + Properties: - '*Replicating Directory Changes All*' - '*1131f6ad-9c07-11d1-f79f-00c04fc2dcd2*' filter1: SubjectDomainName: 'Window Manager' - filter2: + filter2: SubjectUserName: - 'NT AUTHORITY*' - '*$' diff --git a/rules/windows/builtin/win_disable_event_logging.yml b/rules/windows/builtin/win_disable_event_logging.yml index 20463e6a..788ac854 100644 --- a/rules/windows/builtin/win_disable_event_logging.yml +++ b/rules/windows/builtin/win_disable_event_logging.yml @@ -1,15 +1,12 @@ title: Disabling Windows Event Auditing id: 69aeb277-f15f-4d2d-b32a-55e883609563 -description: 'Detects scenarios where system auditing (ie: windows event log auditing) is disabled. This may be used in a scenario where an entity would want to bypass - local logging to evade detection when windows event logging is enabled and reviewed. Also, it is recommended to turn off "Local Group Policy Object Processing" - via GPO, which will make sure that Active Directory GPOs take precedence over local/edited computer policies via something such as "gpedit.msc". Please note, - that disabling "Local Group Policy Object Processing" may cause an issue in scenarios of one off specific GPO modifications -- however it is recommended to perform - these modifications in Active Directory anyways.' +description: 'Detects scenarios where system auditing (ie: windows event log auditing) is disabled. This may be used in a scenario where an entity would want to bypass local logging to evade detection when windows event logging is enabled and reviewed. Also, it is recommended to turn off "Local Group Policy Object Processing" via GPO, which will make sure that Active Directory GPOs take precedence over local/edited computer policies via something such as "gpedit.msc". Please note, that disabling "Local Group Policy Object Processing" may cause an issue in scenarios of one off specific GPO modifications -- however it is recommended to perform these modifications in Active Directory anyways.' references: - https://bit.ly/WinLogsZero2Hero tags: - attack.defense_evasion - attack.t1054 + - attack.t1562.006 author: '@neu5ron' date: 2017/11/19 logsource: diff --git a/rules/windows/builtin/win_dpapi_domain_backupkey_extraction.yml b/rules/windows/builtin/win_dpapi_domain_backupkey_extraction.yml index 3093a086..fc70f3b1 100644 --- a/rules/windows/builtin/win_dpapi_domain_backupkey_extraction.yml +++ b/rules/windows/builtin/win_dpapi_domain_backupkey_extraction.yml @@ -9,11 +9,12 @@ references: tags: - attack.credential_access - attack.t1003 + - attack.t1003.004 logsource: product: windows service: security detection: - selection: + selection: EventID: 4662 ObjectType: 'SecretObject' AccessMask: '0x2' @@ -21,4 +22,4 @@ detection: condition: selection falsepositives: - Unknown -level: critical \ No newline at end of file +level: critical diff --git a/rules/windows/builtin/win_dpapi_domain_masterkey_backup_attempt.yml b/rules/windows/builtin/win_dpapi_domain_masterkey_backup_attempt.yml index f488f98a..47ec4686 100644 --- a/rules/windows/builtin/win_dpapi_domain_masterkey_backup_attempt.yml +++ b/rules/windows/builtin/win_dpapi_domain_masterkey_backup_attempt.yml @@ -9,11 +9,12 @@ references: tags: - attack.credential_access - attack.t1003 + - attack.t1003.004 logsource: product: windows service: security detection: - selection: + selection: EventID: 4692 condition: selection fields: diff --git a/rules/windows/builtin/win_hack_smbexec.yml b/rules/windows/builtin/win_hack_smbexec.yml index bf335fbe..270419c1 100644 --- a/rules/windows/builtin/win_hack_smbexec.yml +++ b/rules/windows/builtin/win_hack_smbexec.yml @@ -10,6 +10,8 @@ tags: - attack.execution - attack.t1077 - attack.t1035 + - attack.t1021 + - attack.t1569.002 logsource: product: windows service: system @@ -25,4 +27,4 @@ fields: falsepositives: - Penetration Test - Unknown -level: critical \ No newline at end of file +level: critical diff --git a/rules/windows/builtin/win_impacket_secretdump.yml b/rules/windows/builtin/win_impacket_secretdump.yml index 14d5060e..ca4effe5 100644 --- a/rules/windows/builtin/win_impacket_secretdump.yml +++ b/rules/windows/builtin/win_impacket_secretdump.yml @@ -8,6 +8,9 @@ references: tags: - attack.credential_access - attack.t1003 + - attack.t1003.002 + - attack.t1003.004 + - attack.t1003.003 logsource: product: windows service: security diff --git a/rules/windows/builtin/win_lm_namedpipe.yml b/rules/windows/builtin/win_lm_namedpipe.yml index 90dca9c1..8bbbbc1a 100644 --- a/rules/windows/builtin/win_lm_namedpipe.yml +++ b/rules/windows/builtin/win_lm_namedpipe.yml @@ -1,7 +1,6 @@ title: First Time Seen Remote Named Pipe id: 52d8b0c6-53d6-439a-9e41-52ad442ad9ad -description: This detection excludes known namped pipes accessible remotely and notify on newly observed ones, may help to detect lateral movement and remote exec - using named pipes +description: This detection excludes known namped pipes accessible remotely and notify on newly observed ones, may help to detect lateral movement and remote exec using named pipes author: Samir Bousseaden date: 2019/04/03 references: @@ -9,6 +8,7 @@ references: tags: - attack.lateral_movement - attack.t1077 + - attack.t1021.002 logsource: product: windows service: security @@ -21,23 +21,23 @@ detection: EventID: 5145 ShareName: \\*\IPC$ RelativeTargetName: - - 'atsvc' - - 'samr' - - 'lsarpc' - - 'winreg' - - 'netlogon' - - 'srvsvc' - - 'protected_storage' - - 'wkssvc' - - 'browser' - - 'netdfs' - - 'svcctl' - - 'spoolss' - - 'ntsvcs' - - 'LSM_API_service' - - 'HydraLsPipe' - - 'TermSrv_API_service' - - 'MsFteWds' + - 'atsvc' + - 'samr' + - 'lsarpc' + - 'winreg' + - 'netlogon' + - 'srvsvc' + - 'protected_storage' + - 'wkssvc' + - 'browser' + - 'netdfs' + - 'svcctl' + - 'spoolss' + - 'ntsvcs' + - 'LSM_API_service' + - 'HydraLsPipe' + - 'TermSrv_API_service' + - 'MsFteWds' condition: selection1 and not selection2 falsepositives: - update the excluded named pipe to filter out any newly observed legit named pipe diff --git a/rules/windows/builtin/win_lsass_access_non_system_account.yml b/rules/windows/builtin/win_lsass_access_non_system_account.yml index adb3f7a6..9f0bd07f 100644 --- a/rules/windows/builtin/win_lsass_access_non_system_account.yml +++ b/rules/windows/builtin/win_lsass_access_non_system_account.yml @@ -10,11 +10,12 @@ references: tags: - attack.credential_access - attack.t1003 + - attack.t1003.001 logsource: product: windows service: security detection: - selection: + selection: EventID: - 4663 - 4656 diff --git a/rules/windows/builtin/win_mal_service_installs.yml b/rules/windows/builtin/win_mal_service_installs.yml index d2bb06fe..8fe19151 100644 --- a/rules/windows/builtin/win_mal_service_installs.yml +++ b/rules/windows/builtin/win_mal_service_installs.yml @@ -11,6 +11,8 @@ tags: - attack.t1035 - attack.t1050 - car.2013-09-005 + - attack.t1543.003 + - attack.t1569.002 logsource: product: windows service: system @@ -24,6 +26,6 @@ detection: malsvc_persistence: ServiceFileName|contains: 'net user' condition: selection and 1 of malsvc_* -falsepositives: +falsepositives: - Penetration testing level: critical diff --git a/rules/windows/builtin/win_mmc20_lateral_movement.yml b/rules/windows/builtin/win_mmc20_lateral_movement.yml index baaaca7f..b6ee82fb 100644 --- a/rules/windows/builtin/win_mmc20_lateral_movement.yml +++ b/rules/windows/builtin/win_mmc20_lateral_movement.yml @@ -1,23 +1,25 @@ title: MMC20 Lateral Movement id: f1f3bf22-deb2-418d-8cce-e1a45e46a5bd -description: Detects MMC20.Application Lateral Movement; specifically looks for the spawning of the parent MMC.exe with a command line of "-Embedding" as a child of svchost.exe +description: Detects MMC20.Application Lateral Movement; specifically looks for the spawning of the parent MMC.exe with a command line of "-Embedding" as a child of svchost.exe author: '@2xxeformyshirt (Security Risk Advisors)' date: 2020/03/04 references: - - https://enigma0x3.net/2017/01/05/lateral-movement-using-the-mmc20-application-com-object/ - - https://drive.google.com/file/d/1lKya3_mLnR3UQuCoiYruO3qgu052_iS_/view?usp=sharing + - https://enigma0x3.net/2017/01/05/lateral-movement-using-the-mmc20-application-com-object/ + - https://drive.google.com/file/d/1lKya3_mLnR3UQuCoiYruO3qgu052_iS_/view?usp=sharing tags: - - attack.execution - - attack.t1175 + - attack.execution + - attack.t1175 + - attack.t1021.003 + - attack.t1559.001 logsource: - category: process_creation - product: windows + category: process_creation + product: windows detection: - selection: - ParentImage: '*\svchost.exe' - Image: '*\mmc.exe' - CommandLine: '*-Embedding*' - condition: selection + selection: + ParentImage: '*\svchost.exe' + Image: '*\mmc.exe' + CommandLine: '*-Embedding*' + condition: selection falsepositives: - - Unlikely + - Unlikely level: high diff --git a/rules/windows/builtin/win_overpass_the_hash.yml b/rules/windows/builtin/win_overpass_the_hash.yml index f909666e..11f2afb8 100644 --- a/rules/windows/builtin/win_overpass_the_hash.yml +++ b/rules/windows/builtin/win_overpass_the_hash.yml @@ -10,6 +10,7 @@ tags: - attack.lateral_movement - attack.t1075 - attack.s0002 + - attack.t1550.002 logsource: product: windows service: security diff --git a/rules/windows/builtin/win_pass_the_hash.yml b/rules/windows/builtin/win_pass_the_hash.yml index 582a77b9..1fa07af1 100644 --- a/rules/windows/builtin/win_pass_the_hash.yml +++ b/rules/windows/builtin/win_pass_the_hash.yml @@ -10,6 +10,7 @@ tags: - attack.lateral_movement - attack.t1075 - car.2016-04-004 + - attack.t1550.002 logsource: product: windows service: security @@ -17,15 +18,15 @@ logsource: detection: selection: - EventID: 4624 - LogonType: '3' - LogonProcessName: 'NtLmSsp' - WorkstationName: '%Workstations%' - ComputerName: '%Workstations%' + LogonType: '3' + LogonProcessName: 'NtLmSsp' + WorkstationName: '%Workstations%' + ComputerName: '%Workstations%' - EventID: 4625 - LogonType: '3' - LogonProcessName: 'NtLmSsp' - WorkstationName: '%Workstations%' - ComputerName: '%Workstations%' + LogonType: '3' + LogonProcessName: 'NtLmSsp' + WorkstationName: '%Workstations%' + ComputerName: '%Workstations%' filter: AccountName: 'ANONYMOUS LOGON' condition: selection and not filter diff --git a/rules/windows/builtin/win_pass_the_hash_2.yml b/rules/windows/builtin/win_pass_the_hash_2.yml index 6930ee9c..82f26131 100644 --- a/rules/windows/builtin/win_pass_the_hash_2.yml +++ b/rules/windows/builtin/win_pass_the_hash_2.yml @@ -11,6 +11,7 @@ date: 2019/06/14 tags: - attack.lateral_movement - attack.t1075 + - attack.t1550.002 logsource: product: windows service: security @@ -18,13 +19,13 @@ logsource: detection: selection: - EventID: 4624 - SubjectUserSid: 'S-1-0-0' - LogonType: '3' - LogonProcessName: 'NtLmSsp' - KeyLength: '0' + SubjectUserSid: 'S-1-0-0' + LogonType: '3' + LogonProcessName: 'NtLmSsp' + KeyLength: '0' - EventID: 4624 - LogonType: '9' - LogonProcessName: 'seclogo' + LogonType: '9' + LogonProcessName: 'seclogo' filter: AccountName: 'ANONYMOUS LOGON' condition: selection and not filter diff --git a/rules/windows/builtin/win_quarkspwdump_clearing_hive_access_history.yml b/rules/windows/builtin/win_quarkspwdump_clearing_hive_access_history.yml index 8484a1f3..b20672ad 100644 --- a/rules/windows/builtin/win_quarkspwdump_clearing_hive_access_history.yml +++ b/rules/windows/builtin/win_quarkspwdump_clearing_hive_access_history.yml @@ -8,6 +8,7 @@ modified: 2019/11/13 tags: - attack.credential_access - attack.t1003 + - attack.t1003.002 level: critical logsource: product: windows diff --git a/rules/windows/builtin/win_rare_schtasks_creations.yml b/rules/windows/builtin/win_rare_schtasks_creations.yml index bbd45c50..de8a93f8 100644 --- a/rules/windows/builtin/win_rare_schtasks_creations.yml +++ b/rules/windows/builtin/win_rare_schtasks_creations.yml @@ -10,6 +10,7 @@ tags: - attack.persistence - attack.t1053 - car.2013-08-001 + - attack.t1053.005 logsource: product: windows service: security diff --git a/rules/windows/builtin/win_rare_service_installs.yml b/rules/windows/builtin/win_rare_service_installs.yml index acd55cb6..14b4ecf8 100644 --- a/rules/windows/builtin/win_rare_service_installs.yml +++ b/rules/windows/builtin/win_rare_service_installs.yml @@ -9,6 +9,7 @@ tags: - attack.privilege_escalation - attack.t1050 - car.2013-09-005 + - attack.t1543.003 logsource: product: windows service: system diff --git a/rules/windows/builtin/win_rdp_localhost_login.yml b/rules/windows/builtin/win_rdp_localhost_login.yml index 3f269fe7..165bd12f 100644 --- a/rules/windows/builtin/win_rdp_localhost_login.yml +++ b/rules/windows/builtin/win_rdp_localhost_login.yml @@ -9,6 +9,7 @@ tags: - attack.lateral_movement - attack.t1076 - car.2013-07-002 + - attack.t1021 status: experimental author: Thomas Patzke logsource: diff --git a/rules/windows/builtin/win_rdp_reverse_tunnel.yml b/rules/windows/builtin/win_rdp_reverse_tunnel.yml index d18e5200..a68d5745 100644 --- a/rules/windows/builtin/win_rdp_reverse_tunnel.yml +++ b/rules/windows/builtin/win_rdp_reverse_tunnel.yml @@ -14,6 +14,7 @@ tags: - attack.t1076 - attack.t1090 - car.2013-07-002 + - attack.t1021 logsource: product: windows service: security diff --git a/rules/windows/builtin/win_register_new_logon_process_by_rubeus.yml b/rules/windows/builtin/win_register_new_logon_process_by_rubeus.yml index 9fb4e644..c1d677ee 100644 --- a/rules/windows/builtin/win_register_new_logon_process_by_rubeus.yml +++ b/rules/windows/builtin/win_register_new_logon_process_by_rubeus.yml @@ -8,6 +8,7 @@ tags: - attack.lateral_movement - attack.privilege_escalation - attack.t1208 + - attack.t1558.003 author: Roberto Rodriguez (source), Ilyas Ochkov (rule), oscd.community date: 2019/10/24 logsource: @@ -16,7 +17,7 @@ logsource: detection: selection: - EventID: 4611 - LogonProcessName: 'User32LogonProcesss' + LogonProcessName: 'User32LogonProcesss' condition: selection falsepositives: - Unkown diff --git a/rules/windows/builtin/win_remote_powershell_session.yml b/rules/windows/builtin/win_remote_powershell_session.yml index d0e395e4..1167c97f 100644 --- a/rules/windows/builtin/win_remote_powershell_session.yml +++ b/rules/windows/builtin/win_remote_powershell_session.yml @@ -9,11 +9,12 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 logsource: product: windows service: security detection: - selection: + selection: EventID: 5156 DestPort: - 5985 diff --git a/rules/windows/builtin/win_susp_add_sid_history.yml b/rules/windows/builtin/win_susp_add_sid_history.yml index 0a407a6e..1eb679dc 100644 --- a/rules/windows/builtin/win_susp_add_sid_history.yml +++ b/rules/windows/builtin/win_susp_add_sid_history.yml @@ -10,6 +10,7 @@ tags: - attack.persistence - attack.privilege_escalation - attack.t1178 + - attack.t1134.005 logsource: product: windows service: security @@ -25,7 +26,7 @@ detection: - '-' - '%%1793' filter_null: - SidHistory: null + SidHistory: condition: selection1 or (selection2 and not selection3 and not filter_null) falsepositives: - Migration of an account into a new domain diff --git a/rules/windows/builtin/win_susp_backup_delete.yml b/rules/windows/builtin/win_susp_backup_delete.yml index 32dfb5d0..332b6c80 100644 --- a/rules/windows/builtin/win_susp_backup_delete.yml +++ b/rules/windows/builtin/win_susp_backup_delete.yml @@ -10,6 +10,7 @@ date: 2017/05/12 tags: - attack.defense_evasion - attack.t1107 + - attack.t1551.004 logsource: product: windows service: application diff --git a/rules/windows/builtin/win_susp_codeintegrity_check_failure.yml b/rules/windows/builtin/win_susp_codeintegrity_check_failure.yml index 34331edc..e5afc8f7 100644 --- a/rules/windows/builtin/win_susp_codeintegrity_check_failure.yml +++ b/rules/windows/builtin/win_susp_codeintegrity_check_failure.yml @@ -7,6 +7,7 @@ date: 2019/12/03 tags: - attack.defense_evasion - attack.t1009 + - attack.t1027 logsource: product: windows service: security diff --git a/rules/windows/builtin/win_susp_dhcp_config.yml b/rules/windows/builtin/win_susp_dhcp_config.yml index a7090b8d..0c357fc9 100644 --- a/rules/windows/builtin/win_susp_dhcp_config.yml +++ b/rules/windows/builtin/win_susp_dhcp_config.yml @@ -11,6 +11,7 @@ author: Dimitrios Slamaris tags: - attack.defense_evasion - attack.t1073 + - attack.t1574.002 logsource: product: windows service: system @@ -19,6 +20,6 @@ detection: EventID: 1033 Source: Microsoft-Windows-DHCP-Server condition: selection -falsepositives: +falsepositives: - Unknown level: critical diff --git a/rules/windows/builtin/win_susp_dhcp_config_failed.yml b/rules/windows/builtin/win_susp_dhcp_config_failed.yml index f3c4f36e..8dc62e80 100644 --- a/rules/windows/builtin/win_susp_dhcp_config_failed.yml +++ b/rules/windows/builtin/win_susp_dhcp_config_failed.yml @@ -11,18 +11,19 @@ modified: 2019/07/17 tags: - attack.defense_evasion - attack.t1073 + - attack.t1574.002 author: "Dimitrios Slamaris, @atc_project (fix)" logsource: product: windows service: system detection: selection: - EventID: + EventID: - 1031 - 1032 - 1034 - Source: Microsoft-Windows-DHCP-Server + Source: Microsoft-Windows-DHCP-Server condition: selection -falsepositives: +falsepositives: - Unknown level: critical diff --git a/rules/windows/builtin/win_susp_dns_config.yml b/rules/windows/builtin/win_susp_dns_config.yml index df7ffe3f..8ef63d9c 100644 --- a/rules/windows/builtin/win_susp_dns_config.yml +++ b/rules/windows/builtin/win_susp_dns_config.yml @@ -10,17 +10,18 @@ references: tags: - attack.defense_evasion - attack.t1073 + - attack.t1574.002 author: Florian Roth logsource: product: windows service: dns-server detection: selection: - EventID: + EventID: - 150 - 770 condition: selection -falsepositives: +falsepositives: - Unknown level: critical diff --git a/rules/windows/builtin/win_susp_eventlog_cleared.yml b/rules/windows/builtin/win_susp_eventlog_cleared.yml index ec1981f5..b0698a1c 100644 --- a/rules/windows/builtin/win_susp_eventlog_cleared.yml +++ b/rules/windows/builtin/win_susp_eventlog_cleared.yml @@ -10,6 +10,7 @@ tags: - attack.defense_evasion - attack.t1070 - car.2016-04-002 + - attack.t1551 logsource: product: windows service: system diff --git a/rules/windows/builtin/win_susp_lsass_dump.yml b/rules/windows/builtin/win_susp_lsass_dump.yml index 52921441..b3b39f7b 100644 --- a/rules/windows/builtin/win_susp_lsass_dump.yml +++ b/rules/windows/builtin/win_susp_lsass_dump.yml @@ -8,6 +8,7 @@ references: tags: - attack.credential_access - attack.t1003 + - attack.t1003.001 logsource: product: windows service: security diff --git a/rules/windows/builtin/win_susp_lsass_dump_generic.yml b/rules/windows/builtin/win_susp_lsass_dump_generic.yml index 604c2f41..fa536e26 100644 --- a/rules/windows/builtin/win_susp_lsass_dump_generic.yml +++ b/rules/windows/builtin/win_susp_lsass_dump_generic.yml @@ -12,6 +12,7 @@ tags: - attack.credential_access - attack.t1003 - car.2019-04-004 + - attack.t1003.001 logsource: product: windows service: security @@ -40,7 +41,7 @@ detection: - '4484' - '4416' filter: - ProcessName|endswith: + ProcessName|endswith: - '\wmiprvse.exe' - '\taskmgr.exe' - '\procexp64.exe' diff --git a/rules/windows/builtin/win_susp_msmpeng_crash.yml b/rules/windows/builtin/win_susp_msmpeng_crash.yml index 3e6f6fcb..4ce48ead 100644 --- a/rules/windows/builtin/win_susp_msmpeng_crash.yml +++ b/rules/windows/builtin/win_susp_msmpeng_crash.yml @@ -5,6 +5,7 @@ tags: - attack.defense_evasion - attack.t1089 - attack.t1211 + - attack.t1562.001 status: experimental date: 2017/05/09 references: diff --git a/rules/windows/builtin/win_susp_ntlm_auth.yml b/rules/windows/builtin/win_susp_ntlm_auth.yml index f8ea778c..3e4a2fb9 100644 --- a/rules/windows/builtin/win_susp_ntlm_auth.yml +++ b/rules/windows/builtin/win_susp_ntlm_auth.yml @@ -10,6 +10,7 @@ date: 2018/06/08 tags: - attack.lateral_movement - attack.t1075 + - attack.t1550.002 logsource: product: windows service: ntlm diff --git a/rules/windows/builtin/win_susp_psexec.yml b/rules/windows/builtin/win_susp_psexec.yml index f48f593b..62216f2e 100644 --- a/rules/windows/builtin/win_susp_psexec.yml +++ b/rules/windows/builtin/win_susp_psexec.yml @@ -1,7 +1,6 @@ title: Suspicious PsExec Execution id: c462f537-a1e3-41a6-b5fc-b2c2cef9bf82 -description: detects execution of psexec or paexec with renamed service name, this rule helps to filter out the noise if psexec is used for legit purposes or if attacker - uses a different psexec client other than sysinternal one +description: detects execution of psexec or paexec with renamed service name, this rule helps to filter out the noise if psexec is used for legit purposes or if attacker uses a different psexec client other than sysinternal one author: Samir Bousseaden date: 2019/04/03 references: @@ -9,6 +8,7 @@ references: tags: - attack.lateral_movement - attack.t1077 + - attack.t1021.002 logsource: product: windows service: security @@ -18,9 +18,9 @@ detection: EventID: 5145 ShareName: \\*\IPC$ RelativeTargetName: - - '*-stdin' - - '*-stdout' - - '*-stderr' + - '*-stdin' + - '*-stdout' + - '*-stderr' selection2: EventID: 5145 ShareName: \\*\IPC$ diff --git a/rules/windows/builtin/win_susp_rc4_kerberos.yml b/rules/windows/builtin/win_susp_rc4_kerberos.yml index 534151c4..56bea540 100644 --- a/rules/windows/builtin/win_susp_rc4_kerberos.yml +++ b/rules/windows/builtin/win_susp_rc4_kerberos.yml @@ -7,6 +7,7 @@ references: tags: - attack.credential_access - attack.t1208 + - attack.t1558.003 description: Detects service ticket requests using RC4 encryption type author: Florian Roth date: 2017/02/06 diff --git a/rules/windows/builtin/win_susp_rottenpotato.yml b/rules/windows/builtin/win_susp_rottenpotato.yml index 1e7d58b2..c6df3410 100644 --- a/rules/windows/builtin/win_susp_rottenpotato.yml +++ b/rules/windows/builtin/win_susp_rottenpotato.yml @@ -10,6 +10,7 @@ tags: - attack.privilege_escalation - attack.credential_access - attack.t1171 + - attack.t1557.001 logsource: product: windows service: security diff --git a/rules/windows/builtin/win_susp_sam_dump.yml b/rules/windows/builtin/win_susp_sam_dump.yml index 930531db..117fa49b 100644 --- a/rules/windows/builtin/win_susp_sam_dump.yml +++ b/rules/windows/builtin/win_susp_sam_dump.yml @@ -5,6 +5,7 @@ description: Detects suspicious SAM dump activity as cause by QuarksPwDump and o tags: - attack.credential_access - attack.t1003 + - attack.t1003.002 author: Florian Roth date: 2018/01/27 logsource: diff --git a/rules/windows/builtin/win_susp_sdelete.yml b/rules/windows/builtin/win_susp_sdelete.yml index 5f8df21e..8483f026 100644 --- a/rules/windows/builtin/win_susp_sdelete.yml +++ b/rules/windows/builtin/win_susp_sdelete.yml @@ -13,6 +13,8 @@ tags: - attack.t1107 - attack.t1066 - attack.s0195 + - attack.t1551.004 + - attack.t1027 logsource: product: windows service: security diff --git a/rules/windows/builtin/win_susp_security_eventlog_cleared.yml b/rules/windows/builtin/win_susp_security_eventlog_cleared.yml index 7b0b7dcc..d31a49b4 100644 --- a/rules/windows/builtin/win_susp_security_eventlog_cleared.yml +++ b/rules/windows/builtin/win_susp_security_eventlog_cleared.yml @@ -5,6 +5,7 @@ tags: - attack.defense_evasion - attack.t1070 - car.2016-04-002 + - attack.t1551 author: Florian Roth date: 2017/02/19 logsource: diff --git a/rules/windows/builtin/win_susp_time_modification.yml b/rules/windows/builtin/win_susp_time_modification.yml index 628f4a7f..c457b28e 100644 --- a/rules/windows/builtin/win_susp_time_modification.yml +++ b/rules/windows/builtin/win_susp_time_modification.yml @@ -11,6 +11,7 @@ midified: 2020/01/27 tags: - attack.defense_evasion - attack.t1099 + - attack.t1551.006 logsource: product: windows service: security diff --git a/rules/windows/builtin/win_suspicious_outbound_kerberos_connection.yml b/rules/windows/builtin/win_suspicious_outbound_kerberos_connection.yml index 7eca151e..921c558e 100644 --- a/rules/windows/builtin/win_suspicious_outbound_kerberos_connection.yml +++ b/rules/windows/builtin/win_suspicious_outbound_kerberos_connection.yml @@ -10,6 +10,7 @@ modified: 2019/11/13 tags: - attack.lateral_movement - attack.t1208 + - attack.t1558.003 logsource: product: windows service: security @@ -23,7 +24,7 @@ detection: - '\opera.exe' - '\chrome.exe' - '\firefox.exe' - condition: selection and not filter + condition: selection and not filter falsepositives: - Other browsers level: high diff --git a/rules/windows/builtin/win_transferring_files_with_credential_data_via_network_shares.yml b/rules/windows/builtin/win_transferring_files_with_credential_data_via_network_shares.yml index 15a91884..9084a2cb 100644 --- a/rules/windows/builtin/win_transferring_files_with_credential_data_via_network_shares.yml +++ b/rules/windows/builtin/win_transferring_files_with_credential_data_via_network_shares.yml @@ -8,6 +8,9 @@ references: tags: - attack.credential_access - attack.t1003 + - attack.t1003.002 + - attack.t1003.001 + - attack.t1003.003 logsource: product: windows service: security diff --git a/rules/windows/builtin/win_user_couldnt_call_privileged_service_lsaregisterlogonprocess.yml b/rules/windows/builtin/win_user_couldnt_call_privileged_service_lsaregisterlogonprocess.yml index 319250a1..59ee3b4b 100644 --- a/rules/windows/builtin/win_user_couldnt_call_privileged_service_lsaregisterlogonprocess.yml +++ b/rules/windows/builtin/win_user_couldnt_call_privileged_service_lsaregisterlogonprocess.yml @@ -1,7 +1,6 @@ title: User Couldn't Call a Privileged Service 'LsaRegisterLogonProcess' id: 6daac7fc-77d1-449a-a71a-e6b4d59a0e54 -description: The 'LsaRegisterLogonProcess' function verifies that the application making the function call is a logon process by checking that it has the SeTcbPrivilege - privilege set. Possible Rubeus tries to get a handle to LSA. +description: The 'LsaRegisterLogonProcess' function verifies that the application making the function call is a logon process by checking that it has the SeTcbPrivilege privilege set. Possible Rubeus tries to get a handle to LSA. status: experimental references: - https://posts.specterops.io/hunting-in-active-directory-unconstrained-delegation-forests-trusts-71f2b33688e1 @@ -9,6 +8,7 @@ tags: - attack.lateral_movement - attack.privilege_escalation - attack.t1208 + - attack.t1558.003 author: Roberto Rodriguez (source), Ilyas Ochkov (rule), oscd.community date: 2019/10/24 logsource: @@ -17,8 +17,8 @@ logsource: detection: selection: - EventID: 4673 - Service: 'LsaRegisterLogonProcess()' - Keywords: '0x8010000000000000' #failure + Service: 'LsaRegisterLogonProcess()' + Keywords: '0x8010000000000000' #failure condition: selection falsepositives: - Unkown diff --git a/rules/windows/builtin/win_user_driver_loaded.yml b/rules/windows/builtin/win_user_driver_loaded.yml index e993a8d4..9d3ae187 100644 --- a/rules/windows/builtin/win_user_driver_loaded.yml +++ b/rules/windows/builtin/win_user_driver_loaded.yml @@ -8,6 +8,7 @@ references: tags: - attack.t1089 - attack.defense_evasion + - attack.t1562.001 date: 2019/04/08 author: xknow (@xknow_infosec), xorxes (@xor_xes) logsource: diff --git a/rules/windows/malware/av_password_dumper.yml b/rules/windows/malware/av_password_dumper.yml index 52854854..168d357e 100644 --- a/rules/windows/malware/av_password_dumper.yml +++ b/rules/windows/malware/av_password_dumper.yml @@ -9,11 +9,14 @@ references: tags: - attack.credential_access - attack.t1003 + - attack.t1558 + - attack.t1003.001 + - attack.t1003.002 logsource: product: antivirus detection: selection: - Signature: + Signature: - "*DumpCreds*" - "*Mimikatz*" - "*PWCrack*" diff --git a/rules/windows/malware/av_webshell.yml b/rules/windows/malware/av_webshell.yml index b041fda8..11f8eb0b 100644 --- a/rules/windows/malware/av_webshell.yml +++ b/rules/windows/malware/av_webshell.yml @@ -9,11 +9,12 @@ references: tags: - attack.persistence - attack.t1100 + - attack.t1505.003 logsource: product: antivirus detection: selection: - Signature: + Signature: - "PHP/Backdoor*" - "JSP/Backdoor*" - "ASP/Backdoor*" diff --git a/rules/windows/other/win_defender_bypass.yml b/rules/windows/other/win_defender_bypass.yml index cc4fb5b8..f70b847e 100644 --- a/rules/windows/other/win_defender_bypass.yml +++ b/rules/windows/other/win_defender_bypass.yml @@ -6,6 +6,7 @@ references: tags: - attack.defense_evasion - attack.t1089 + - attack.t1562.001 author: "@BarryShooshooga" date: 2019/10/26 logsource: @@ -14,13 +15,13 @@ logsource: definition: 'Requirements: Audit Policy : Security Settings/Local Policies/Audit Policy, Registry System Access Control (SACL): Auditing/User' detection: selection: - EventID: + EventID: - 4657 - 4656 - 4660 - 4663 ObjectName|contains: '\Microsoft\Windows Defender\Exclusions\' condition: selection -falsepositives: +falsepositives: - Intended inclusions by administrator level: high diff --git a/rules/windows/other/win_rare_schtask_creation.yml b/rules/windows/other/win_rare_schtask_creation.yml index 2992ab30..1329e32f 100644 --- a/rules/windows/other/win_rare_schtask_creation.yml +++ b/rules/windows/other/win_rare_schtask_creation.yml @@ -1,12 +1,12 @@ title: Rare Scheduled Task Creations id: b20f6158-9438-41be-83da-a5a16ac90c2b status: experimental -description: This rule detects rare scheduled task creations. Typically software gets installed on multiple systems and not only on a few. The aggregation and count - function selects tasks with rare names. +description: This rule detects rare scheduled task creations. Typically software gets installed on multiple systems and not only on a few. The aggregation and count function selects tasks with rare names. tags: - attack.persistence - attack.t1053 - attack.s0111 + - attack.t1053.005 author: Florian Roth date: 2017/03/17 logsource: diff --git a/rules/windows/powershell/powershell_alternate_powershell_hosts.yml b/rules/windows/powershell/powershell_alternate_powershell_hosts.yml index 37f10827..07b87d01 100644 --- a/rules/windows/powershell/powershell_alternate_powershell_hosts.yml +++ b/rules/windows/powershell/powershell_alternate_powershell_hosts.yml @@ -10,11 +10,12 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 logsource: product: windows service: powershell detection: - selection: + selection: EventID: - 4103 - 400 diff --git a/rules/windows/powershell/powershell_clear_powershell_history.yml b/rules/windows/powershell/powershell_clear_powershell_history.yml index d6c42d03..4f52faec 100644 --- a/rules/windows/powershell/powershell_clear_powershell_history.yml +++ b/rules/windows/powershell/powershell_clear_powershell_history.yml @@ -9,6 +9,7 @@ references: tags: - attack.defense_evasion - attack.t1146 + - attack.t1551.003 logsource: product: windows service: powershell diff --git a/rules/windows/powershell/powershell_create_local_user.yml b/rules/windows/powershell/powershell_create_local_user.yml index 279826f9..d479cb48 100644 --- a/rules/windows/powershell/powershell_create_local_user.yml +++ b/rules/windows/powershell/powershell_create_local_user.yml @@ -1,6 +1,6 @@ title: PowerShell Create Local User id: 243de76f-4725-4f2e-8225-a8a69b15ad61 -status: experimental +status: experimental description: Detects creation of a local user via PowerShell references: - https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1136/T1136.md @@ -9,8 +9,9 @@ tags: - attack.t1086 - attack.persistence - attack.t1136 -author: '@ROxPinTeddy' -date: 2020/04/11 + - attack.t1059.001 +author: '@ROxPinTeddy' +date: 2020/04/11 logsource: product: windows service: powershell @@ -19,7 +20,7 @@ detection: EventID: 4104 Message|contains: - 'New-LocalUser' - condition: selection + condition: selection falsepositives: - - Legitimate user creation + - Legitimate user creation level: medium diff --git a/rules/windows/powershell/powershell_data_compressed.yml b/rules/windows/powershell/powershell_data_compressed.yml index 9af0feff..ebd3a1c0 100644 --- a/rules/windows/powershell/powershell_data_compressed.yml +++ b/rules/windows/powershell/powershell_data_compressed.yml @@ -1,8 +1,7 @@ title: Data Compressed - Powershell id: 6dc5d284-69ea-42cf-9311-fb1c3932a69a status: experimental -description: An adversary may compress data (e.g., sensitive documents) that is collected prior to exfiltration in order to make it portable and minimize the amount - of data sent over the network +description: An adversary may compress data (e.g., sensitive documents) that is collected prior to exfiltration in order to make it portable and minimize the amount of data sent over the network author: Timur Zinniatullin, oscd.community date: 2019/10/21 modified: 2019/11/04 @@ -15,7 +14,7 @@ logsource: detection: selection: EventID: 4104 - keywords|contains|all: + keywords|contains|all: - '-Recurse' - '|' - 'Compress-Archive' @@ -26,3 +25,4 @@ level: low tags: - attack.exfiltration - attack.t1002 + - attack.t1560 diff --git a/rules/windows/powershell/powershell_downgrade_attack.yml b/rules/windows/powershell/powershell_downgrade_attack.yml index 8071fcb4..d14ef31a 100644 --- a/rules/windows/powershell/powershell_downgrade_attack.yml +++ b/rules/windows/powershell/powershell_downgrade_attack.yml @@ -8,6 +8,7 @@ tags: - attack.defense_evasion - attack.execution - attack.t1086 + - attack.t1059.001 author: Florian Roth (rule), Lee Holmes (idea), Harish Segar (improvements) date: 2017/03/22 modified: 2020/03/20 @@ -24,4 +25,4 @@ detection: falsepositives: - Penetration Test - Unknown -level: medium \ No newline at end of file +level: medium diff --git a/rules/windows/powershell/powershell_exe_calling_ps.yml b/rules/windows/powershell/powershell_exe_calling_ps.yml index 28448cc5..9a921aa8 100644 --- a/rules/windows/powershell/powershell_exe_calling_ps.yml +++ b/rules/windows/powershell/powershell_exe_calling_ps.yml @@ -8,6 +8,7 @@ tags: - attack.defense_evasion - attack.execution - attack.t1086 + - attack.t1059.001 author: Sean Metcalf (source), Florian Roth (rule) date: 2017/03/05 logsource: diff --git a/rules/windows/powershell/powershell_malicious_commandlets.yml b/rules/windows/powershell/powershell_malicious_commandlets.yml index 04c495ef..e232d1bf 100644 --- a/rules/windows/powershell/powershell_malicious_commandlets.yml +++ b/rules/windows/powershell/powershell_malicious_commandlets.yml @@ -8,6 +8,7 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 author: Sean Metcalf (source), Florian Roth (rule) date: 2017/03/05 logsource: diff --git a/rules/windows/powershell/powershell_malicious_keywords.yml b/rules/windows/powershell/powershell_malicious_keywords.yml index 1fb45807..a0131ff6 100644 --- a/rules/windows/powershell/powershell_malicious_keywords.yml +++ b/rules/windows/powershell/powershell_malicious_keywords.yml @@ -8,6 +8,7 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 author: Sean Metcalf (source), Florian Roth (rule) date: 2017/03/05 logsource: diff --git a/rules/windows/powershell/powershell_nishang_malicious_commandlets.yml b/rules/windows/powershell/powershell_nishang_malicious_commandlets.yml index 26074603..e7d075a5 100644 --- a/rules/windows/powershell/powershell_nishang_malicious_commandlets.yml +++ b/rules/windows/powershell/powershell_nishang_malicious_commandlets.yml @@ -8,6 +8,7 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 author: Alec Costello logsource: product: windows diff --git a/rules/windows/powershell/powershell_ntfs_ads_access.yml b/rules/windows/powershell/powershell_ntfs_ads_access.yml index e2c531b7..bf4c81ea 100644 --- a/rules/windows/powershell/powershell_ntfs_ads_access.yml +++ b/rules/windows/powershell/powershell_ntfs_ads_access.yml @@ -7,6 +7,7 @@ references: tags: - attack.defense_evasion - attack.t1096 + - attack.t1564.004 author: Sami Ruohonen date: 2018/07/24 logsource: diff --git a/rules/windows/powershell/powershell_prompt_credentials.yml b/rules/windows/powershell/powershell_prompt_credentials.yml index 9b810c4b..c4c4d5f2 100644 --- a/rules/windows/powershell/powershell_prompt_credentials.yml +++ b/rules/windows/powershell/powershell_prompt_credentials.yml @@ -9,6 +9,7 @@ tags: - attack.execution - attack.credential_access - attack.t1086 + - attack.t1059.001 author: John Lambert (idea), Florian Roth (rule) date: 2017/04/09 logsource: diff --git a/rules/windows/powershell/powershell_psattack.yml b/rules/windows/powershell/powershell_psattack.yml index c955031d..9ca1ffa5 100644 --- a/rules/windows/powershell/powershell_psattack.yml +++ b/rules/windows/powershell/powershell_psattack.yml @@ -7,6 +7,7 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 author: Sean Metcalf (source), Florian Roth (rule) date: 2017/03/05 logsource: diff --git a/rules/windows/powershell/powershell_remote_powershell_session.yml b/rules/windows/powershell/powershell_remote_powershell_session.yml index 2da0f0f3..c5b9e3cf 100644 --- a/rules/windows/powershell/powershell_remote_powershell_session.yml +++ b/rules/windows/powershell/powershell_remote_powershell_session.yml @@ -10,11 +10,12 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 logsource: product: windows service: powershell detection: - selection: + selection: EventID: - 4103 - 400 diff --git a/rules/windows/powershell/powershell_shellcode_b64.yml b/rules/windows/powershell/powershell_shellcode_b64.yml index f705329d..fabff88a 100644 --- a/rules/windows/powershell/powershell_shellcode_b64.yml +++ b/rules/windows/powershell/powershell_shellcode_b64.yml @@ -9,6 +9,7 @@ tags: - attack.execution - attack.t1055 - attack.t1086 + - attack.t1059 author: David Ledbetter (shellcode), Florian Roth (rule) date: 2018/11/17 logsource: @@ -18,9 +19,9 @@ logsource: detection: selection: EventID: 4104 - keyword1: + keyword1: - '*AAAAYInlM*' - keyword2: + keyword2: - '*OiCAAAAYInlM*' - '*OiJAAAAYInlM*' condition: selection and keyword1 and keyword2 diff --git a/rules/windows/powershell/powershell_suspicious_download.yml b/rules/windows/powershell/powershell_suspicious_download.yml index cc735186..6d8fe1b1 100644 --- a/rules/windows/powershell/powershell_suspicious_download.yml +++ b/rules/windows/powershell/powershell_suspicious_download.yml @@ -5,6 +5,7 @@ description: Detects suspicious PowerShell download command tags: - attack.execution - attack.t1086 + - attack.t1059.001 author: Florian Roth date: 2017/03/05 modified: 2020/03/25 diff --git a/rules/windows/powershell/powershell_suspicious_invocation_generic.yml b/rules/windows/powershell/powershell_suspicious_invocation_generic.yml index 6127e1f7..8f6637cc 100644 --- a/rules/windows/powershell/powershell_suspicious_invocation_generic.yml +++ b/rules/windows/powershell/powershell_suspicious_invocation_generic.yml @@ -5,6 +5,7 @@ description: Detects suspicious PowerShell invocation command parameters tags: - attack.execution - attack.t1086 + - attack.t1059.001 author: Florian Roth (rule) date: 2017/03/12 logsource: diff --git a/rules/windows/powershell/powershell_suspicious_invocation_specific.yml b/rules/windows/powershell/powershell_suspicious_invocation_specific.yml index 41b6f78b..bfdbad36 100644 --- a/rules/windows/powershell/powershell_suspicious_invocation_specific.yml +++ b/rules/windows/powershell/powershell_suspicious_invocation_specific.yml @@ -5,6 +5,7 @@ description: Detects suspicious PowerShell invocation command parameters tags: - attack.execution - attack.t1086 + - attack.t1059.001 author: Florian Roth (rule) date: 2017/03/05 logsource: diff --git a/rules/windows/powershell/powershell_suspicious_keywords.yml b/rules/windows/powershell/powershell_suspicious_keywords.yml index fa90f0eb..0f2b8c49 100644 --- a/rules/windows/powershell/powershell_suspicious_keywords.yml +++ b/rules/windows/powershell/powershell_suspicious_keywords.yml @@ -11,6 +11,7 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 logsource: product: windows service: powershell diff --git a/rules/windows/powershell/powershell_winlogon_helper_dll.yml b/rules/windows/powershell/powershell_winlogon_helper_dll.yml index fd1378f4..bc5c334e 100644 --- a/rules/windows/powershell/powershell_winlogon_helper_dll.yml +++ b/rules/windows/powershell/powershell_winlogon_helper_dll.yml @@ -1,10 +1,7 @@ title: Winlogon Helper DLL id: 851c506b-6b7c-4ce2-8802-c703009d03c0 status: experimental -description: Winlogon.exe is a Windows component responsible for actions at logon/logoff as well as the secure attention sequence (SAS) triggered by Ctrl-Alt-Delete. - Registry entries in HKLM\Software[Wow6432Node]Microsoft\Windows NT\CurrentVersion\Winlogon\ and HKCU\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\ are - used to manage additional helper programs and functionalities that support Winlogon. Malicious modifications to these Registry keys may cause Winlogon to load - and execute malicious DLLs and/or executables. +description: Winlogon.exe is a Windows component responsible for actions at logon/logoff as well as the secure attention sequence (SAS) triggered by Ctrl-Alt-Delete. Registry entries in HKLM\Software[Wow6432Node]Microsoft\Windows NT\CurrentVersion\Winlogon\ and HKCU\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\ are used to manage additional helper programs and functionalities that support Winlogon. Malicious modifications to these Registry keys may cause Winlogon to load and execute malicious DLLs and/or executables. author: Timur Zinniatullin, oscd.community date: 2019/10/21 modified: 2019/11/04 @@ -17,10 +14,10 @@ logsource: detection: selection: EventID: 4104 - keyword1: + keyword1: - '*Set-ItemProperty*' - '*New-Item*' - keyword2: + keyword2: - '*CurrentVersion\Winlogon*' condition: selection and ( keyword1 and keyword2 ) falsepositives: @@ -29,3 +26,4 @@ level: medium tags: - attack.persistence - attack.t1004 + - attack.t1547.004 diff --git a/rules/windows/process_creation/win_apt_apt29_thinktanks.yml b/rules/windows/process_creation/win_apt_apt29_thinktanks.yml index fe907c49..d4f12292 100644 --- a/rules/windows/process_creation/win_apt_apt29_thinktanks.yml +++ b/rules/windows/process_creation/win_apt_apt29_thinktanks.yml @@ -7,8 +7,9 @@ tags: - attack.execution - attack.g0016 - attack.t1086 + - attack.t1059.001 author: Florian Roth -date: 2018/12/04 +date: 2018/12/04 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_apt_babyshark.yml b/rules/windows/process_creation/win_apt_babyshark.yml index fe7bc28c..cf40e92f 100644 --- a/rules/windows/process_creation/win_apt_babyshark.yml +++ b/rules/windows/process_creation/win_apt_babyshark.yml @@ -12,6 +12,9 @@ tags: - attack.t1012 - attack.defense_evasion - attack.t1170 + - attack.t1218 + - attack.t1059.003 + - attack.t1059.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_apt_bear_activity_gtr19.yml b/rules/windows/process_creation/win_apt_bear_activity_gtr19.yml index d3d160ee..d629b491 100644 --- a/rules/windows/process_creation/win_apt_bear_activity_gtr19.yml +++ b/rules/windows/process_creation/win_apt_bear_activity_gtr19.yml @@ -9,6 +9,7 @@ tags: - attack.credential_access - attack.t1081 - attack.t1003 + - attack.t1552.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_apt_bluemashroom.yml b/rules/windows/process_creation/win_apt_bluemashroom.yml index 231f2bb8..ab58aaff 100644 --- a/rules/windows/process_creation/win_apt_bluemashroom.yml +++ b/rules/windows/process_creation/win_apt_bluemashroom.yml @@ -7,6 +7,7 @@ references: tags: - attack.defense_evasion - attack.t1117 + - attack.t1218.010 author: Florian Roth date: 2019/10/02 logsource: @@ -14,7 +15,7 @@ logsource: product: windows detection: selection: - CommandLine: + CommandLine: - '*\regsvr32*\AppData\Local\\*' - '*\AppData\Local\\*,DllEntry*' condition: selection diff --git a/rules/windows/process_creation/win_apt_cloudhopper.yml b/rules/windows/process_creation/win_apt_cloudhopper.yml index 3e94043f..51a72fe6 100755 --- a/rules/windows/process_creation/win_apt_cloudhopper.yml +++ b/rules/windows/process_creation/win_apt_cloudhopper.yml @@ -9,6 +9,7 @@ tags: - attack.execution - attack.g0045 - attack.t1064 + - attack.t1059.005 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_apt_equationgroup_dll_u_load.yml b/rules/windows/process_creation/win_apt_equationgroup_dll_u_load.yml index 8cfc979a..2cb176b2 100755 --- a/rules/windows/process_creation/win_apt_equationgroup_dll_u_load.yml +++ b/rules/windows/process_creation/win_apt_equationgroup_dll_u_load.yml @@ -13,6 +13,7 @@ tags: - attack.t1059 - attack.defense_evasion - attack.t1085 + - attack.t1218.011 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_apt_judgement_panda_gtr19.yml b/rules/windows/process_creation/win_apt_judgement_panda_gtr19.yml index a9924f6e..e781f65b 100644 --- a/rules/windows/process_creation/win_apt_judgement_panda_gtr19.yml +++ b/rules/windows/process_creation/win_apt_judgement_panda_gtr19.yml @@ -12,6 +12,7 @@ tags: - attack.t1098 - attack.exfiltration - attack.t1002 + - attack.t1560 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_apt_sofacy.yml b/rules/windows/process_creation/win_apt_sofacy.yml index 15963070..2124e236 100755 --- a/rules/windows/process_creation/win_apt_sofacy.yml +++ b/rules/windows/process_creation/win_apt_sofacy.yml @@ -15,6 +15,7 @@ tags: - attack.defense_evasion - attack.t1085 - car.2013-10-002 + - attack.t1218.011 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_apt_tropictrooper.yml b/rules/windows/process_creation/win_apt_tropictrooper.yml index 69697511..7bf80dfb 100644 --- a/rules/windows/process_creation/win_apt_tropictrooper.yml +++ b/rules/windows/process_creation/win_apt_tropictrooper.yml @@ -9,6 +9,7 @@ references: tags: - attack.execution - attack.t1085 + - attack.t1218.011 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_apt_turla_comrat_may20.yml b/rules/windows/process_creation/win_apt_turla_comrat_may20.yml index c2b7bf87..23bfc182 100644 --- a/rules/windows/process_creation/win_apt_turla_comrat_may20.yml +++ b/rules/windows/process_creation/win_apt_turla_comrat_may20.yml @@ -12,6 +12,7 @@ tags: - attack.t1027 - attack.discovery - attack.t1016 + - attack.t1059.001 author: Florian Roth date: 2020/05/26 logsource: diff --git a/rules/windows/process_creation/win_apt_winnti_mal_hk_jan20.yml b/rules/windows/process_creation/win_apt_winnti_mal_hk_jan20.yml index ed6e7b42..ef29cd98 100644 --- a/rules/windows/process_creation/win_apt_winnti_mal_hk_jan20.yml +++ b/rules/windows/process_creation/win_apt_winnti_mal_hk_jan20.yml @@ -8,6 +8,7 @@ tags: - attack.defense_evasion - attack.t1073 - attack.g0044 + - attack.t1574.002 author: Florian Roth, Markus Neis date: 2020/02/01 logsource: @@ -15,9 +16,9 @@ logsource: product: windows detection: selection1: - ParentImage|contains: - - 'C:\Windows\Temp' - - '\hpqhvind.exe' + ParentImage|contains: + - 'C:\Windows\Temp' + - '\hpqhvind.exe' Image|startswith: 'C:\ProgramData\DRM' selection2: ParentImage|startswith: 'C:\ProgramData\DRM' diff --git a/rules/windows/process_creation/win_apt_zxshell.yml b/rules/windows/process_creation/win_apt_zxshell.yml index af5e6122..47a5b4f7 100755 --- a/rules/windows/process_creation/win_apt_zxshell.yml +++ b/rules/windows/process_creation/win_apt_zxshell.yml @@ -11,6 +11,7 @@ tags: - attack.t1059 - attack.defense_evasion - attack.t1085 + - attack.t1218.011 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_attrib_hiding_files.yml b/rules/windows/process_creation/win_attrib_hiding_files.yml index ec753dcf..048ae435 100644 --- a/rules/windows/process_creation/win_attrib_hiding_files.yml +++ b/rules/windows/process_creation/win_attrib_hiding_files.yml @@ -26,6 +26,7 @@ tags: - attack.defense_evasion - attack.persistence - attack.t1158 + - attack.t1564.001 falsepositives: - igfxCUIService.exe hiding *.cui files via .bat script (attrib.exe a child of cmd.exe and igfxCUIService.exe is the parent of the cmd.exe) - msiexec.exe hiding desktop.ini diff --git a/rules/windows/process_creation/win_change_default_file_association.yml b/rules/windows/process_creation/win_change_default_file_association.yml index c01a933c..db1a6be5 100644 --- a/rules/windows/process_creation/win_change_default_file_association.yml +++ b/rules/windows/process_creation/win_change_default_file_association.yml @@ -1,9 +1,7 @@ title: Change Default File Association id: 3d3aa6cd-6272-44d6-8afc-7e88dfef7061 status: experimental -description: When a file is opened, the default program used to open the file (also called the file association or handler) is checked. File association selections - are stored in the Windows Registry and can be edited by users, administrators, or programs that have Registry access or by administrators using the built-in assoc - utility. Applications can modify the file association for a given file extension to call an arbitrary program when a file with the given extension is opened. +description: When a file is opened, the default program used to open the file (also called the file association or handler) is checked. File association selections are stored in the Windows Registry and can be edited by users, administrators, or programs that have Registry access or by administrators using the built-in assoc utility. Applications can modify the file association for a given file extension to call an arbitrary program when a file with the given extension is opened. author: Timur Zinniatullin, oscd.community date: 2019/10/21 modified: 2019/11/04 @@ -15,9 +13,9 @@ logsource: detection: selection: CommandLine|contains|all: - - 'cmd' - - '/c' - - 'assoc' + - 'cmd' + - '/c' + - 'assoc' condition: selection falsepositives: - Admin activity @@ -33,3 +31,4 @@ level: low tags: - attack.persistence - attack.t1042 + - attack.t1546.001 diff --git a/rules/windows/process_creation/win_cmdkey_recon.yml b/rules/windows/process_creation/win_cmdkey_recon.yml index 9a880199..86b9126f 100644 --- a/rules/windows/process_creation/win_cmdkey_recon.yml +++ b/rules/windows/process_creation/win_cmdkey_recon.yml @@ -10,6 +10,7 @@ date: 2019/01/16 tags: - attack.credential_access - attack.t1003 + - attack.t1003.005 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_cmstp_com_object_access.yml b/rules/windows/process_creation/win_cmstp_com_object_access.yml index 67f9fe09..ffa1d6f5 100644 --- a/rules/windows/process_creation/win_cmstp_com_object_access.yml +++ b/rules/windows/process_creation/win_cmstp_com_object_access.yml @@ -10,6 +10,8 @@ tags: - attack.t1191 - attack.g0069 - car.2019-04-001 + - attack.t1548.002 + - attack.t1218 author: Nik Seetharaman modified: 2019/07/31 date: 2019/01/16 diff --git a/rules/windows/process_creation/win_control_panel_item.yml b/rules/windows/process_creation/win_control_panel_item.yml index ead8d17a..f1b50d7e 100644 --- a/rules/windows/process_creation/win_control_panel_item.yml +++ b/rules/windows/process_creation/win_control_panel_item.yml @@ -8,6 +8,7 @@ tags: - attack.execution - attack.t1196 - attack.defense_evasion + - attack.t1218 author: Kyaw Min Thein date: 2019/08/27 level: critical diff --git a/rules/windows/process_creation/win_copying_sensitive_files_with_credential_data.yml b/rules/windows/process_creation/win_copying_sensitive_files_with_credential_data.yml index f7b43d2d..50f341af 100644 --- a/rules/windows/process_creation/win_copying_sensitive_files_with_credential_data.yml +++ b/rules/windows/process_creation/win_copying_sensitive_files_with_credential_data.yml @@ -13,13 +13,15 @@ tags: - attack.credential_access - attack.t1003 - car.2013-07-001 + - attack.t1003.002 + - attack.t1003.003 logsource: category: process_creation product: windows detection: selection: - Image|endswith: '\esentutl.exe' - CommandLine|contains: + CommandLine|contains: - 'vss' - ' /m ' - ' /y ' diff --git a/rules/windows/process_creation/win_crime_fireball.yml b/rules/windows/process_creation/win_crime_fireball.yml index 8c714f37..3fca4131 100755 --- a/rules/windows/process_creation/win_crime_fireball.yml +++ b/rules/windows/process_creation/win_crime_fireball.yml @@ -12,6 +12,7 @@ tags: - attack.t1059 - attack.defense_evasion - attack.t1085 + - attack.t1218.011 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_data_compressed_with_rar.yml b/rules/windows/process_creation/win_data_compressed_with_rar.yml index b499999d..b7ed701e 100644 --- a/rules/windows/process_creation/win_data_compressed_with_rar.yml +++ b/rules/windows/process_creation/win_data_compressed_with_rar.yml @@ -29,4 +29,5 @@ falsepositives: level: low tags: - attack.exfiltration - - attack.t1002 \ No newline at end of file + - attack.t1002 + - attack.t1560 diff --git a/rules/windows/process_creation/win_encoded_frombase64string.yml b/rules/windows/process_creation/win_encoded_frombase64string.yml index 9a480ec0..92087ad2 100644 --- a/rules/windows/process_creation/win_encoded_frombase64string.yml +++ b/rules/windows/process_creation/win_encoded_frombase64string.yml @@ -9,6 +9,7 @@ tags: - attack.t1140 - attack.execution - attack.defense_evasion + - attack.t1059.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_encoded_iex.yml b/rules/windows/process_creation/win_encoded_iex.yml index 61bff8ab..e3740b9b 100644 --- a/rules/windows/process_creation/win_encoded_iex.yml +++ b/rules/windows/process_creation/win_encoded_iex.yml @@ -8,16 +8,17 @@ tags: - attack.t1086 - attack.t1140 - attack.execution + - attack.t1059.003 logsource: category: process_creation product: windows detection: selection: - CommandLine|base64offset|contains: - - 'IEX ([' - - 'iex ([' - - 'iex (New' - - 'IEX (New' + CommandLine|base64offset|contains: + - 'IEX ([' + - 'iex ([' + - 'iex (New' + - 'IEX (New' condition: selection fields: - CommandLine diff --git a/rules/windows/process_creation/win_etw_trace_evasion.yml b/rules/windows/process_creation/win_etw_trace_evasion.yml index 1a04a8dd..6b6e182f 100644 --- a/rules/windows/process_creation/win_etw_trace_evasion.yml +++ b/rules/windows/process_creation/win_etw_trace_evasion.yml @@ -10,8 +10,9 @@ author: '@neu5ron, Florian Roth' date: 2019/03/22 tags: - attack.execution - - attack.t1070 - - car.2016-04-002 + - attack.t1070 + - car.2016-04-002 + - attack.t1551 level: high logsource: category: process_creation diff --git a/rules/windows/process_creation/win_grabbing_sensitive_hives_via_reg.yml b/rules/windows/process_creation/win_grabbing_sensitive_hives_via_reg.yml index a8377a19..c7a4b601 100644 --- a/rules/windows/process_creation/win_grabbing_sensitive_hives_via_reg.yml +++ b/rules/windows/process_creation/win_grabbing_sensitive_hives_via_reg.yml @@ -11,17 +11,18 @@ tags: - attack.credential_access - attack.t1003 - car.2013-07-001 + - attack.t1003.002 logsource: category: process_creation product: windows detection: selection_1: Image: '*\reg.exe' - CommandLine|contains: + CommandLine|contains: - 'save' - 'export' selection_2: - CommandLine|contains: + CommandLine|contains: - 'hklm' - 'hkey_local_machine' selection_3: diff --git a/rules/windows/process_creation/win_hack_koadic.yml b/rules/windows/process_creation/win_hack_koadic.yml index 9e8b46fa..a012eb57 100644 --- a/rules/windows/process_creation/win_hack_koadic.yml +++ b/rules/windows/process_creation/win_hack_koadic.yml @@ -1,7 +1,7 @@ title: Koadic Execution id: 5cddf373-ef00-4112-ad72-960ac29bac34 status: experimental -description: Detects command line parameters used by Koadic hack tool +description: Detects command line parameters used by Koadic hack tool references: - https://unit42.paloaltonetworks.com/unit42-sofacy-groups-parallel-attacks/ - https://github.com/zerosum0x0/koadic/blob/master/data/stager/js/stdlib.js#L955 @@ -9,6 +9,7 @@ references: tags: - attack.execution - attack.t1170 + - attack.t1218.005 date: 2020/01/12 author: wagga logsource: diff --git a/rules/windows/process_creation/win_hack_rubeus.yml b/rules/windows/process_creation/win_hack_rubeus.yml index 9c63c07d..df77011c 100644 --- a/rules/windows/process_creation/win_hack_rubeus.yml +++ b/rules/windows/process_creation/win_hack_rubeus.yml @@ -9,6 +9,8 @@ tags: - attack.credential_access - attack.t1003 - attack.s0005 + - attack.t1558 + - attack.t1558.003 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_hh_chm.yml b/rules/windows/process_creation/win_hh_chm.yml index bbc69068..82d1791d 100644 --- a/rules/windows/process_creation/win_hh_chm.yml +++ b/rules/windows/process_creation/win_hh_chm.yml @@ -12,6 +12,7 @@ tags: - attack.defense_evasion - attack.execution - attack.t1223 + - attack.t1218.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_html_help_spawn.yml b/rules/windows/process_creation/win_html_help_spawn.yml index ed18c5c0..ce841312 100644 --- a/rules/windows/process_creation/win_html_help_spawn.yml +++ b/rules/windows/process_creation/win_html_help_spawn.yml @@ -11,6 +11,7 @@ tags: - attack.execution - attack.defense_evasion - attack.t1223 + - attack.t1218.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_hwp_exploits.yml b/rules/windows/process_creation/win_hwp_exploits.yml index d9002353..24a96f3e 100644 --- a/rules/windows/process_creation/win_hwp_exploits.yml +++ b/rules/windows/process_creation/win_hwp_exploits.yml @@ -16,6 +16,7 @@ tags: - attack.t1202 - attack.t1193 - attack.g0032 + - attack.t1566.001 author: Florian Roth date: 2019/10/24 logsource: diff --git a/rules/windows/process_creation/win_impacket_lateralization.yml b/rules/windows/process_creation/win_impacket_lateralization.yml index 52149935..c56855d6 100644 --- a/rules/windows/process_creation/win_impacket_lateralization.yml +++ b/rules/windows/process_creation/win_impacket_lateralization.yml @@ -53,6 +53,7 @@ tags: - attack.lateral_movement - attack.t1047 - attack.t1175 + - attack.t1021 falsepositives: - pentesters level: critical diff --git a/rules/windows/process_creation/win_install_reg_debugger_backdoor.yml b/rules/windows/process_creation/win_install_reg_debugger_backdoor.yml index e04fb312..34f7d609 100644 --- a/rules/windows/process_creation/win_install_reg_debugger_backdoor.yml +++ b/rules/windows/process_creation/win_install_reg_debugger_backdoor.yml @@ -8,6 +8,7 @@ tags: - attack.persistence - attack.privilege_escalation - attack.t1015 + - attack.t1546.008 author: Florian Roth date: 2019/09/06 logsource: @@ -27,4 +28,4 @@ detection: falsepositives: - Penetration Tests level: high - + diff --git a/rules/windows/process_creation/win_interactive_at.yml b/rules/windows/process_creation/win_interactive_at.yml index 3c7e0009..b28ba32e 100644 --- a/rules/windows/process_creation/win_interactive_at.yml +++ b/rules/windows/process_creation/win_interactive_at.yml @@ -11,6 +11,7 @@ modified: 2019/11/11 tags: - attack.privilege_escalation - attack.t1053 + - attack.t1053.002 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_lethalhta.yml b/rules/windows/process_creation/win_lethalhta.yml index 80496bc9..331c64c0 100644 --- a/rules/windows/process_creation/win_lethalhta.yml +++ b/rules/windows/process_creation/win_lethalhta.yml @@ -8,6 +8,7 @@ tags: - attack.defense_evasion - attack.execution - attack.t1170 + - attack.t1218.005 author: Markus Neis date: 2018/06/07 logsource: diff --git a/rules/windows/process_creation/win_lsass_dump.yml b/rules/windows/process_creation/win_lsass_dump.yml index 7514fe9c..de0ee64e 100644 --- a/rules/windows/process_creation/win_lsass_dump.yml +++ b/rules/windows/process_creation/win_lsass_dump.yml @@ -1,7 +1,6 @@ title: LSASS Memory Dumping id: ffa6861c-4461-4f59-8a41-578c39f3f23e -description: Detect creation of dump files containing the memory space of lsass.exe, which contains sensitive credentials. Identifies usage of Sysinternals procdump.exe - to export the memory space of lsass.exe which contains sensitive credentials. +description: Detect creation of dump files containing the memory space of lsass.exe, which contains sensitive credentials. Identifies usage of Sysinternals procdump.exe to export the memory space of lsass.exe which contains sensitive credentials. status: experimental author: E.M. Anhaus (orignally from Atomic Blue Detections, Tony Lambert), oscd.community date: 2019/10/24 @@ -13,6 +12,7 @@ references: tags: - attack.credential_access - attack.t1003 + - attack.t1003.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_malware_notpetya.yml b/rules/windows/process_creation/win_malware_notpetya.yml index d294395c..10ecc8a7 100644 --- a/rules/windows/process_creation/win_malware_notpetya.yml +++ b/rules/windows/process_creation/win_malware_notpetya.yml @@ -1,8 +1,7 @@ title: NotPetya Ransomware Activity id: 79aeeb41-8156-4fac-a0cd-076495ab82a1 status: experimental -description: Detects NotPetya ransomware activity in which the extracted passwords are passed back to the main module via named pipe, the file system journal of drive - C is deleted and windows eventlogs are cleared using wevtutil +description: Detects NotPetya ransomware activity in which the extracted passwords are passed back to the main module via named pipe, the file system journal of drive C is deleted and windows eventlogs are cleared using wevtutil author: Florian Roth, Tom Ueltschi date: 2019/01/16 references: @@ -16,6 +15,8 @@ tags: - attack.t1070 - attack.t1003 - car.2016-04-002 + - attack.t1218.011 + - attack.t1551 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_malware_script_dropper.yml b/rules/windows/process_creation/win_malware_script_dropper.yml index 251a3a0a..0dda1360 100644 --- a/rules/windows/process_creation/win_malware_script_dropper.yml +++ b/rules/windows/process_creation/win_malware_script_dropper.yml @@ -8,6 +8,7 @@ tags: - attack.defense_evasion - attack.execution - attack.t1064 + - attack.t1059.005 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_mimikatz_command_line.yml b/rules/windows/process_creation/win_mimikatz_command_line.yml index 11b6aa84..90ab5245 100644 --- a/rules/windows/process_creation/win_mimikatz_command_line.yml +++ b/rules/windows/process_creation/win_mimikatz_command_line.yml @@ -8,6 +8,10 @@ references: tags: - attack.credential_access - attack.t1003 + - attack.t1003.002 + - attack.t1003.004 + - attack.t1003.001 + - attack.t1003.006 logsource: category: process_creation product: windows @@ -30,8 +34,7 @@ detection: selection_3: CommandLine|contains: - '::' - condition: selection_1 or - selection_2 and selection_3 + condition: selection_1 or selection_2 and selection_3 falsepositives: - Legitimate Administrator using tool for password recovery level: medium diff --git a/rules/windows/process_creation/win_mmc_spawn_shell.yml b/rules/windows/process_creation/win_mmc_spawn_shell.yml index bf207beb..dc0dfb5a 100644 --- a/rules/windows/process_creation/win_mmc_spawn_shell.yml +++ b/rules/windows/process_creation/win_mmc_spawn_shell.yml @@ -7,6 +7,10 @@ date: 2019/08/05 tags: - attack.lateral_movement - attack.t1175 + - attack.t1059.004 + - attack.t1059.005 + - attack.t1059.003 + - attack.t1059.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_mshta_javascript.yml b/rules/windows/process_creation/win_mshta_javascript.yml index a52c88d1..62b7d608 100644 --- a/rules/windows/process_creation/win_mshta_javascript.yml +++ b/rules/windows/process_creation/win_mshta_javascript.yml @@ -12,6 +12,7 @@ tags: - attack.execution - attack.defense_evasion - attack.t1170 + - attack.t1218.005 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_mshta_spawn_shell.yml b/rules/windows/process_creation/win_mshta_spawn_shell.yml index 3909f721..f6900f53 100644 --- a/rules/windows/process_creation/win_mshta_spawn_shell.yml +++ b/rules/windows/process_creation/win_mshta_spawn_shell.yml @@ -33,6 +33,7 @@ tags: - car.2013-02-003 - car.2013-03-001 - car.2014-04-003 + - attack.t1218 falsepositives: - Printer software / driver installations - HP software diff --git a/rules/windows/process_creation/win_netsh_allow_port_rdp.yml b/rules/windows/process_creation/win_netsh_allow_port_rdp.yml index f2fc0607..def36dc7 100644 --- a/rules/windows/process_creation/win_netsh_allow_port_rdp.yml +++ b/rules/windows/process_creation/win_netsh_allow_port_rdp.yml @@ -1,5 +1,5 @@ title: Netsh RDP Port Opening -id: 01aeb693-138d-49d2-9403-c4f52d7d3d62 +id: 01aeb693-138d-49d2-9403-c4f52d7d3d62 description: Detects netsh commands that opens the port 3389 used for RDP, used in Sarwent Malware references: - https://labs.sentinelone.com/sarwent-malware-updates-command-detonation/ @@ -7,6 +7,7 @@ date: 2020/05/23 tags: - attack.command_and_control - attack.t1076 + - attack.t1021.001 status: experimental author: Sander Wiebing logsource: diff --git a/rules/windows/process_creation/win_new_service_creation.yml b/rules/windows/process_creation/win_new_service_creation.yml index 67d6ae36..e8a3c4bb 100644 --- a/rules/windows/process_creation/win_new_service_creation.yml +++ b/rules/windows/process_creation/win_new_service_creation.yml @@ -9,6 +9,7 @@ tags: - attack.persistence - attack.privilege_escalation - attack.t1050 + - attack.t1543.003 references: - https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1050/T1050.yaml logsource: @@ -16,11 +17,11 @@ logsource: product: windows detection: selection: - - Image|endswith: '\sc.exe' + - Image|endswith: '\sc.exe' CommandLine|contains|all: - 'create' - 'binpath' - - Image|endswith: '\powershell.exe' + - Image|endswith: '\powershell.exe' CommandLine|contains: 'new-service' condition: selection falsepositives: diff --git a/rules/windows/process_creation/win_non_interactive_powershell.yml b/rules/windows/process_creation/win_non_interactive_powershell.yml index 0333dde0..7855ea3a 100644 --- a/rules/windows/process_creation/win_non_interactive_powershell.yml +++ b/rules/windows/process_creation/win_non_interactive_powershell.yml @@ -10,11 +10,12 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 logsource: category: process_creation product: windows detection: - selection: + selection: Image|endswith: '\powershell.exe' filter: ParentImage|endswith: '\explorer.exe' diff --git a/rules/windows/process_creation/win_office_shell.yml b/rules/windows/process_creation/win_office_shell.yml index aa29383e..537def03 100644 --- a/rules/windows/process_creation/win_office_shell.yml +++ b/rules/windows/process_creation/win_office_shell.yml @@ -12,6 +12,7 @@ tags: - attack.t1202 - car.2013-02-003 - car.2014-04-003 + - attack.t1059.003 author: Michael Haag, Florian Roth, Markus Neis date: 2018/04/06 logsource: diff --git a/rules/windows/process_creation/win_plugx_susp_exe_locations.yml b/rules/windows/process_creation/win_plugx_susp_exe_locations.yml index 5d8a8035..64c87d03 100644 --- a/rules/windows/process_creation/win_plugx_susp_exe_locations.yml +++ b/rules/windows/process_creation/win_plugx_susp_exe_locations.yml @@ -11,6 +11,7 @@ tags: - attack.s0013 - attack.defense_evasion - attack.t1073 + - attack.t1574.002 logsource: category: process_creation product: windows @@ -84,10 +85,7 @@ detection: - '*\Windows Kit*' - '*\Windows Resource Kit\\*' - '*\Microsoft.NET\\*' - condition: ( selection_cammute and not filter_cammute ) or ( selection_chrome_frame and not filter_chrome_frame ) or ( selection_devemu and not filter_devemu ) - or ( selection_gadget and not filter_gadget ) or ( selection_hcc and not filter_hcc ) or ( selection_hkcmd and not filter_hkcmd ) or ( selection_mc and not filter_mc - ) or ( selection_msmpeng and not filter_msmpeng ) or ( selection_msseces and not filter_msseces ) or ( selection_oinfo and not filter_oinfo ) or ( selection_oleview - and not filter_oleview ) or ( selection_rc and not filter_rc ) + condition: ( selection_cammute and not filter_cammute ) or ( selection_chrome_frame and not filter_chrome_frame ) or ( selection_devemu and not filter_devemu ) or ( selection_gadget and not filter_gadget ) or ( selection_hcc and not filter_hcc ) or ( selection_hkcmd and not filter_hkcmd ) or ( selection_mc and not filter_mc ) or ( selection_msmpeng and not filter_msmpeng ) or ( selection_msseces and not filter_msseces ) or ( selection_oinfo and not filter_oinfo ) or ( selection_oleview and not filter_oleview ) or ( selection_rc and not filter_rc ) fields: - CommandLine - ParentCommandLine diff --git a/rules/windows/process_creation/win_possible_applocker_bypass.yml b/rules/windows/process_creation/win_possible_applocker_bypass.yml index 65b988f8..b0b0853a 100644 --- a/rules/windows/process_creation/win_possible_applocker_bypass.yml +++ b/rules/windows/process_creation/win_possible_applocker_bypass.yml @@ -13,6 +13,7 @@ tags: - attack.t1121 - attack.t1127 - attack.t1170 + - attack.t1218 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_powershell_amsi_bypass.yml b/rules/windows/process_creation/win_powershell_amsi_bypass.yml index 0211555b..335aadc3 100644 --- a/rules/windows/process_creation/win_powershell_amsi_bypass.yml +++ b/rules/windows/process_creation/win_powershell_amsi_bypass.yml @@ -9,6 +9,7 @@ tags: - attack.execution - attack.defense_evasion - attack.t1086 + - attack.t1059.001 author: Markus Neis date: 2018/08/17 logsource: diff --git a/rules/windows/process_creation/win_powershell_dll_execution.yml b/rules/windows/process_creation/win_powershell_dll_execution.yml index 4cb036d6..1e8ff007 100644 --- a/rules/windows/process_creation/win_powershell_dll_execution.yml +++ b/rules/windows/process_creation/win_powershell_dll_execution.yml @@ -8,6 +8,7 @@ tags: - attack.execution - attack.t1086 - car.2014-04-003 + - attack.t1059.001 author: Markus Neis date: 2018/08/25 logsource: diff --git a/rules/windows/process_creation/win_powershell_downgrade_attack.yml b/rules/windows/process_creation/win_powershell_downgrade_attack.yml index d9781724..3d6c063f 100644 --- a/rules/windows/process_creation/win_powershell_downgrade_attack.yml +++ b/rules/windows/process_creation/win_powershell_downgrade_attack.yml @@ -1,7 +1,7 @@ title: PowerShell Downgrade Attack id: b3512211-c67e-4707-bedc-66efc7848863 related: - - id: 6331d09b-4785-4c13-980f-f96661356249 + - id: 6331d09b-4785-4c13-980f-f96661356249 type: derived status: experimental description: Detects PowerShell downgrade attack by comparing the host versions with the actually used engine version 2.0 @@ -11,6 +11,7 @@ tags: - attack.defense_evasion - attack.execution - attack.t1086 + - attack.t1059.001 author: Harish Segar (rule) date: 2020/03/20 falsepositives: @@ -22,12 +23,12 @@ logsource: product: windows detection: selection: - CommandLine|contains: + CommandLine|contains: - ' -version 2 ' - ' -versio 2 ' - ' -versi 2 ' - ' -vers 2 ' - ' -ver 2 ' - - ' -ve 2 ' + - ' -ve 2 ' Image|endswith: '\powershell.exe' condition: selection diff --git a/rules/windows/process_creation/win_powershell_download.yml b/rules/windows/process_creation/win_powershell_download.yml index 83b93e13..813a45bf 100644 --- a/rules/windows/process_creation/win_powershell_download.yml +++ b/rules/windows/process_creation/win_powershell_download.yml @@ -7,6 +7,7 @@ date: 2019/01/16 tags: - attack.t1086 - attack.execution + - attack.t1059.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_powershell_suspicious_parameter_variation.yml b/rules/windows/process_creation/win_powershell_suspicious_parameter_variation.yml index 41a0f1cd..14100059 100644 --- a/rules/windows/process_creation/win_powershell_suspicious_parameter_variation.yml +++ b/rules/windows/process_creation/win_powershell_suspicious_parameter_variation.yml @@ -7,6 +7,7 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 author: Florian Roth (rule), Daniel Bohannon (idea), Roberto Rodriguez (Fix) date: 2019/01/16 logsource: diff --git a/rules/windows/process_creation/win_powershell_xor_commandline.yml b/rules/windows/process_creation/win_powershell_xor_commandline.yml index c7d39c95..150a13e7 100644 --- a/rules/windows/process_creation/win_powershell_xor_commandline.yml +++ b/rules/windows/process_creation/win_powershell_xor_commandline.yml @@ -7,6 +7,7 @@ date: 2018/09/05 tags: - attack.execution - attack.t1086 + - attack.t1059.001 detection: selection: CommandLine: diff --git a/rules/windows/process_creation/win_powersploit_empire_schtasks.yml b/rules/windows/process_creation/win_powersploit_empire_schtasks.yml index e6f689ca..a3094b5b 100644 --- a/rules/windows/process_creation/win_powersploit_empire_schtasks.yml +++ b/rules/windows/process_creation/win_powersploit_empire_schtasks.yml @@ -31,6 +31,8 @@ tags: - attack.g0022 - attack.g0060 - car.2013-08-001 + - attack.t1053.005 + - attack.t1059.001 falsepositives: - False positives are possible, depends on organisation and processes level: high diff --git a/rules/windows/process_creation/win_process_dump_rundll32_comsvcs.yml b/rules/windows/process_creation/win_process_dump_rundll32_comsvcs.yml index 88e15976..5d85fbdf 100644 --- a/rules/windows/process_creation/win_process_dump_rundll32_comsvcs.yml +++ b/rules/windows/process_creation/win_process_dump_rundll32_comsvcs.yml @@ -12,6 +12,7 @@ tags: - attack.credential_access - attack.t1003 - car.2013-05-009 + - attack.t1003.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_psexesvc_start.yml b/rules/windows/process_creation/win_psexesvc_start.yml index 5c77a450..a2c3dbf1 100644 --- a/rules/windows/process_creation/win_psexesvc_start.yml +++ b/rules/windows/process_creation/win_psexesvc_start.yml @@ -8,12 +8,13 @@ tags: - attack.execution - attack.t1035 - attack.s0029 + - attack.t1569.002 logsource: category: process_creation product: windows detection: selection: - CommandLine: C:\Windows\PSEXESVC.exe + CommandLine: C:\Windows\PSEXESVC.exe condition: selection falsepositives: - Administrative activity diff --git a/rules/windows/process_creation/win_remote_powershell_session_process.yml b/rules/windows/process_creation/win_remote_powershell_session_process.yml index cdd0ce0d..5509721e 100644 --- a/rules/windows/process_creation/win_remote_powershell_session_process.yml +++ b/rules/windows/process_creation/win_remote_powershell_session_process.yml @@ -10,6 +10,7 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_run_powershell_script_from_ads.yml b/rules/windows/process_creation/win_run_powershell_script_from_ads.yml index b4a03177..eaa76e6c 100644 --- a/rules/windows/process_creation/win_run_powershell_script_from_ads.yml +++ b/rules/windows/process_creation/win_run_powershell_script_from_ads.yml @@ -9,6 +9,7 @@ date: 2019/10/30 tags: - attack.defense_evasion - attack.t1096 + - attack.t1564.004 logsource: category: process_creation product: windows @@ -16,9 +17,9 @@ detection: selection: ParentImage|endswith: '\powershell.exe' Image|endswith: '\powershell.exe' - CommandLine|contains|all: - - 'Get-Content' - - '-Stream' + CommandLine|contains|all: + - 'Get-Content' + - '-Stream' condition: selection falsepositives: - Unknown diff --git a/rules/windows/process_creation/win_sdbinst_shim_persistence.yml b/rules/windows/process_creation/win_sdbinst_shim_persistence.yml index 1509516e..b98a0c86 100644 --- a/rules/windows/process_creation/win_sdbinst_shim_persistence.yml +++ b/rules/windows/process_creation/win_sdbinst_shim_persistence.yml @@ -7,6 +7,7 @@ references: tags: - attack.persistence - attack.t1138 + - attack.t1546.011 author: Markus Neis date: 2019/01/16 logsource: diff --git a/rules/windows/process_creation/win_service_execution.yml b/rules/windows/process_creation/win_service_execution.yml index 865e7a22..72b3903f 100644 --- a/rules/windows/process_creation/win_service_execution.yml +++ b/rules/windows/process_creation/win_service_execution.yml @@ -12,7 +12,7 @@ logsource: product: windows detection: selection: - Image|endswith: + Image|endswith: - '\net.exe' - '\net1.exe' CommandLine|contains: ' start ' # space character after the 'start' keyword indicates that a service name follows, in contrast to `net start` discovery expression @@ -23,3 +23,4 @@ level: low tags: - attack.execution - attack.t1035 + - attack.t1569.002 diff --git a/rules/windows/process_creation/win_shadow_copies_access_symlink.yml b/rules/windows/process_creation/win_shadow_copies_access_symlink.yml index 17c6d56d..45149619 100644 --- a/rules/windows/process_creation/win_shadow_copies_access_symlink.yml +++ b/rules/windows/process_creation/win_shadow_copies_access_symlink.yml @@ -8,14 +8,16 @@ references: tags: - attack.credential_access - attack.t1003 + - attack.t1003.002 + - attack.t1003.003 logsource: category: process_creation product: windows detection: selection: - CommandLine|contains|all: - - mklink - - HarddiskVolumeShadowCopy + CommandLine|contains|all: + - mklink + - HarddiskVolumeShadowCopy condition: selection falsepositives: - Legitimate administrator working with shadow copies, access for backup purposes diff --git a/rules/windows/process_creation/win_shadow_copies_creation.yml b/rules/windows/process_creation/win_shadow_copies_creation.yml index 828c54a5..578c1ba1 100644 --- a/rules/windows/process_creation/win_shadow_copies_creation.yml +++ b/rules/windows/process_creation/win_shadow_copies_creation.yml @@ -9,6 +9,8 @@ references: tags: - attack.credential_access - attack.t1003 + - attack.t1003.002 + - attack.t1003.003 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_shadow_copies_deletion.yml b/rules/windows/process_creation/win_shadow_copies_deletion.yml index 43bdfd90..d017b359 100644 --- a/rules/windows/process_creation/win_shadow_copies_deletion.yml +++ b/rules/windows/process_creation/win_shadow_copies_deletion.yml @@ -15,6 +15,7 @@ tags: - attack.impact - attack.t1070 - attack.t1490 + - attack.t1551 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_shell_spawn_susp_program.yml b/rules/windows/process_creation/win_shell_spawn_susp_program.yml index 1a77be48..17968c3b 100644 --- a/rules/windows/process_creation/win_shell_spawn_susp_program.yml +++ b/rules/windows/process_creation/win_shell_spawn_susp_program.yml @@ -11,6 +11,8 @@ tags: - attack.execution - attack.defense_evasion - attack.t1064 + - attack.t1059.005 + - attack.t1059.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_spn_enum.yml b/rules/windows/process_creation/win_spn_enum.yml index 21638ae3..7bc87568 100644 --- a/rules/windows/process_creation/win_spn_enum.yml +++ b/rules/windows/process_creation/win_spn_enum.yml @@ -9,6 +9,7 @@ date: 2018/11/14 tags: - attack.credential_access - attack.t1208 + - attack.t1558.003 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_susp_bcdedit.yml b/rules/windows/process_creation/win_susp_bcdedit.yml index 47b52713..7b74bef4 100644 --- a/rules/windows/process_creation/win_susp_bcdedit.yml +++ b/rules/windows/process_creation/win_susp_bcdedit.yml @@ -11,6 +11,8 @@ tags: - attack.t1070 - attack.persistence - attack.t1067 + - attack.t1551 + - attack.t1542.003 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_susp_cmd_http_appdata.yml b/rules/windows/process_creation/win_susp_cmd_http_appdata.yml index 92445f87..64efc023 100644 --- a/rules/windows/process_creation/win_susp_cmd_http_appdata.yml +++ b/rules/windows/process_creation/win_susp_cmd_http_appdata.yml @@ -1,8 +1,7 @@ title: Command Line Execution with Suspicious URL and AppData Strings id: 1ac8666b-046f-4201-8aba-1951aaec03a3 status: experimental -description: Detects a suspicious command line execution that includes an URL and AppData string in the command line parameters as used by several droppers (js/vbs - > powershell) +description: Detects a suspicious command line execution that includes an URL and AppData string in the command line parameters as used by several droppers (js/vbs > powershell) references: - https://www.hybrid-analysis.com/sample/3a1f01206684410dbe8f1900bbeaaa543adfcd07368ba646b499fa5274b9edf6?environmentId=100 - https://www.hybrid-analysis.com/sample/f16c729aad5c74f19784a24257236a8bbe27f7cdc4a89806031ec7f1bebbd475?environmentId=100 @@ -11,6 +10,8 @@ date: 2019/01/16 tags: - attack.execution - attack.t1059 + - attack.t1059.005 + - attack.t1059.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_susp_compression_params.yml b/rules/windows/process_creation/win_susp_compression_params.yml index e3e5c980..cb5a3cc9 100644 --- a/rules/windows/process_creation/win_susp_compression_params.yml +++ b/rules/windows/process_creation/win_susp_compression_params.yml @@ -8,6 +8,7 @@ tags: - attack.exfiltration - attack.t1020 - attack.t1002 + - attack.t1560 author: Florian Roth, Samir Bousseaden date: 2019/10/15 logsource: diff --git a/rules/windows/process_creation/win_susp_comsvcs_procdump.yml b/rules/windows/process_creation/win_susp_comsvcs_procdump.yml index bcab5a8e..be58a43a 100644 --- a/rules/windows/process_creation/win_susp_comsvcs_procdump.yml +++ b/rules/windows/process_creation/win_susp_comsvcs_procdump.yml @@ -26,6 +26,7 @@ fields: tags: - attack.credential_access - attack.t1003 + - attack.t1003.001 falsepositives: - unknown level: medium diff --git a/rules/windows/process_creation/win_susp_control_dll_load.yml b/rules/windows/process_creation/win_susp_control_dll_load.yml index 00eaf7a6..cc049031 100644 --- a/rules/windows/process_creation/win_susp_control_dll_load.yml +++ b/rules/windows/process_creation/win_susp_control_dll_load.yml @@ -11,6 +11,8 @@ tags: - attack.t1073 - attack.t1085 - car.2013-10-002 + - attack.t1218 + - attack.t1574.002 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_susp_copy_lateral_movement.yml b/rules/windows/process_creation/win_susp_copy_lateral_movement.yml index 6d56fec2..10b56613 100644 --- a/rules/windows/process_creation/win_susp_copy_lateral_movement.yml +++ b/rules/windows/process_creation/win_susp_copy_lateral_movement.yml @@ -2,22 +2,23 @@ title: Copy from Admin Share id: 855bc8b5-2ae8-402e-a9ed-b889e6df1900 status: experimental description: Detects a suspicious copy command from a remote C$ or ADMIN$ share -references: - - https://twitter.com/SBousseaden/status/1211636381086339073 +references: + - https://twitter.com/SBousseaden/status/1211636381086339073 author: Florian Roth date: 2019/12/30 tags: - attack.lateral_movement - attack.t1077 - attack.t1105 + - attack.t1021 logsource: category: process_creation product: windows detection: selection: - CommandLine|contains: - - 'copy *\c$' - - 'copy *\ADMIN$' + CommandLine|contains: + - 'copy *\c$' + - 'copy *\ADMIN$' condition: selection fields: - CommandLine diff --git a/rules/windows/process_creation/win_susp_crackmapexec_execution.yml b/rules/windows/process_creation/win_susp_crackmapexec_execution.yml index ed8904ba..98071a31 100644 --- a/rules/windows/process_creation/win_susp_crackmapexec_execution.yml +++ b/rules/windows/process_creation/win_susp_crackmapexec_execution.yml @@ -9,6 +9,8 @@ tags: - attack.t1047 - attack.t1053 - attack.t1086 + - attack.t1059.003 + - attack.t1059.001 author: Thomas Patzke date: 2020/05/22 logsource: diff --git a/rules/windows/process_creation/win_susp_crackmapexec_powershell_obfuscation.yml b/rules/windows/process_creation/win_susp_crackmapexec_powershell_obfuscation.yml index 0d943703..20bb2c13 100644 --- a/rules/windows/process_creation/win_susp_crackmapexec_powershell_obfuscation.yml +++ b/rules/windows/process_creation/win_susp_crackmapexec_powershell_obfuscation.yml @@ -10,6 +10,7 @@ tags: - attack.t1086 - attack.defense_evasion - attack.t1027 + - attack.t1059.001 author: Thomas Patzke date: 2020/05/22 logsource: diff --git a/rules/windows/process_creation/win_susp_csc_folder.yml b/rules/windows/process_creation/win_susp_csc_folder.yml index fb2a5fdf..9752e5ff 100644 --- a/rules/windows/process_creation/win_susp_csc_folder.yml +++ b/rules/windows/process_creation/win_susp_csc_folder.yml @@ -13,17 +13,18 @@ modified: 2019/12/17 tags: - attack.defense_evasion - attack.t1500 + - attack.t1027 logsource: category: process_creation product: windows detection: selection: Image: '*\csc.exe' - CommandLine: + CommandLine: - '*\AppData\\*' - '*\Windows\Temp\\*' filter: - ParentImage: + ParentImage: - 'C:\Program Files*' # https://twitter.com/gN3mes1s/status/1206874118282448897 - '*\sdiagnhost.exe' # https://twitter.com/gN3mes1s/status/1206874118282448897 - '*\w3wp.exe' # https://twitter.com/gabriele_pippi/status/1206907900268072962 diff --git a/rules/windows/process_creation/win_susp_direct_asep_reg_keys_modification.yml b/rules/windows/process_creation/win_susp_direct_asep_reg_keys_modification.yml index 3a6bf756..490884fe 100644 --- a/rules/windows/process_creation/win_susp_direct_asep_reg_keys_modification.yml +++ b/rules/windows/process_creation/win_susp_direct_asep_reg_keys_modification.yml @@ -7,6 +7,7 @@ references: tags: - attack.persistence - attack.t1060 + - attack.t1547.001 date: 2019/10/25 modified: 2019/11/10 author: Victor Sergeev, Daniil Yugoslavskiy, oscd.community diff --git a/rules/windows/process_creation/win_susp_double_extension.yml b/rules/windows/process_creation/win_susp_double_extension.yml index 95a5a0e3..8b6ca56a 100644 --- a/rules/windows/process_creation/win_susp_double_extension.yml +++ b/rules/windows/process_creation/win_susp_double_extension.yml @@ -1,7 +1,6 @@ title: Suspicious Double Extension id: 1cdd9a09-06c9-4769-99ff-626e2b3991b8 -description: Detects suspicious use of an .exe extension after a non-executable file extension like .pdf.exe, a set of spaces or underlines to cloak the executable - file in spear phishing campaigns +description: Detects suspicious use of an .exe extension after a non-executable file extension like .pdf.exe, a set of spaces or underlines to cloak the executable file in spear phishing campaigns references: - https://blu3-team.blogspot.com/2019/06/misleading-extensions-xlsexe-docexe.html - https://twitter.com/blackorbird/status/1140519090961825792 @@ -10,12 +9,13 @@ date: 2019/06/26 tags: - attack.initial_access - attack.t1193 + - attack.t1566.001 logsource: category: process_creation product: windows detection: selection: - Image: + Image: - '*.doc.exe' - '*.docx.exe' - '*.xls.exe' @@ -28,6 +28,6 @@ detection: - '* .exe' - '*______.exe' condition: selection -falsepositives: +falsepositives: - Unknown level: critical diff --git a/rules/windows/process_creation/win_susp_eventlog_clear.yml b/rules/windows/process_creation/win_susp_eventlog_clear.yml index 8100a2e4..b0e27546 100644 --- a/rules/windows/process_creation/win_susp_eventlog_clear.yml +++ b/rules/windows/process_creation/win_susp_eventlog_clear.yml @@ -11,6 +11,7 @@ tags: - attack.defense_evasion - attack.t1070 - car.2016-04-002 + - attack.t1551 level: high logsource: category: process_creation @@ -19,14 +20,14 @@ detection: selection_wevtutil_binary: Image|endswith: '\wevtutil.exe' selection_wevtutil_command: - CommandLine|contains: + CommandLine|contains: - 'clear-log' # clears specified log - ' cl ' # short version of 'clear-log' - 'set-log' # modifies config of specified log. could be uset to set it to a tiny size - ' sl ' # short version of 'set-log' selection_other_ps: Image|endswith: '\powershell.exe' - CommandLine|contains: + CommandLine|contains: - 'Clear-EventLog' - 'Remove-EventLog' - 'Limit-EventLog' diff --git a/rules/windows/process_creation/win_susp_execution_path_webserver.yml b/rules/windows/process_creation/win_susp_execution_path_webserver.yml index be5af625..8398dc4c 100644 --- a/rules/windows/process_creation/win_susp_execution_path_webserver.yml +++ b/rules/windows/process_creation/win_susp_execution_path_webserver.yml @@ -7,6 +7,7 @@ date: 2019/01/16 tags: - attack.persistence - attack.t1100 + - attack.t1505.003 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_susp_file_characteristics.yml b/rules/windows/process_creation/win_susp_file_characteristics.yml index 8243fe88..cb900eee 100644 --- a/rules/windows/process_creation/win_susp_file_characteristics.yml +++ b/rules/windows/process_creation/win_susp_file_characteristics.yml @@ -12,6 +12,7 @@ tags: - attack.defense_evasion - attack.execution - attack.t1064 + - attack.t1059.006 logsource: product: windows category: process_creation diff --git a/rules/windows/process_creation/win_susp_fsutil_usage.yml b/rules/windows/process_creation/win_susp_fsutil_usage.yml index e204a9d7..e7a3d0c9 100644 --- a/rules/windows/process_creation/win_susp_fsutil_usage.yml +++ b/rules/windows/process_creation/win_susp_fsutil_usage.yml @@ -12,6 +12,7 @@ references: tags: - attack.defense_evasion - attack.t1070 + - attack.t1551 logsource: category: process_creation product: windows @@ -21,7 +22,7 @@ detection: binary_2: OriginalFileName: 'fsutil.exe' selection: - CommandLine|contains: + CommandLine|contains: - 'deletejournal' # usn deletejournal ==> generally ransomware or attacker - 'createjournal' # usn createjournal ==> can modify config to set it to a tiny size condition: (1 of binary_*) and selection diff --git a/rules/windows/process_creation/win_susp_gup.yml b/rules/windows/process_creation/win_susp_gup.yml index e9fbbc95..1fd19502 100644 --- a/rules/windows/process_creation/win_susp_gup.yml +++ b/rules/windows/process_creation/win_susp_gup.yml @@ -7,6 +7,7 @@ references: tags: - attack.defense_evasion - attack.t1073 + - attack.t1574.002 author: Florian Roth date: 2019/02/06 logsource: diff --git a/rules/windows/process_creation/win_susp_iss_module_install.yml b/rules/windows/process_creation/win_susp_iss_module_install.yml index d9b0a18e..7970eaf4 100644 --- a/rules/windows/process_creation/win_susp_iss_module_install.yml +++ b/rules/windows/process_creation/win_susp_iss_module_install.yml @@ -9,6 +9,7 @@ date: 2012/12/11 tags: - attack.persistence - attack.t1100 + - attack.t1505.003 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_susp_net_execution.yml b/rules/windows/process_creation/win_susp_net_execution.yml index fa11306c..21f8f346 100644 --- a/rules/windows/process_creation/win_susp_net_execution.yml +++ b/rules/windows/process_creation/win_susp_net_execution.yml @@ -18,6 +18,7 @@ tags: - attack.lateral_movement - attack.discovery - attack.defense_evasion + - attack.t1021 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_susp_netsh_dll_persistence.yml b/rules/windows/process_creation/win_susp_netsh_dll_persistence.yml index 885268c5..102e607b 100644 --- a/rules/windows/process_creation/win_susp_netsh_dll_persistence.yml +++ b/rules/windows/process_creation/win_susp_netsh_dll_persistence.yml @@ -7,12 +7,13 @@ references: tags: - attack.persistence - attack.t1128 + - attack.t1546.007 date: 2019/10/25 modified: 2019/10/25 author: Victor Sergeev, oscd.community logsource: category: process_creation - product: windows + product: windows detection: selection: Image|endswith: '\netsh.exe' diff --git a/rules/windows/process_creation/win_susp_ntdsutil.yml b/rules/windows/process_creation/win_susp_ntdsutil.yml index a8c2f6fd..ba0e49e3 100644 --- a/rules/windows/process_creation/win_susp_ntdsutil.yml +++ b/rules/windows/process_creation/win_susp_ntdsutil.yml @@ -9,6 +9,7 @@ date: 2019/01/16 tags: - attack.credential_access - attack.t1003 + - attack.t1003.003 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_susp_outlook_temp.yml b/rules/windows/process_creation/win_susp_outlook_temp.yml index b841940b..19a11004 100644 --- a/rules/windows/process_creation/win_susp_outlook_temp.yml +++ b/rules/windows/process_creation/win_susp_outlook_temp.yml @@ -7,6 +7,7 @@ date: 2019/10/01 tags: - attack.initial_access - attack.t1193 + - attack.t1566.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_susp_powershell_empire_launch.yml b/rules/windows/process_creation/win_susp_powershell_empire_launch.yml index a45c4801..1097603f 100644 --- a/rules/windows/process_creation/win_susp_powershell_empire_launch.yml +++ b/rules/windows/process_creation/win_susp_powershell_empire_launch.yml @@ -10,8 +10,9 @@ references: author: Florian Roth date: 2019/04/20 tags: - - attack.execution - - attack.t1086 + - attack.execution + - attack.t1086 + - attack.t1059.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_susp_powershell_empire_uac_bypass.yml b/rules/windows/process_creation/win_susp_powershell_empire_uac_bypass.yml index 0d662e28..493e7220 100644 --- a/rules/windows/process_creation/win_susp_powershell_empire_uac_bypass.yml +++ b/rules/windows/process_creation/win_susp_powershell_empire_uac_bypass.yml @@ -24,6 +24,7 @@ tags: - attack.privilege_escalation - attack.t1088 - car.2019-04-001 + - attack.t1548.002 falsepositives: - unknown level: critical diff --git a/rules/windows/process_creation/win_susp_powershell_enc_cmd.yml b/rules/windows/process_creation/win_susp_powershell_enc_cmd.yml index e6ccc632..feb5a72d 100644 --- a/rules/windows/process_creation/win_susp_powershell_enc_cmd.yml +++ b/rules/windows/process_creation/win_susp_powershell_enc_cmd.yml @@ -8,8 +8,9 @@ author: Florian Roth, Markus Neis date: 2018/09/03 modified: 2019/12/16 tags: - - attack.execution - - attack.t1086 + - attack.execution + - attack.t1086 + - attack.t1059.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_susp_powershell_hidden_b64_cmd.yml b/rules/windows/process_creation/win_susp_powershell_hidden_b64_cmd.yml index 7da4d36d..417c37dc 100644 --- a/rules/windows/process_creation/win_susp_powershell_hidden_b64_cmd.yml +++ b/rules/windows/process_creation/win_susp_powershell_hidden_b64_cmd.yml @@ -7,6 +7,7 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 author: John Lambert (rule) date: 2019/01/16 logsource: diff --git a/rules/windows/process_creation/win_susp_powershell_parent_combo.yml b/rules/windows/process_creation/win_susp_powershell_parent_combo.yml index 32e9e296..dfb15868 100644 --- a/rules/windows/process_creation/win_susp_powershell_parent_combo.yml +++ b/rules/windows/process_creation/win_susp_powershell_parent_combo.yml @@ -9,6 +9,7 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_susp_procdump.yml b/rules/windows/process_creation/win_susp_procdump.yml index a450ce4b..bfa3d6ff 100644 --- a/rules/windows/process_creation/win_susp_procdump.yml +++ b/rules/windows/process_creation/win_susp_procdump.yml @@ -13,6 +13,7 @@ tags: - attack.credential_access - attack.t1003 - car.2013-05-009 + - attack.t1003.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_susp_ps_appdata.yml b/rules/windows/process_creation/win_susp_ps_appdata.yml index b4663c8f..13c16b3a 100644 --- a/rules/windows/process_creation/win_susp_ps_appdata.yml +++ b/rules/windows/process_creation/win_susp_ps_appdata.yml @@ -8,6 +8,7 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 author: Florian Roth date: 2019/01/09 logsource: diff --git a/rules/windows/process_creation/win_susp_ps_downloadfile.yml b/rules/windows/process_creation/win_susp_ps_downloadfile.yml index 5fe3001d..f2440a8a 100644 --- a/rules/windows/process_creation/win_susp_ps_downloadfile.yml +++ b/rules/windows/process_creation/win_susp_ps_downloadfile.yml @@ -9,12 +9,13 @@ date: 2020/03/25 tags: - attack.execution - attack.t1086 + - attack.t1059.001 logsource: category: process_creation product: windows detection: selection: - CommandLine|contains|all: + CommandLine|contains|all: - 'powershell' - '.DownloadFile' - 'System.Net.WebClient' diff --git a/rules/windows/process_creation/win_susp_rasdial_activity.yml b/rules/windows/process_creation/win_susp_rasdial_activity.yml index 6a4b0233..e9959628 100644 --- a/rules/windows/process_creation/win_susp_rasdial_activity.yml +++ b/rules/windows/process_creation/win_susp_rasdial_activity.yml @@ -10,6 +10,7 @@ tags: - attack.defense_evasion - attack.execution - attack.t1064 + - attack.t1059 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_susp_regsvr32_anomalies.yml b/rules/windows/process_creation/win_susp_regsvr32_anomalies.yml index ce51e4b7..a19bdbf7 100644 --- a/rules/windows/process_creation/win_susp_regsvr32_anomalies.yml +++ b/rules/windows/process_creation/win_susp_regsvr32_anomalies.yml @@ -12,6 +12,7 @@ tags: - attack.execution - car.2019-04-002 - car.2019-04-003 + - attack.t1218 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_susp_rundll32_activity.yml b/rules/windows/process_creation/win_susp_rundll32_activity.yml index c388da17..a7dedd20 100644 --- a/rules/windows/process_creation/win_susp_rundll32_activity.yml +++ b/rules/windows/process_creation/win_susp_rundll32_activity.yml @@ -10,6 +10,7 @@ tags: - attack.defense_evasion - attack.execution - attack.t1085 + - attack.t1218.011 author: juju4 date: 2019/01/16 logsource: diff --git a/rules/windows/process_creation/win_susp_rundll32_by_ordinal.yml b/rules/windows/process_creation/win_susp_rundll32_by_ordinal.yml index 44f830c9..0867f34b 100644 --- a/rules/windows/process_creation/win_susp_rundll32_by_ordinal.yml +++ b/rules/windows/process_creation/win_susp_rundll32_by_ordinal.yml @@ -10,6 +10,7 @@ tags: - attack.defense_evasion - attack.execution - attack.t1085 + - attack.t1218.011 author: Florian Roth date: 2019/10/22 logsource: diff --git a/rules/windows/process_creation/win_susp_schtask_creation.yml b/rules/windows/process_creation/win_susp_schtask_creation.yml index 7c2d3fa6..9a33912a 100644 --- a/rules/windows/process_creation/win_susp_schtask_creation.yml +++ b/rules/windows/process_creation/win_susp_schtask_creation.yml @@ -24,6 +24,7 @@ tags: - attack.t1053 - attack.s0111 - car.2013-08-001 + - attack.t1053.005 falsepositives: - Administrative activity - Software installation diff --git a/rules/windows/process_creation/win_susp_script_execution.yml b/rules/windows/process_creation/win_susp_script_execution.yml index 2404edc4..2e7ad48d 100644 --- a/rules/windows/process_creation/win_susp_script_execution.yml +++ b/rules/windows/process_creation/win_susp_script_execution.yml @@ -7,6 +7,7 @@ date: 2019/01/16 tags: - attack.execution - attack.t1064 + - attack.t1059.005 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_susp_service_path_modification.yml b/rules/windows/process_creation/win_susp_service_path_modification.yml index 6a3dbabd..6e6504ba 100644 --- a/rules/windows/process_creation/win_susp_service_path_modification.yml +++ b/rules/windows/process_creation/win_susp_service_path_modification.yml @@ -7,6 +7,7 @@ references: tags: - attack.persistence - attack.t1031 + - attack.t1543.003 date: 2019/10/21 modified: 2019/11/10 author: Victor Sergeev, oscd.community diff --git a/rules/windows/process_creation/win_susp_tscon_rdp_redirect.yml b/rules/windows/process_creation/win_susp_tscon_rdp_redirect.yml index dceac89d..fb2f5d65 100644 --- a/rules/windows/process_creation/win_susp_tscon_rdp_redirect.yml +++ b/rules/windows/process_creation/win_susp_tscon_rdp_redirect.yml @@ -10,6 +10,7 @@ tags: - attack.privilege_escalation - attack.t1076 - car.2013-07-002 + - attack.t1021 author: Florian Roth date: 2018/03/17 modified: 2018/12/11 diff --git a/rules/windows/process_creation/win_task_folder_evasion.yml b/rules/windows/process_creation/win_task_folder_evasion.yml index dfe043a8..e7844c4f 100644 --- a/rules/windows/process_creation/win_task_folder_evasion.yml +++ b/rules/windows/process_creation/win_task_folder_evasion.yml @@ -1,8 +1,8 @@ title: Tasks Folder Evasion id: cc4e02ba-9c06-48e2-b09e-2500cace9ae0 status: experimental -description: The Tasks folder in system32 and syswow64 are globally writable paths. Adversaries can take advantage of this and load or influence any script hosts or ANY .NET Application in Tasks to load and execute a custom assembly into cscript, wscript, regsvr32, mshta, eventvwr -references: +description: The Tasks folder in system32 and syswow64 are globally writable paths. Adversaries can take advantage of this and load or influence any script hosts or ANY .NET Application in Tasks to load and execute a custom assembly into cscript, wscript, regsvr32, mshta, eventvwr +references: - https://twitter.com/subTee/status/1216465628946563073 - https://gist.github.com/am0nsec/8378da08f848424e4ab0cc5b317fdd26 date: 2020/01/13 @@ -13,6 +13,7 @@ tags: - attack.t1059 - attack.defense_evasion - attack.persistence + - attack.t1059.005 logsource: product: Windows detection: diff --git a/rules/windows/process_creation/win_uac_cmstp.yml b/rules/windows/process_creation/win_uac_cmstp.yml index b10c9195..1c234bfe 100644 --- a/rules/windows/process_creation/win_uac_cmstp.yml +++ b/rules/windows/process_creation/win_uac_cmstp.yml @@ -13,13 +13,15 @@ tags: - attack.execution - attack.t1191 - attack.t1088 + - attack.t1548.002 + - attack.t1218 logsource: category: process_creation product: windows detection: selection: Image|endswith: '\cmstp.exe' - CommandLine|contains: + CommandLine|contains: - '/s' - '/au' condition: selection diff --git a/rules/windows/process_creation/win_uac_fodhelper.yml b/rules/windows/process_creation/win_uac_fodhelper.yml index d3ce1690..31f1181d 100644 --- a/rules/windows/process_creation/win_uac_fodhelper.yml +++ b/rules/windows/process_creation/win_uac_fodhelper.yml @@ -11,6 +11,7 @@ references: tags: - attack.privilege_escalation - attack.t1088 + - attack.t1548.002 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_uac_wsreset.yml b/rules/windows/process_creation/win_uac_wsreset.yml index 1296b8e4..ff41e342 100644 --- a/rules/windows/process_creation/win_uac_wsreset.yml +++ b/rules/windows/process_creation/win_uac_wsreset.yml @@ -10,6 +10,7 @@ references: tags: - attack.privilege_escalation - attack.t1088 + - attack.t1548.002 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_webshell_detection.yml b/rules/windows/process_creation/win_webshell_detection.yml index fc41f0f5..1437d0a6 100644 --- a/rules/windows/process_creation/win_webshell_detection.yml +++ b/rules/windows/process_creation/win_webshell_detection.yml @@ -10,6 +10,7 @@ tags: - attack.privilege_escalation - attack.persistence - attack.t1100 + - attack.t1505.003 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_webshell_spawn.yml b/rules/windows/process_creation/win_webshell_spawn.yml index 0f119262..3d5888fe 100644 --- a/rules/windows/process_creation/win_webshell_spawn.yml +++ b/rules/windows/process_creation/win_webshell_spawn.yml @@ -30,6 +30,7 @@ tags: - attack.privilege_escalation - attack.persistence - attack.t1100 + - attack.t1505.003 falsepositives: - Particular web applications may spawn a shell process legitimately level: high diff --git a/rules/windows/process_creation/win_win10_sched_task_0day.yml b/rules/windows/process_creation/win_win10_sched_task_0day.yml index 555c7132..312fb4cd 100644 --- a/rules/windows/process_creation/win_win10_sched_task_0day.yml +++ b/rules/windows/process_creation/win_win10_sched_task_0day.yml @@ -21,4 +21,5 @@ tags: - attack.execution - attack.t1053 - car.2013-08-001 + - attack.t1053.005 level: high diff --git a/rules/windows/process_creation/win_wmi_backdoor_exchange_transport_agent.yml b/rules/windows/process_creation/win_wmi_backdoor_exchange_transport_agent.yml index 0d5761e9..b5fa97cb 100644 --- a/rules/windows/process_creation/win_wmi_backdoor_exchange_transport_agent.yml +++ b/rules/windows/process_creation/win_wmi_backdoor_exchange_transport_agent.yml @@ -13,8 +13,9 @@ logsource: tags: - attack.persistence - attack.t1084 + - attack.t1546.003 detection: - selection: + selection: ParentImage: '*\EdgeTransport.exe' condition: selection falsepositives: diff --git a/rules/windows/process_creation/win_wmi_spwns_powershell.yml b/rules/windows/process_creation/win_wmi_spwns_powershell.yml index abe55079..91a69ec6 100644 --- a/rules/windows/process_creation/win_wmi_spwns_powershell.yml +++ b/rules/windows/process_creation/win_wmi_spwns_powershell.yml @@ -11,6 +11,7 @@ tags: - attack.execution - attack.defense_evasion - attack.t1064 + - attack.t1059.001 logsource: category: process_creation product: windows diff --git a/rules/windows/process_creation/win_wsreset_uac_bypass.yml b/rules/windows/process_creation/win_wsreset_uac_bypass.yml index 02d0398e..61622933 100644 --- a/rules/windows/process_creation/win_wsreset_uac_bypass.yml +++ b/rules/windows/process_creation/win_wsreset_uac_bypass.yml @@ -1,7 +1,7 @@ title: Wsreset UAC Bypass id: bdc8918e-a1d5-49d1-9db7-ea0fd91aa2ae status: experimental -description: Detects a method that uses Wsreset.exe tool that can be used to reset the Windows Store to bypass UAC +description: Detects a method that uses Wsreset.exe tool that can be used to reset the Windows Store to bypass UAC references: - https://lolbas-project.github.io/lolbas/Binaries/Wsreset/ - https://www.activecyber.us/activelabs/windows-uac-bypass @@ -12,6 +12,7 @@ tags: - attack.defense_evasion - attack.execution - attack.t1088 + - attack.t1548.002 logsource: category: process_creation product: windows diff --git a/rules/windows/sysmon/sysmon_alternate_powershell_hosts_pipe.yml b/rules/windows/sysmon/sysmon_alternate_powershell_hosts_pipe.yml index 067cd370..da710320 100644 --- a/rules/windows/sysmon/sysmon_alternate_powershell_hosts_pipe.yml +++ b/rules/windows/sysmon/sysmon_alternate_powershell_hosts_pipe.yml @@ -10,17 +10,18 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 logsource: product: windows service: sysmon detection: - selection: + selection: EventID: 17 PipeName|startswith: '\PSHost' filter: Image|endswith: - - '\powershell.exe' - - '\powershell_ise.exe' + - '\powershell.exe' + - '\powershell_ise.exe' condition: selection and not filter fields: - ComputerName diff --git a/rules/windows/sysmon/sysmon_asep_reg_keys_modification.yml b/rules/windows/sysmon/sysmon_asep_reg_keys_modification.yml index 09e94d15..72f08c5e 100644 --- a/rules/windows/sysmon/sysmon_asep_reg_keys_modification.yml +++ b/rules/windows/sysmon/sysmon_asep_reg_keys_modification.yml @@ -7,6 +7,7 @@ references: tags: - attack.persistence - attack.t1060 + - attack.t1547.001 date: 2019/10/21 modified: 2019/11/10 author: Victor Sergeev, Daniil Yugoslavskiy, oscd.community diff --git a/rules/windows/sysmon/sysmon_cred_dump_lsass_access.yml b/rules/windows/sysmon/sysmon_cred_dump_lsass_access.yml index f91ffabc..5e05ea71 100644 --- a/rules/windows/sysmon/sysmon_cred_dump_lsass_access.yml +++ b/rules/windows/sysmon/sysmon_cred_dump_lsass_access.yml @@ -2,8 +2,7 @@ title: Credentials Dumping Tools Accessing LSASS Memory id: 32d0d3e2-e58d-4d41-926b-18b520b2b32d status: experimental description: Detects process access LSASS memory which is typical for credentials dumping tools -author: Florian Roth, Roberto Rodriguez, Dimitrios Slamaris, Mark Russinovich, Thomas Patzke, Teymur Kheirkhabarov, Sherif Eldeeb, James Dickenson, Aleksey Potapov, - oscd.community (update) +author: Florian Roth, Roberto Rodriguez, Dimitrios Slamaris, Mark Russinovich, Thomas Patzke, Teymur Kheirkhabarov, Sherif Eldeeb, James Dickenson, Aleksey Potapov, oscd.community (update) date: 2017/02/16 modified: 2019/11/08 references: @@ -16,6 +15,7 @@ tags: - attack.s0002 - attack.credential_access - car.2019-04-004 + - attack.t1003.001 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_cred_dump_tools_dropped_files.yml b/rules/windows/sysmon/sysmon_cred_dump_tools_dropped_files.yml index 4ea0955c..6a76bfa6 100644 --- a/rules/windows/sysmon/sysmon_cred_dump_tools_dropped_files.yml +++ b/rules/windows/sysmon/sysmon_cred_dump_tools_dropped_files.yml @@ -9,20 +9,23 @@ references: tags: - attack.credential_access - attack.t1003 + - attack.t1003.002 + - attack.t1003.001 + - attack.t1003.003 logsource: product: windows service: sysmon detection: selection: EventID: 11 - TargetFilename|contains: + TargetFilename|contains: - '\pwdump' - '\kirbi' - '\pwhashes' - '\wce_ccache' - '\wce_krbtkts' - '\fgdump-log' - TargetFilename|endswith: + TargetFilename|endswith: - '\test.pwd' - '\lsremora64.dll' - '\lsremora.dll' diff --git a/rules/windows/sysmon/sysmon_cred_dump_tools_named_pipes.yml b/rules/windows/sysmon/sysmon_cred_dump_tools_named_pipes.yml index f0036118..78c45714 100644 --- a/rules/windows/sysmon/sysmon_cred_dump_tools_named_pipes.yml +++ b/rules/windows/sysmon/sysmon_cred_dump_tools_named_pipes.yml @@ -8,6 +8,9 @@ references: tags: - attack.credential_access - attack.t1003 + - attack.t1003.002 + - attack.t1003.004 + - attack.t1003.006 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_dhcp_calloutdll.yml b/rules/windows/sysmon/sysmon_dhcp_calloutdll.yml index 3432e7c2..0375f267 100644 --- a/rules/windows/sysmon/sysmon_dhcp_calloutdll.yml +++ b/rules/windows/sysmon/sysmon_dhcp_calloutdll.yml @@ -1,8 +1,7 @@ title: DHCP Callout DLL Installation id: 9d3436ef-9476-4c43-acca-90ce06bdf33a status: experimental -description: Detects the installation of a Callout DLL via CalloutDlls and CalloutEnabled parameter in Registry, which can be used to execute code in context of the - DHCP server (restart required) +description: Detects the installation of a Callout DLL via CalloutDlls and CalloutEnabled parameter in Registry, which can be used to execute code in context of the DHCP server (restart required) references: - https://blog.3or.de/mimilib-dhcp-server-callout-dll-injection.html - https://technet.microsoft.com/en-us/library/cc726884(v=ws.10).aspx @@ -13,6 +12,7 @@ tags: - attack.defense_evasion - attack.t1073 - attack.t1112 + - attack.t1574.002 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_disable_security_events_logging_adding_reg_key_minint.yml b/rules/windows/sysmon/sysmon_disable_security_events_logging_adding_reg_key_minint.yml index ea7a4ea4..b363db33 100644 --- a/rules/windows/sysmon/sysmon_disable_security_events_logging_adding_reg_key_minint.yml +++ b/rules/windows/sysmon/sysmon_disable_security_events_logging_adding_reg_key_minint.yml @@ -7,6 +7,7 @@ references: tags: - attack.defense_evasion - attack.t1089 + - attack.t1562.001 author: Ilyas Ochkov, oscd.community date: 2019/10/25 modified: 2019/11/13 @@ -15,11 +16,11 @@ logsource: service: sysmon detection: selection: - - EventID: 12 # key create + - EventID: 12 # key create # Sysmon gives us HKLM\SYSTEM\CurrentControlSet\.. if ControlSetXX is the selected one TargetObject: 'HKLM\SYSTEM\CurrentControlSet\Control\MiniNt' EventType: 'CreateKey' # we don't want deletekey - - EventID: 14 # key rename + - EventID: 14 # key rename NewName: 'HKLM\SYSTEM\CurrentControlSet\Control\MiniNt' condition: selection fields: diff --git a/rules/windows/sysmon/sysmon_ghostpack_safetykatz.yml b/rules/windows/sysmon/sysmon_ghostpack_safetykatz.yml index cfa37cb8..1dc20497 100644 --- a/rules/windows/sysmon/sysmon_ghostpack_safetykatz.yml +++ b/rules/windows/sysmon/sysmon_ghostpack_safetykatz.yml @@ -7,6 +7,7 @@ references: tags: - attack.credential_access - attack.t1003 + - attack.t1003.001 author: Markus Neis date: 2018/07/24 logsource: diff --git a/rules/windows/sysmon/sysmon_in_memory_powershell.yml b/rules/windows/sysmon/sysmon_in_memory_powershell.yml index 56e6e453..55b1f058 100644 --- a/rules/windows/sysmon/sysmon_in_memory_powershell.yml +++ b/rules/windows/sysmon/sysmon_in_memory_powershell.yml @@ -11,6 +11,7 @@ references: tags: - attack.t1086 - attack.execution + - attack.t1059.001 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_invoke_phantom.yml b/rules/windows/sysmon/sysmon_invoke_phantom.yml index 5ed1498c..9dda2195 100644 --- a/rules/windows/sysmon/sysmon_invoke_phantom.yml +++ b/rules/windows/sysmon/sysmon_invoke_phantom.yml @@ -10,6 +10,7 @@ references: tags: - attack.t1089 - attack.defense_evasion + - attack.t1562.001 logsource: product: windows service: sysmon @@ -19,7 +20,7 @@ detection: TargetImage: '*\windows\system32\svchost.exe' GrantedAccess: '0x1f3fff' CallTrace: - - '*unknown*' + - '*unknown*' condition: selection falsepositives: - unknown diff --git a/rules/windows/sysmon/sysmon_lsass_memdump.yml b/rules/windows/sysmon/sysmon_lsass_memdump.yml index d6e7d045..2a59dc1a 100644 --- a/rules/windows/sysmon/sysmon_lsass_memdump.yml +++ b/rules/windows/sysmon/sysmon_lsass_memdump.yml @@ -10,6 +10,7 @@ tags: - attack.t1003 - attack.s0002 - attack.credential_access + - attack.t1003.001 logsource: product: windows service: sysmon @@ -19,8 +20,8 @@ detection: TargetImage: 'C:\windows\system32\lsass.exe' GrantedAccess: '0x1fffff' CallTrace: - - '*dbghelp.dll*' - - '*dbgcore.dll*' + - '*dbghelp.dll*' + - '*dbgcore.dll*' condition: selection falsepositives: - unknown diff --git a/rules/windows/sysmon/sysmon_lsass_memory_dump_file_creation.yml b/rules/windows/sysmon/sysmon_lsass_memory_dump_file_creation.yml index 54f7e04f..f5d8963f 100644 --- a/rules/windows/sysmon/sysmon_lsass_memory_dump_file_creation.yml +++ b/rules/windows/sysmon/sysmon_lsass_memory_dump_file_creation.yml @@ -9,6 +9,7 @@ modified: 2019/11/13 tags: - attack.credential_access - attack.t1003 + - attack.t1003.001 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_malware_backconnect_ports.yml b/rules/windows/sysmon/sysmon_malware_backconnect_ports.yml index 953c8610..a69294b3 100644 --- a/rules/windows/sysmon/sysmon_malware_backconnect_ports.yml +++ b/rules/windows/sysmon/sysmon_malware_backconnect_ports.yml @@ -9,6 +9,7 @@ date: 2017/03/19 tags: - attack.command_and_control - attack.t1043 + - attack.t1571 logsource: product: windows service: sysmon @@ -71,7 +72,7 @@ detection: filter1: Image: '*\Program Files*' filter2: - DestinationIp: + DestinationIp: - '10.*' - '192.168.*' - '172.16.*' diff --git a/rules/windows/sysmon/sysmon_mimikatz_inmemory_detection.yml b/rules/windows/sysmon/sysmon_mimikatz_inmemory_detection.yml index 58f1cf58..a9832506 100644 --- a/rules/windows/sysmon/sysmon_mimikatz_inmemory_detection.yml +++ b/rules/windows/sysmon/sysmon_mimikatz_inmemory_detection.yml @@ -10,6 +10,10 @@ tags: - attack.lateral_movement - attack.credential_access - car.2019-04-004 + - attack.t1003.002 + - attack.t1003.004 + - attack.t1003.001 + - attack.t1003.006 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_mimikatz_trough_winrm.yml b/rules/windows/sysmon/sysmon_mimikatz_trough_winrm.yml index 871724ab..693cdeef 100644 --- a/rules/windows/sysmon/sysmon_mimikatz_trough_winrm.yml +++ b/rules/windows/sysmon/sysmon_mimikatz_trough_winrm.yml @@ -21,6 +21,8 @@ tags: - attack.t1003 - attack.t1028 - attack.s0005 + - attack.t1003.001 + - attack.t1021.006 falsepositives: - low level: high diff --git a/rules/windows/sysmon/sysmon_narrator_feedback_persistance.yml b/rules/windows/sysmon/sysmon_narrator_feedback_persistance.yml index 44389267..7c88604c 100644 --- a/rules/windows/sysmon/sysmon_narrator_feedback_persistance.yml +++ b/rules/windows/sysmon/sysmon_narrator_feedback_persistance.yml @@ -6,6 +6,7 @@ references: tags: - attack.persistence - attack.t1060 + - attack.t1547.001 author: Dmitriy Lifanov, oscd.community status: experimental date: 2019/10/25 diff --git a/rules/windows/sysmon/sysmon_new_dll_added_to_appcertdlls_registry_key.yml b/rules/windows/sysmon/sysmon_new_dll_added_to_appcertdlls_registry_key.yml index 79202088..b88b0a87 100644 --- a/rules/windows/sysmon/sysmon_new_dll_added_to_appcertdlls_registry_key.yml +++ b/rules/windows/sysmon/sysmon_new_dll_added_to_appcertdlls_registry_key.yml @@ -1,14 +1,14 @@ title: New DLL Added to AppCertDlls Registry Key id: 6aa1d992-5925-4e9f-a49b-845e51d1de01 status: experimental -description: Dynamic-link libraries (DLLs) that are specified in the AppCertDLLs value in the Registry key can be abused to obtain persistence and privilege escalation - by causing a malicious DLL to be loaded and run in the context of separate processes on the computer. +description: Dynamic-link libraries (DLLs) that are specified in the AppCertDLLs value in the Registry key can be abused to obtain persistence and privilege escalation by causing a malicious DLL to be loaded and run in the context of separate processes on the computer. references: - http://www.hexacorn.com/blog/2013/01/19/beyond-good-ol-run-key-part-3/ - https://eqllib.readthedocs.io/en/latest/analytics/14f90406-10a0-4d36-a672-31cabe149f2f.html tags: - attack.persistence - attack.t1182 + - attack.t1546.009 author: Ilyas Ochkov, oscd.community date: 2019/10/25 modified: 2019/11/13 @@ -17,12 +17,12 @@ logsource: service: sysmon detection: selection: - - EventID: + - EventID: - 12 # key create - 13 # value set # Sysmon gives us HKLM\SYSTEM\CurrentControlSet\.. if ControlSetXX is the selected one TargetObject: 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDlls' - - EventID: 14 # key rename + - EventID: 14 # key rename NewName: 'HKLM\SYSTEM\CurentControlSet\Control\Session Manager\AppCertDlls' condition: selection fields: diff --git a/rules/windows/sysmon/sysmon_new_dll_added_to_appinit_dlls_registry_key.yml b/rules/windows/sysmon/sysmon_new_dll_added_to_appinit_dlls_registry_key.yml index 604cc1eb..f7cfcd8e 100644 --- a/rules/windows/sysmon/sysmon_new_dll_added_to_appinit_dlls_registry_key.yml +++ b/rules/windows/sysmon/sysmon_new_dll_added_to_appinit_dlls_registry_key.yml @@ -7,6 +7,7 @@ references: tags: - attack.persistence - attack.t1103 + - attack.t1546.010 author: Ilyas Ochkov, oscd.community date: 2019/10/25 modified: 2019/11/13 @@ -15,16 +16,16 @@ logsource: service: sysmon detection: selection: - - EventID: + - EventID: - 12 # key create - 13 # value set TargetObject: - - '*\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls' - - '*\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls' - - EventID: 14 # key rename + - '*\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls' + - '*\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls' + - EventID: 14 # key rename NewName: - - '*\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls' - - '*\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls' + - '*\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls' + - '*\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls' condition: selection fields: - EventID diff --git a/rules/windows/sysmon/sysmon_password_dumper_lsass.yml b/rules/windows/sysmon/sysmon_password_dumper_lsass.yml index 70a4246e..f5632f4d 100644 --- a/rules/windows/sysmon/sysmon_password_dumper_lsass.yml +++ b/rules/windows/sysmon/sysmon_password_dumper_lsass.yml @@ -1,7 +1,6 @@ title: Password Dumper Remote Thread in LSASS id: f239b326-2f41-4d6b-9dfa-c846a60ef505 -description: Detects password dumper activity by monitoring remote thread creation EventID 8 in combination with the lsass.exe process as TargetImage. The process - in field Process is the malicious program. A single execution can lead to hundreds of events. +description: Detects password dumper activity by monitoring remote thread creation EventID 8 in combination with the lsass.exe process as TargetImage. The process in field Process is the malicious program. A single execution can lead to hundreds of events. references: - https://jpcertcc.github.io/ToolAnalysisResultSheet/details/WCE.htm status: stable @@ -14,12 +13,13 @@ detection: selection: EventID: 8 TargetImage: 'C:\Windows\System32\lsass.exe' - StartModule: null + StartModule: condition: selection tags: - attack.credential_access - attack.t1003 - attack.s0005 + - attack.t1003.001 falsepositives: - unknown level: high diff --git a/rules/windows/sysmon/sysmon_possible_dns_rebinding.yml b/rules/windows/sysmon/sysmon_possible_dns_rebinding.yml index 9845263a..6070a673 100644 --- a/rules/windows/sysmon/sysmon_possible_dns_rebinding.yml +++ b/rules/windows/sysmon/sysmon_possible_dns_rebinding.yml @@ -1,8 +1,7 @@ title: Possible DNS Rebinding id: eb07e747-2552-44cd-af36-b659ae0958e4 status: experimental -description: Detects several different DNS-answers by one domain with IPs from internal and external networks. Normally, DNS-answer contain TTL >100. (DNS-record - will saved in host cache for a while TTL). +description: Detects several different DNS-answers by one domain with IPs from internal and external networks. Normally, DNS-answer contain TTL >100. (DNS-record will saved in host cache for a while TTL). date: 2019/10/25 modified: 2019/11/13 author: Ilyas Ochkov, oscd.community @@ -11,6 +10,7 @@ references: tags: - attack.command_and_control - attack.t1043 + - attack.t1571 logsource: product: windows service: sysmon @@ -18,9 +18,9 @@ detection: dns_answer: EventID: 22 QueryName: '*' - QueryStatus: '0' + QueryStatus: '0' filter_int_ip: - QueryResults|startswith: + QueryResults|startswith: - '(::ffff:)?10.' - '(::ffff:)?192.168.' - '(::ffff:)?172.16.' @@ -39,7 +39,7 @@ detection: - '(::ffff:)?172.29.' - '(::ffff:)?172.30.' - '(::ffff:)?172.31.' - - '(::ffff:)?127.' + - '(::ffff:)?127.' timeframe: 30s condition: (dns_answer and filter_int_ip) and (dns_answer and not filter_int_ip) | count(QueryName) by ComputerName > 3 level: medium diff --git a/rules/windows/sysmon/sysmon_possible_privilege_escalation_via_service_registry_permissions_weakness.yml b/rules/windows/sysmon/sysmon_possible_privilege_escalation_via_service_registry_permissions_weakness.yml index 6251dd07..89ab5297 100644 --- a/rules/windows/sysmon/sysmon_possible_privilege_escalation_via_service_registry_permissions_weakness.yml +++ b/rules/windows/sysmon/sysmon_possible_privilege_escalation_via_service_registry_permissions_weakness.yml @@ -7,6 +7,7 @@ references: tags: - attack.privilege_escalation - attack.t1058 + - attack.t1574.011 status: experimental author: Teymur Kheirkhabarov date: 2019/10/26 diff --git a/rules/windows/sysmon/sysmon_powershell_execution_moduleload.yml b/rules/windows/sysmon/sysmon_powershell_execution_moduleload.yml index 124c8312..9d93c4c0 100644 --- a/rules/windows/sysmon/sysmon_powershell_execution_moduleload.yml +++ b/rules/windows/sysmon/sysmon_powershell_execution_moduleload.yml @@ -13,8 +13,9 @@ logsource: tags: - attack.execution - attack.t1086 + - attack.t1059.001 detection: - selection: + selection: EventID: 7 Description: 'system.management.automation' ImageLoaded|contains: 'system.management.automation' diff --git a/rules/windows/sysmon/sysmon_powershell_exploit_scripts.yml b/rules/windows/sysmon/sysmon_powershell_exploit_scripts.yml index d7a6df7a..60028363 100644 --- a/rules/windows/sysmon/sysmon_powershell_exploit_scripts.yml +++ b/rules/windows/sysmon/sysmon_powershell_exploit_scripts.yml @@ -7,6 +7,7 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 author: Markus Neis date: 2018/04/07 logsource: @@ -16,7 +17,7 @@ detection: selection: EventID: 11 TargetFilename: - - '*\Invoke-DllInjection.ps1' + - '*\Invoke-DllInjection.ps1' - '*\Invoke-WmiCommand.ps1' - '*\Get-GPPPassword.ps1' - '*\Get-Keystrokes.ps1' @@ -115,4 +116,4 @@ detection: falsepositives: - Penetration Tests level: high - + diff --git a/rules/windows/sysmon/sysmon_powershell_network_connection.yml b/rules/windows/sysmon/sysmon_powershell_network_connection.yml index 55f83462..0dd64587 100644 --- a/rules/windows/sysmon/sysmon_powershell_network_connection.yml +++ b/rules/windows/sysmon/sysmon_powershell_network_connection.yml @@ -1,8 +1,7 @@ title: PowerShell Network Connections id: 1f21ec3f-810d-4b0e-8045-322202e22b4b status: experimental -description: Detects a Powershell process that opens network connections - check for suspicious target ports and target systems - adjust to your environment (e.g. - extend filters with company's ip range') +description: Detects a Powershell process that opens network connections - check for suspicious target ports and target systems - adjust to your environment (e.g. extend filters with company's ip range') author: Florian Roth date: 2017/03/13 references: @@ -10,6 +9,7 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_quarkspw_filedump.yml b/rules/windows/sysmon/sysmon_quarkspw_filedump.yml index 5b712d9c..135b66b9 100644 --- a/rules/windows/sysmon/sysmon_quarkspw_filedump.yml +++ b/rules/windows/sysmon/sysmon_quarkspw_filedump.yml @@ -7,8 +7,9 @@ references: author: Florian Roth date: 2018/02/10 tags: - - attack.credential_access - - attack.t1003 + - attack.credential_access + - attack.t1003 + - attack.t1003.002 level: critical logsource: product: windows diff --git a/rules/windows/sysmon/sysmon_rdp_reverse_tunnel.yml b/rules/windows/sysmon/sysmon_rdp_reverse_tunnel.yml index ee2e85ea..f7979bd6 100644 --- a/rules/windows/sysmon/sysmon_rdp_reverse_tunnel.yml +++ b/rules/windows/sysmon/sysmon_rdp_reverse_tunnel.yml @@ -11,6 +11,7 @@ tags: - attack.command_and_control - attack.t1076 - car.2013-07-002 + - attack.t1021 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_registry_persistence_key_linking.yml b/rules/windows/sysmon/sysmon_registry_persistence_key_linking.yml index e0131f92..e4087c05 100644 --- a/rules/windows/sysmon/sysmon_registry_persistence_key_linking.yml +++ b/rules/windows/sysmon/sysmon_registry_persistence_key_linking.yml @@ -10,6 +10,7 @@ modified: 2019/11/07 tags: - attack.persistence - attack.t1122 + - attack.t1546.015 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_registry_persistence_search_order.yml b/rules/windows/sysmon/sysmon_registry_persistence_search_order.yml index 6e8aae23..5d6a6e8e 100644 --- a/rules/windows/sysmon/sysmon_registry_persistence_search_order.yml +++ b/rules/windows/sysmon/sysmon_registry_persistence_search_order.yml @@ -9,6 +9,7 @@ date: 2020/04/14 tags: - attack.persistence - attack.t1038 + - attack.t1574.001 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_registry_trust_record_modification.yml b/rules/windows/sysmon/sysmon_registry_trust_record_modification.yml index eec9375a..22b7bc79 100644 --- a/rules/windows/sysmon/sysmon_registry_trust_record_modification.yml +++ b/rules/windows/sysmon/sysmon_registry_trust_record_modification.yml @@ -11,6 +11,7 @@ modified: 2020/02/19 tags: - attack.initial_access - attack.t1193 + - attack.t1566.001 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_regsvr32_network_activity.yml b/rules/windows/sysmon/sysmon_regsvr32_network_activity.yml index 9722b7a7..71c7903c 100644 --- a/rules/windows/sysmon/sysmon_regsvr32_network_activity.yml +++ b/rules/windows/sysmon/sysmon_regsvr32_network_activity.yml @@ -9,6 +9,7 @@ tags: - attack.execution - attack.defense_evasion - attack.t1117 + - attack.t1218.010 author: Dmitriy Lifanov, oscd.community status: experimental date: 2019/10/25 @@ -19,8 +20,8 @@ logsource: detection: selection: EventID: - - 3 - - 22 + - 3 + - 22 Image|endswith: '\regsvr32.exe' condition: selection fields: diff --git a/rules/windows/sysmon/sysmon_remote_powershell_session_network.yml b/rules/windows/sysmon/sysmon_remote_powershell_session_network.yml index 805f7db5..b0695d7a 100644 --- a/rules/windows/sysmon/sysmon_remote_powershell_session_network.yml +++ b/rules/windows/sysmon/sysmon_remote_powershell_session_network.yml @@ -9,11 +9,12 @@ references: tags: - attack.execution - attack.t1086 + - attack.t1059.001 logsource: product: windows service: sysmon detection: - selection: + selection: EventID: 3 DestinationPort: - 5985 diff --git a/rules/windows/sysmon/sysmon_rundll32_net_connections.yml b/rules/windows/sysmon/sysmon_rundll32_net_connections.yml index c02164f3..c7f6e7b9 100644 --- a/rules/windows/sysmon/sysmon_rundll32_net_connections.yml +++ b/rules/windows/sysmon/sysmon_rundll32_net_connections.yml @@ -10,6 +10,7 @@ tags: - attack.t1085 - attack.defense_evasion - attack.execution + - attack.t1218 logsource: product: windows service: sysmon @@ -19,7 +20,7 @@ detection: Image: '*\rundll32.exe' Initiated: 'true' filter: - DestinationIp: + DestinationIp: - '10.*' - '192.168.*' - '172.16.*' diff --git a/rules/windows/sysmon/sysmon_susp_desktop_ini.yml b/rules/windows/sysmon/sysmon_susp_desktop_ini.yml index 606076a2..ec1df92c 100644 --- a/rules/windows/sysmon/sysmon_susp_desktop_ini.yml +++ b/rules/windows/sysmon/sysmon_susp_desktop_ini.yml @@ -9,6 +9,7 @@ date: 2020/03/19 tags: - attack.persistence - attack.t1023 + - attack.t1547.009 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_susp_download_run_key.yml b/rules/windows/sysmon/sysmon_susp_download_run_key.yml index 5f1bad94..14f5d5ca 100644 --- a/rules/windows/sysmon/sysmon_susp_download_run_key.yml +++ b/rules/windows/sysmon/sysmon_susp_download_run_key.yml @@ -9,13 +9,14 @@ date: 2019/10/01 tags: - attack.persistence - attack.t1060 + - attack.t1547.001 logsource: product: windows service: sysmon detection: selection: EventID: 13 - Image: + Image: - '*\Downloads\\*' - '*\Temporary Internet Files\Content.Outlook\\*' - '*\Local Settings\Temporary Internet Files\\*' @@ -23,4 +24,4 @@ detection: condition: selection falsepositives: - Software installers downloaded and used by users -level: high \ No newline at end of file +level: high diff --git a/rules/windows/sysmon/sysmon_susp_driver_load.yml b/rules/windows/sysmon/sysmon_susp_driver_load.yml index 1bfec5e1..c353d7e9 100644 --- a/rules/windows/sysmon/sysmon_susp_driver_load.yml +++ b/rules/windows/sysmon/sysmon_susp_driver_load.yml @@ -6,6 +6,7 @@ date: 2017/02/12 tags: - attack.persistence - attack.t1050 + - attack.t1543.003 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_susp_image_load.yml b/rules/windows/sysmon/sysmon_susp_image_load.yml index 577f9610..11a696b0 100644 --- a/rules/windows/sysmon/sysmon_susp_image_load.yml +++ b/rules/windows/sysmon/sysmon_susp_image_load.yml @@ -9,6 +9,7 @@ date: 2018/01/07 tags: - attack.defense_evasion - attack.t1073 + - attack.t1574.002 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_susp_lsass_dll_load.yml b/rules/windows/sysmon/sysmon_susp_lsass_dll_load.yml index 78cf4bf7..44a1020d 100644 --- a/rules/windows/sysmon/sysmon_susp_lsass_dll_load.yml +++ b/rules/windows/sysmon/sysmon_susp_lsass_dll_load.yml @@ -13,15 +13,16 @@ logsource: detection: selection: EventID: - - 12 + - 12 - 13 - TargetObject: + TargetObject: - '*\CurrentControlSet\Services\NTDS\DirectoryServiceExtPt*' - '*\CurrentControlSet\Services\NTDS\LsaDbExtPt*' condition: selection tags: - attack.execution - attack.t1177 + - attack.t1547.008 falsepositives: - Unknown level: high diff --git a/rules/windows/sysmon/sysmon_susp_office_dotnet_assembly_dll_load.yml b/rules/windows/sysmon/sysmon_susp_office_dotnet_assembly_dll_load.yml index 47036525..f3d5acd9 100644 --- a/rules/windows/sysmon/sysmon_susp_office_dotnet_assembly_dll_load.yml +++ b/rules/windows/sysmon/sysmon_susp_office_dotnet_assembly_dll_load.yml @@ -9,6 +9,7 @@ date: 2020/02/19 tags: - attack.initial_access - attack.t1193 + - attack.t1566.001 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_susp_office_dotnet_clr_dll_load.yml b/rules/windows/sysmon/sysmon_susp_office_dotnet_clr_dll_load.yml index bd58c23b..e76e29d5 100644 --- a/rules/windows/sysmon/sysmon_susp_office_dotnet_clr_dll_load.yml +++ b/rules/windows/sysmon/sysmon_susp_office_dotnet_clr_dll_load.yml @@ -9,6 +9,7 @@ date: 2020/02/19 tags: - attack.initial_access - attack.t1193 + - attack.t1566.001 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_susp_office_dotnet_gac_dll_load.yml b/rules/windows/sysmon/sysmon_susp_office_dotnet_gac_dll_load.yml index 354d7e8a..670a5552 100644 --- a/rules/windows/sysmon/sysmon_susp_office_dotnet_gac_dll_load.yml +++ b/rules/windows/sysmon/sysmon_susp_office_dotnet_gac_dll_load.yml @@ -9,6 +9,7 @@ date: 2020/02/19 tags: - attack.initial_access - attack.t1193 + - attack.t1566.001 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_susp_office_dsparse_dll_load.yml b/rules/windows/sysmon/sysmon_susp_office_dsparse_dll_load.yml index e46824e6..24afa4ca 100644 --- a/rules/windows/sysmon/sysmon_susp_office_dsparse_dll_load.yml +++ b/rules/windows/sysmon/sysmon_susp_office_dsparse_dll_load.yml @@ -9,6 +9,7 @@ date: 2020/02/19 tags: - attack.initial_access - attack.t1193 + - attack.t1566.001 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_susp_office_kerberos_dll_load.yml b/rules/windows/sysmon/sysmon_susp_office_kerberos_dll_load.yml index 77aaf326..d55fe994 100644 --- a/rules/windows/sysmon/sysmon_susp_office_kerberos_dll_load.yml +++ b/rules/windows/sysmon/sysmon_susp_office_kerberos_dll_load.yml @@ -9,6 +9,7 @@ date: 2020/02/19 tags: - attack.initial_access - attack.t1193 + - attack.t1566.001 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_susp_powershell_rundll32.yml b/rules/windows/sysmon/sysmon_susp_powershell_rundll32.yml index 58ec943c..d989a010 100644 --- a/rules/windows/sysmon/sysmon_susp_powershell_rundll32.yml +++ b/rules/windows/sysmon/sysmon_susp_powershell_rundll32.yml @@ -20,6 +20,8 @@ tags: - attack.execution - attack.t1085 - attack.t1086 + - attack.t1218.011 + - attack.t1059.001 falsepositives: - Unkown level: high diff --git a/rules/windows/sysmon/sysmon_susp_procexplorer_driver_created_in_tmp_folder.yml b/rules/windows/sysmon/sysmon_susp_procexplorer_driver_created_in_tmp_folder.yml index b73320b3..25ee0df7 100644 --- a/rules/windows/sysmon/sysmon_susp_procexplorer_driver_created_in_tmp_folder.yml +++ b/rules/windows/sysmon/sysmon_susp_procexplorer_driver_created_in_tmp_folder.yml @@ -9,6 +9,7 @@ references: tags: - attack.t1089 - attack.defense_evasion + - attack.t1562.001 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_susp_reg_persist_explorer_run.yml b/rules/windows/sysmon/sysmon_susp_reg_persist_explorer_run.yml index e5786395..0dc20e16 100644 --- a/rules/windows/sysmon/sysmon_susp_reg_persist_explorer_run.yml +++ b/rules/windows/sysmon/sysmon_susp_reg_persist_explorer_run.yml @@ -13,7 +13,7 @@ detection: selection: EventID: 13 TargetObject: '*\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run' - Details: + Details: - 'C:\Windows\Temp\\*' - 'C:\ProgramData\\*' - '*\AppData\\*' @@ -26,6 +26,7 @@ tags: - attack.persistence - attack.t1060 - capec.270 + - attack.t1547.001 fields: - Image - ParentImage diff --git a/rules/windows/sysmon/sysmon_susp_run_key_img_folder.yml b/rules/windows/sysmon/sysmon_susp_run_key_img_folder.yml index 43c5990a..7798f552 100644 --- a/rules/windows/sysmon/sysmon_susp_run_key_img_folder.yml +++ b/rules/windows/sysmon/sysmon_susp_run_key_img_folder.yml @@ -8,6 +8,7 @@ author: Florian Roth, Markus Neis, Sander Wiebing tags: - attack.persistence - attack.t1060 + - attack.t1547.001 date: 2018/08/25 modified: 2020/05/24 logsource: @@ -16,7 +17,7 @@ logsource: detection: selection: EventID: 13 - TargetObject: + TargetObject: - '*\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\\*' - '*\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce\\*' Details: diff --git a/rules/windows/sysmon/sysmon_susp_service_installed.yml b/rules/windows/sysmon/sysmon_susp_service_installed.yml index 39efbfaa..c15a8c94 100644 --- a/rules/windows/sysmon/sysmon_susp_service_installed.yml +++ b/rules/windows/sysmon/sysmon_susp_service_installed.yml @@ -9,6 +9,7 @@ references: tags: - attack.t1089 - attack.defense_evasion + - attack.t1562.001 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_susp_winword_vbadll_load.yml b/rules/windows/sysmon/sysmon_susp_winword_vbadll_load.yml index c792c8c2..1006e845 100644 --- a/rules/windows/sysmon/sysmon_susp_winword_vbadll_load.yml +++ b/rules/windows/sysmon/sysmon_susp_winword_vbadll_load.yml @@ -9,6 +9,7 @@ date: 2020/02/19 tags: - attack.initial_access - attack.t1193 + - attack.t1566.001 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_suspicious_dbghelp_dbgcore_load.yml b/rules/windows/sysmon/sysmon_suspicious_dbghelp_dbgcore_load.yml index b5f36b4e..09cb9dfb 100644 --- a/rules/windows/sysmon/sysmon_suspicious_dbghelp_dbgcore_load.yml +++ b/rules/windows/sysmon/sysmon_suspicious_dbghelp_dbgcore_load.yml @@ -1,9 +1,7 @@ title: Load of dbghelp/dbgcore DLL from Suspicious Process id: 0e277796-5f23-4e49-a490-483131d4f6e1 status: experimental -description: Detects the load of dbghelp/dbgcore DLL (used to make memory dumps) by suspicious processes. Tools like ProcessHacker and some attacker tradecract use MiniDumpWriteDump - API found in dbghelp.dll or dbgcore.dll. As an example, SilentTrynity C2 Framework has a module that leverages this API to dump the contents of Lsass.exe and - transfer it over the network back to the attacker's machine. +description: Detects the load of dbghelp/dbgcore DLL (used to make memory dumps) by suspicious processes. Tools like ProcessHacker and some attacker tradecract use MiniDumpWriteDump API found in dbghelp.dll or dbgcore.dll. As an example, SilentTrynity C2 Framework has a module that leverages this API to dump the contents of Lsass.exe and transfer it over the network back to the attacker's machine. date: 2019/10/27 modified: 2020/05/23 author: Perez Diego (@darkquassar), oscd.community, Ecco @@ -14,6 +12,7 @@ references: tags: - attack.credential_access - attack.t1003 + - attack.t1003.001 logsource: product: windows service: sysmon @@ -23,7 +22,7 @@ detection: ImageLoaded|endswith: - '\dbghelp.dll' - '\dbgcore.dll' - Image|endswith: + Image|endswith: - '\msbuild.exe' - '\cmd.exe' - '\svchost.exe' diff --git a/rules/windows/sysmon/sysmon_suspicious_outbound_kerberos_connection.yml b/rules/windows/sysmon/sysmon_suspicious_outbound_kerberos_connection.yml index 353034a7..3b1fd52b 100644 --- a/rules/windows/sysmon/sysmon_suspicious_outbound_kerberos_connection.yml +++ b/rules/windows/sysmon/sysmon_suspicious_outbound_kerberos_connection.yml @@ -10,6 +10,7 @@ modified: 2019/11/13 tags: - attack.lateral_movement - attack.t1208 + - attack.t1558.003 logsource: product: windows service: sysmon @@ -24,7 +25,7 @@ detection: - '\opera.exe' - '\chrome.exe' - '\firefox.exe' - condition: selection and not filter + condition: selection and not filter falsepositives: - Other browsers level: high diff --git a/rules/windows/sysmon/sysmon_svchost_dll_search_order_hijack.yml b/rules/windows/sysmon/sysmon_svchost_dll_search_order_hijack.yml index f06a1e20..1773855c 100644 --- a/rules/windows/sysmon/sysmon_svchost_dll_search_order_hijack.yml +++ b/rules/windows/sysmon/sysmon_svchost_dll_search_order_hijack.yml @@ -1,9 +1,7 @@ title: Svchost DLL Search Order Hijack id: 602a1f13-c640-4d73-b053-be9a2fa58b77 status: experimental -description: IKEEXT and SessionEnv service, as they call LoadLibrary on files that do not exist within C:\Windows\System32\ by default. An attacker can place their - malicious logic within the PROCESS_ATTACH block of their library and restart the aforementioned services "svchost.exe -k netsvcs" to gain code execution on a - remote machine. +description: IKEEXT and SessionEnv service, as they call LoadLibrary on files that do not exist within C:\Windows\System32\ by default. An attacker can place their malicious logic within the PROCESS_ATTACH block of their library and restart the aforementioned services "svchost.exe -k netsvcs" to gain code execution on a remote machine. references: - https://posts.specterops.io/lateral-movement-scm-and-dll-hijacking-primer-d2f61e8ab992 author: SBousseaden @@ -14,6 +12,8 @@ tags: - attack.t1073 - attack.t1038 - attack.t1112 + - attack.t1574.002 + - attack.t1574.001 logsource: product: windows service: sysmon @@ -28,7 +28,7 @@ detection: - '*\wlbsctrl.dll' filter: ImageLoaded: - - 'C:\Windows\WinSxS\\*' + - 'C:\Windows\WinSxS\\*' condition: selection and not filter falsepositives: - Pentest diff --git a/rules/windows/sysmon/sysmon_uac_bypass_eventvwr.yml b/rules/windows/sysmon/sysmon_uac_bypass_eventvwr.yml index c91f0abd..ded431bf 100644 --- a/rules/windows/sysmon/sysmon_uac_bypass_eventvwr.yml +++ b/rules/windows/sysmon/sysmon_uac_bypass_eventvwr.yml @@ -28,6 +28,7 @@ tags: - attack.privilege_escalation - attack.t1088 - car.2019-04-001 + - attack.t1548.002 falsepositives: - unknown level: critical diff --git a/rules/windows/sysmon/sysmon_uac_bypass_sdclt.yml b/rules/windows/sysmon/sysmon_uac_bypass_sdclt.yml index 042c1477..2e8f8c36 100644 --- a/rules/windows/sysmon/sysmon_uac_bypass_sdclt.yml +++ b/rules/windows/sysmon/sysmon_uac_bypass_sdclt.yml @@ -20,6 +20,7 @@ tags: - attack.privilege_escalation - attack.t1088 - car.2019-04-001 + - attack.t1548.002 falsepositives: - unknown level: high diff --git a/rules/windows/sysmon/sysmon_unsigned_image_loaded_into_lsass.yml b/rules/windows/sysmon/sysmon_unsigned_image_loaded_into_lsass.yml index c88a6d4c..cba4a5e0 100644 --- a/rules/windows/sysmon/sysmon_unsigned_image_loaded_into_lsass.yml +++ b/rules/windows/sysmon/sysmon_unsigned_image_loaded_into_lsass.yml @@ -9,6 +9,7 @@ references: tags: - attack.credential_access - attack.t1003 + - attack.t1003.001 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_webshell_creation_detect.yml b/rules/windows/sysmon/sysmon_webshell_creation_detect.yml index 7f94a425..64a99889 100644 --- a/rules/windows/sysmon/sysmon_webshell_creation_detect.yml +++ b/rules/windows/sysmon/sysmon_webshell_creation_detect.yml @@ -10,6 +10,7 @@ modified: 2020/05/18 tags: - attack.persistence - attack.t1100 + - attack.t1505.003 level: critical logsource: product: windows diff --git a/rules/windows/sysmon/sysmon_win_reg_persistence.yml b/rules/windows/sysmon/sysmon_win_reg_persistence.yml index 06a18db8..a2d5512c 100644 --- a/rules/windows/sysmon/sysmon_win_reg_persistence.yml +++ b/rules/windows/sysmon/sysmon_win_reg_persistence.yml @@ -23,6 +23,7 @@ tags: - attack.defense_evasion - attack.t1183 - car.2013-01-002 + - attack.t1546.012 falsepositives: - unknown level: critical diff --git a/rules/windows/sysmon/sysmon_wmi_event_subscription.yml b/rules/windows/sysmon/sysmon_wmi_event_subscription.yml index 34db9562..6862faf3 100644 --- a/rules/windows/sysmon/sysmon_wmi_event_subscription.yml +++ b/rules/windows/sysmon/sysmon_wmi_event_subscription.yml @@ -7,6 +7,7 @@ references: tags: - attack.t1084 - attack.persistence + - attack.t1546.003 author: Tom Ueltschi (@c_APT_ure) date: 2019/01/12 logsource: diff --git a/rules/windows/sysmon/sysmon_wmi_persistence_commandline_event_consumer.yml b/rules/windows/sysmon/sysmon_wmi_persistence_commandline_event_consumer.yml index c87d2af6..52672a95 100644 --- a/rules/windows/sysmon/sysmon_wmi_persistence_commandline_event_consumer.yml +++ b/rules/windows/sysmon/sysmon_wmi_persistence_commandline_event_consumer.yml @@ -9,6 +9,7 @@ date: 2018/03/07 tags: - attack.t1084 - attack.persistence + - attack.t1546.003 logsource: product: windows service: sysmon @@ -18,6 +19,6 @@ detection: Image: 'C:\Windows\System32\wbem\WmiPrvSE.exe' ImageLoaded|endswith: '\wbemcons.dll' condition: selection -falsepositives: +falsepositives: - Unknown (data set is too small; further testing needed) level: high diff --git a/rules/windows/sysmon/sysmon_wmi_persistence_script_event_consumer_write.yml b/rules/windows/sysmon/sysmon_wmi_persistence_script_event_consumer_write.yml index 907a2873..7095ec85 100644 --- a/rules/windows/sysmon/sysmon_wmi_persistence_script_event_consumer_write.yml +++ b/rules/windows/sysmon/sysmon_wmi_persistence_script_event_consumer_write.yml @@ -9,6 +9,7 @@ date: 2018/03/07 tags: - attack.t1084 - attack.persistence + - attack.t1546.003 logsource: product: windows service: sysmon @@ -17,6 +18,6 @@ detection: EventID: 11 Image: 'C:\WINDOWS\system32\wbem\scrcons.exe' condition: selection -falsepositives: +falsepositives: - Unknown (data set is too small; further testing needed) level: high diff --git a/rules/windows/sysmon/sysmon_wmi_susp_scripting.yml b/rules/windows/sysmon/sysmon_wmi_susp_scripting.yml index d6d05986..ad5c4132 100644 --- a/rules/windows/sysmon/sysmon_wmi_susp_scripting.yml +++ b/rules/windows/sysmon/sysmon_wmi_susp_scripting.yml @@ -10,9 +10,10 @@ date: 2019/04/15 tags: - attack.t1086 - attack.execution + - attack.t1059.005 logsource: - product: windows - service: sysmon + product: windows + service: sysmon detection: selection: EventID: 20 From 5c0bb0e94f127ad224722818a3e5e9d491d626e3 Mon Sep 17 00:00:00 2001 From: Ivan Kirillov Date: Tue, 16 Jun 2020 15:01:13 -0600 Subject: [PATCH 90/94] Fixed indentation --- rules/windows/builtin/win_pass_the_hash.yml | 16 ++++++++-------- rules/windows/builtin/win_pass_the_hash_2.yml | 12 ++++++------ .../win_register_new_logon_process_by_rubeus.yml | 2 +- ...rivileged_service_lsaregisterlogonprocess.yml | 4 ++-- ...ying_sensitive_files_with_credential_data.yml | 2 +- .../win_new_service_creation.yml | 4 ++-- .../win_powershell_downgrade_attack.yml | 2 +- ...rity_events_logging_adding_reg_key_minint.yml | 8 ++++---- ...new_dll_added_to_appcertdlls_registry_key.yml | 4 ++-- ...ew_dll_added_to_appinit_dlls_registry_key.yml | 12 ++++++------ 10 files changed, 33 insertions(+), 33 deletions(-) diff --git a/rules/windows/builtin/win_pass_the_hash.yml b/rules/windows/builtin/win_pass_the_hash.yml index 1fa07af1..c6aaae74 100644 --- a/rules/windows/builtin/win_pass_the_hash.yml +++ b/rules/windows/builtin/win_pass_the_hash.yml @@ -18,15 +18,15 @@ logsource: detection: selection: - EventID: 4624 - LogonType: '3' - LogonProcessName: 'NtLmSsp' - WorkstationName: '%Workstations%' - ComputerName: '%Workstations%' + LogonType: '3' + LogonProcessName: 'NtLmSsp' + WorkstationName: '%Workstations%' + ComputerName: '%Workstations%' - EventID: 4625 - LogonType: '3' - LogonProcessName: 'NtLmSsp' - WorkstationName: '%Workstations%' - ComputerName: '%Workstations%' + LogonType: '3' + LogonProcessName: 'NtLmSsp' + WorkstationName: '%Workstations%' + ComputerName: '%Workstations%' filter: AccountName: 'ANONYMOUS LOGON' condition: selection and not filter diff --git a/rules/windows/builtin/win_pass_the_hash_2.yml b/rules/windows/builtin/win_pass_the_hash_2.yml index 82f26131..722637eb 100644 --- a/rules/windows/builtin/win_pass_the_hash_2.yml +++ b/rules/windows/builtin/win_pass_the_hash_2.yml @@ -19,13 +19,13 @@ logsource: detection: selection: - EventID: 4624 - SubjectUserSid: 'S-1-0-0' - LogonType: '3' - LogonProcessName: 'NtLmSsp' - KeyLength: '0' + SubjectUserSid: 'S-1-0-0' + LogonType: '3' + LogonProcessName: 'NtLmSsp' + KeyLength: '0' - EventID: 4624 - LogonType: '9' - LogonProcessName: 'seclogo' + LogonType: '9' + LogonProcessName: 'seclogo' filter: AccountName: 'ANONYMOUS LOGON' condition: selection and not filter diff --git a/rules/windows/builtin/win_register_new_logon_process_by_rubeus.yml b/rules/windows/builtin/win_register_new_logon_process_by_rubeus.yml index c1d677ee..25e6180c 100644 --- a/rules/windows/builtin/win_register_new_logon_process_by_rubeus.yml +++ b/rules/windows/builtin/win_register_new_logon_process_by_rubeus.yml @@ -17,7 +17,7 @@ logsource: detection: selection: - EventID: 4611 - LogonProcessName: 'User32LogonProcesss' + LogonProcessName: 'User32LogonProcesss' condition: selection falsepositives: - Unkown diff --git a/rules/windows/builtin/win_user_couldnt_call_privileged_service_lsaregisterlogonprocess.yml b/rules/windows/builtin/win_user_couldnt_call_privileged_service_lsaregisterlogonprocess.yml index 59ee3b4b..3bea7e2a 100644 --- a/rules/windows/builtin/win_user_couldnt_call_privileged_service_lsaregisterlogonprocess.yml +++ b/rules/windows/builtin/win_user_couldnt_call_privileged_service_lsaregisterlogonprocess.yml @@ -17,8 +17,8 @@ logsource: detection: selection: - EventID: 4673 - Service: 'LsaRegisterLogonProcess()' - Keywords: '0x8010000000000000' #failure + Service: 'LsaRegisterLogonProcess()' + Keywords: '0x8010000000000000' #failure condition: selection falsepositives: - Unkown diff --git a/rules/windows/process_creation/win_copying_sensitive_files_with_credential_data.yml b/rules/windows/process_creation/win_copying_sensitive_files_with_credential_data.yml index 50f341af..eb7818e2 100644 --- a/rules/windows/process_creation/win_copying_sensitive_files_with_credential_data.yml +++ b/rules/windows/process_creation/win_copying_sensitive_files_with_credential_data.yml @@ -21,7 +21,7 @@ logsource: detection: selection: - Image|endswith: '\esentutl.exe' - CommandLine|contains: + CommandLine|contains: - 'vss' - ' /m ' - ' /y ' diff --git a/rules/windows/process_creation/win_new_service_creation.yml b/rules/windows/process_creation/win_new_service_creation.yml index e8a3c4bb..59ee6041 100644 --- a/rules/windows/process_creation/win_new_service_creation.yml +++ b/rules/windows/process_creation/win_new_service_creation.yml @@ -18,11 +18,11 @@ logsource: detection: selection: - Image|endswith: '\sc.exe' - CommandLine|contains|all: + CommandLine|contains|all: - 'create' - 'binpath' - Image|endswith: '\powershell.exe' - CommandLine|contains: 'new-service' + CommandLine|contains: 'new-service' condition: selection falsepositives: - Legitimate administrator or user creates a service for legitimate reason diff --git a/rules/windows/process_creation/win_powershell_downgrade_attack.yml b/rules/windows/process_creation/win_powershell_downgrade_attack.yml index 3d6c063f..12a8b950 100644 --- a/rules/windows/process_creation/win_powershell_downgrade_attack.yml +++ b/rules/windows/process_creation/win_powershell_downgrade_attack.yml @@ -2,7 +2,7 @@ title: PowerShell Downgrade Attack id: b3512211-c67e-4707-bedc-66efc7848863 related: - id: 6331d09b-4785-4c13-980f-f96661356249 - type: derived + type: derived status: experimental description: Detects PowerShell downgrade attack by comparing the host versions with the actually used engine version 2.0 references: diff --git a/rules/windows/sysmon/sysmon_disable_security_events_logging_adding_reg_key_minint.yml b/rules/windows/sysmon/sysmon_disable_security_events_logging_adding_reg_key_minint.yml index b363db33..bf53e1c8 100644 --- a/rules/windows/sysmon/sysmon_disable_security_events_logging_adding_reg_key_minint.yml +++ b/rules/windows/sysmon/sysmon_disable_security_events_logging_adding_reg_key_minint.yml @@ -17,11 +17,11 @@ logsource: detection: selection: - EventID: 12 # key create - # Sysmon gives us HKLM\SYSTEM\CurrentControlSet\.. if ControlSetXX is the selected one - TargetObject: 'HKLM\SYSTEM\CurrentControlSet\Control\MiniNt' - EventType: 'CreateKey' # we don't want deletekey + # Sysmon gives us HKLM\SYSTEM\CurrentControlSet\.. if ControlSetXX is the selected one + TargetObject: 'HKLM\SYSTEM\CurrentControlSet\Control\MiniNt' + EventType: 'CreateKey' # we don't want deletekey - EventID: 14 # key rename - NewName: 'HKLM\SYSTEM\CurrentControlSet\Control\MiniNt' + NewName: 'HKLM\SYSTEM\CurrentControlSet\Control\MiniNt' condition: selection fields: - EventID diff --git a/rules/windows/sysmon/sysmon_new_dll_added_to_appcertdlls_registry_key.yml b/rules/windows/sysmon/sysmon_new_dll_added_to_appcertdlls_registry_key.yml index b88b0a87..1ea9cafc 100644 --- a/rules/windows/sysmon/sysmon_new_dll_added_to_appcertdlls_registry_key.yml +++ b/rules/windows/sysmon/sysmon_new_dll_added_to_appcertdlls_registry_key.yml @@ -21,9 +21,9 @@ detection: - 12 # key create - 13 # value set # Sysmon gives us HKLM\SYSTEM\CurrentControlSet\.. if ControlSetXX is the selected one - TargetObject: 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDlls' + TargetObject: 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDlls' - EventID: 14 # key rename - NewName: 'HKLM\SYSTEM\CurentControlSet\Control\Session Manager\AppCertDlls' + NewName: 'HKLM\SYSTEM\CurentControlSet\Control\Session Manager\AppCertDlls' condition: selection fields: - EventID diff --git a/rules/windows/sysmon/sysmon_new_dll_added_to_appinit_dlls_registry_key.yml b/rules/windows/sysmon/sysmon_new_dll_added_to_appinit_dlls_registry_key.yml index f7cfcd8e..78e61989 100644 --- a/rules/windows/sysmon/sysmon_new_dll_added_to_appinit_dlls_registry_key.yml +++ b/rules/windows/sysmon/sysmon_new_dll_added_to_appinit_dlls_registry_key.yml @@ -19,13 +19,13 @@ detection: - EventID: - 12 # key create - 13 # value set - TargetObject: - - '*\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls' - - '*\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls' + TargetObject: + - '*\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls' + - '*\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls' - EventID: 14 # key rename - NewName: - - '*\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls' - - '*\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls' + NewName: + - '*\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls' + - '*\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls' condition: selection fields: - EventID From 002270537303e51b3ff1364b218abca10b97403f Mon Sep 17 00:00:00 2001 From: Florian Roth Date: Wed, 17 Jun 2020 16:09:33 +0200 Subject: [PATCH 91/94] fix: filter not functional since `UsrLogon.cmd` does appear only in `C:\Windows\system32\cmd.exe /c UsrLogon.cmd` command line --- .../sysmon/sysmon_logon_scripts_userinitmprlogonscript.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rules/windows/sysmon/sysmon_logon_scripts_userinitmprlogonscript.yml b/rules/windows/sysmon/sysmon_logon_scripts_userinitmprlogonscript.yml index 4efaaca3..255b18ac 100644 --- a/rules/windows/sysmon/sysmon_logon_scripts_userinitmprlogonscript.yml +++ b/rules/windows/sysmon/sysmon_logon_scripts_userinitmprlogonscript.yml @@ -25,9 +25,9 @@ detection: exec_exclusion1: Image: '*\explorer.exe' exec_exclusion2: - CommandLine: - - '*\netlogon.bat' - - '*\UsrLogon.cmd' + CommandLine|contains: + - 'netlogon.bat' + - 'UsrLogon.cmd' condition: exec_selection and not exec_exclusion1 and not exec_exclusion2 --- logsource: From 99bfa14ae0494c0f7fdfcad4cff2d154c58b5e30 Mon Sep 17 00:00:00 2001 From: ecco Date: Wed, 17 Jun 2020 12:49:27 -0400 Subject: [PATCH 92/94] add 1 more FP --- rules/windows/sysmon/sysmon_wmi_module_load.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/rules/windows/sysmon/sysmon_wmi_module_load.yml b/rules/windows/sysmon/sysmon_wmi_module_load.yml index 3b6561ec..bee87eee 100644 --- a/rules/windows/sysmon/sysmon_wmi_module_load.yml +++ b/rules/windows/sysmon/sysmon_wmi_module_load.yml @@ -37,6 +37,7 @@ detection: - '\SIHClient.exe' - '\msfeedssync.exe' - '\mmc.exe' + - '\MoUsoCoreWorker.exe' # in system32, seen on a win10 pro 2004 machine condition: selection and not filter fields: - ComputerName From b343df222577e3780048d42003f245a8cdf46948 Mon Sep 17 00:00:00 2001 From: Ivan Kirillov Date: Wed, 17 Jun 2020 11:31:40 -0600 Subject: [PATCH 93/94] Further subtechnique updates --- rules/windows/malware/win_mal_octopus_scanner.yml | 1 + .../process_creation/win_apt_lazarus_session_highjack.yml | 1 + .../windows/process_creation/win_commandline_path_traversal.yml | 1 + rules/windows/process_creation/win_hktl_createminidump.yml | 1 + rules/windows/process_creation/win_mal_adwind.yml | 1 + rules/windows/process_creation/win_susp_covenant.yml | 1 + rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml | 1 + rules/windows/sysmon/sysmon_hack_dumpert.yml | 1 + rules/windows/sysmon/sysmon_hack_wce.yml | 1 + .../sysmon/sysmon_logon_scripts_userinitmprlogonscript.yml | 1 + rules/windows/sysmon/sysmon_susp_fax_dll.yml | 2 ++ 11 files changed, 12 insertions(+) diff --git a/rules/windows/malware/win_mal_octopus_scanner.yml b/rules/windows/malware/win_mal_octopus_scanner.yml index 4e7a5888..0c710eae 100644 --- a/rules/windows/malware/win_mal_octopus_scanner.yml +++ b/rules/windows/malware/win_mal_octopus_scanner.yml @@ -6,6 +6,7 @@ references: - https://securitylab.github.com/research/octopus-scanner-malware-open-source-supply-chain tags: - attack.t1195 + - attack.t1195.001 author: NVISO date: 2020/06/09 logsource: diff --git a/rules/windows/process_creation/win_apt_lazarus_session_highjack.yml b/rules/windows/process_creation/win_apt_lazarus_session_highjack.yml index 7f074637..299c767e 100644 --- a/rules/windows/process_creation/win_apt_lazarus_session_highjack.yml +++ b/rules/windows/process_creation/win_apt_lazarus_session_highjack.yml @@ -7,6 +7,7 @@ references: tags: - attack.defense_evasion - attack.t1036 + - attack.t1036.005 author: Trent Liffick (@tliffick) date: 2020/06/03 logsource: diff --git a/rules/windows/process_creation/win_commandline_path_traversal.yml b/rules/windows/process_creation/win_commandline_path_traversal.yml index 772a615c..c1594ad9 100644 --- a/rules/windows/process_creation/win_commandline_path_traversal.yml +++ b/rules/windows/process_creation/win_commandline_path_traversal.yml @@ -9,6 +9,7 @@ references: - https://twitter.com/Oddvarmoe/status/1270633613449723905 tags: - attack.t1059 + - attack.t1059.003 - attack.execution logsource: category: process_creation diff --git a/rules/windows/process_creation/win_hktl_createminidump.yml b/rules/windows/process_creation/win_hktl_createminidump.yml index 6129c97a..aaecdcbd 100644 --- a/rules/windows/process_creation/win_hktl_createminidump.yml +++ b/rules/windows/process_creation/win_hktl_createminidump.yml @@ -9,6 +9,7 @@ date: 2019/12/22 tags: - attack.credential_access - attack.t1003 + - attack.t1003.001 falsepositives: - Unknown level: high diff --git a/rules/windows/process_creation/win_mal_adwind.yml b/rules/windows/process_creation/win_mal_adwind.yml index 68cea191..d7f30acc 100644 --- a/rules/windows/process_creation/win_mal_adwind.yml +++ b/rules/windows/process_creation/win_mal_adwind.yml @@ -12,6 +12,7 @@ modified: 2018/12/11 tags: - attack.execution - attack.t1064 + - attack.t1059.005 detection: condition: selection level: high diff --git a/rules/windows/process_creation/win_susp_covenant.yml b/rules/windows/process_creation/win_susp_covenant.yml index 8f0f92a6..b73909f7 100644 --- a/rules/windows/process_creation/win_susp_covenant.yml +++ b/rules/windows/process_creation/win_susp_covenant.yml @@ -9,6 +9,7 @@ date: 2020/06/04 tags: - attack.execution - attack.t1086 + - attack.t1059.001 logsource: category: process_creation product: windows diff --git a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml index 3bb4c1aa..f5b6e57d 100644 --- a/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml +++ b/rules/windows/sysmon/sysmon_apt_muddywater_dnstunnel.yml @@ -10,6 +10,7 @@ references: tags: - attack.command_and_control - attack.t1071 + - attack.t1071.004 logsource: category: process_creation product: windows diff --git a/rules/windows/sysmon/sysmon_hack_dumpert.yml b/rules/windows/sysmon/sysmon_hack_dumpert.yml index 329cc720..443c8bf3 100644 --- a/rules/windows/sysmon/sysmon_hack_dumpert.yml +++ b/rules/windows/sysmon/sysmon_hack_dumpert.yml @@ -10,6 +10,7 @@ date: 2020/02/04 tags: - attack.credential_access - attack.t1003 + - attack.t1003.001 logsource: product: windows service: sysmon diff --git a/rules/windows/sysmon/sysmon_hack_wce.yml b/rules/windows/sysmon/sysmon_hack_wce.yml index 6432ea86..43fb3a47 100644 --- a/rules/windows/sysmon/sysmon_hack_wce.yml +++ b/rules/windows/sysmon/sysmon_hack_wce.yml @@ -9,6 +9,7 @@ date: 2019/12/31 tags: - attack.credential_access - attack.t1003 + - attack.t1558 - attack.s0005 falsepositives: - 'Another service that uses a single -s command line switch' diff --git a/rules/windows/sysmon/sysmon_logon_scripts_userinitmprlogonscript.yml b/rules/windows/sysmon/sysmon_logon_scripts_userinitmprlogonscript.yml index 4efaaca3..1480db08 100644 --- a/rules/windows/sysmon/sysmon_logon_scripts_userinitmprlogonscript.yml +++ b/rules/windows/sysmon/sysmon_logon_scripts_userinitmprlogonscript.yml @@ -7,6 +7,7 @@ references: - https://attack.mitre.org/techniques/T1037/ tags: - attack.t1037 + - attack.t1037.001 - attack.persistence - attack.lateral_movement author: Tom Ueltschi (@c_APT_ure) diff --git a/rules/windows/sysmon/sysmon_susp_fax_dll.yml b/rules/windows/sysmon/sysmon_susp_fax_dll.yml index 58fe49ee..14b91c1a 100644 --- a/rules/windows/sysmon/sysmon_susp_fax_dll.yml +++ b/rules/windows/sysmon/sysmon_susp_fax_dll.yml @@ -12,6 +12,8 @@ tags: - attack.t1073 - attack.t1038 - attack.t1112 + - attack.t1574.001 + - attack.t1574.002 logsource: product: windows service: sysmon From 69760f6446a612e359f8f3d52a1a3d797acc7e44 Mon Sep 17 00:00:00 2001 From: Ivan Kirillov Date: Wed, 17 Jun 2020 11:51:48 -0600 Subject: [PATCH 94/94] Added subtechniques to MITRE_TECHNIQUES --- tests/test_rules.py | 481 ++++++++++++++++++++------------------------ 1 file changed, 213 insertions(+), 268 deletions(-) diff --git a/tests/test_rules.py b/tests/test_rules.py index 752611ed..9b2e40d8 100755 --- a/tests/test_rules.py +++ b/tests/test_rules.py @@ -15,274 +15,219 @@ from colorama import Fore class TestRules(unittest.TestCase): MITRE_TECHNIQUES = [ - "t1001", - "t1002", - "t1003", - "t1004", - "t1005", - "t1006", - "t1007", - "t1008", - "t1009", - "t1010", - "t1011", - "t1012", - "t1013", - "t1014", - "t1015", - "t1016", - "t1017", - "t1018", - "t1019", - "t1020", - "t1021", - "t1022", - "t1023", - "t1024", - "t1025", - "t1026", - "t1027", - "t1028", - "t1029", - "t1030", - "t1031", - "t1032", - "t1033", - "t1034", - "t1035", - "t1036", - "t1037", - "t1038", - "t1039", - "t1040", - "t1041", - "t1042", - "t1043", - "t1044", - "t1045", - "t1046", - "t1047", - "t1048", - "t1049", - "t1050", - "t1051", - "t1052", - "t1053", - "t1054", - "t1055", - "t1056", - "t1057", - "t1058", - "t1059", - "t1060", - "t1061", - "t1062", - "t1063", - "t1064", - "t1065", - "t1066", - "t1067", - "t1068", - "t1069", - "t1070", - "t1071", - "t1072", - "t1073", - "t1074", - "t1075", - "t1076", - "t1077", - "t1078", - "t1079", - "t1080", - "t1081", - "t1082", - "t1083", - "t1084", - "t1085", - "t1086", - "t1087", - "t1088", - "t1089", - "t1090", - "t1091", - "t1092", - "t1093", - "t1094", - "t1095", - "t1096", - "t1097", - "t1098", - "t1099", - "t1100", - "t1101", - "t1102", - "t1103", - "t1104", - "t1105", - "t1106", - "t1107", - "t1108", - "t1109", - "t1110", - "t1111", - "t1112", - "t1113", - "t1114", - "t1115", - "t1116", - "t1117", - "t1118", - "t1119", - "t1120", - "t1121", - "t1122", - "t1123", - "t1124", - "t1125", - "t1126", - "t1127", - "t1128", - "t1129", - "t1130", - "t1131", - "t1132", - "t1133", - "t1134", - "t1135", - "t1136", - "t1137", - "t1138", - "t1139", - "t1140", - "t1141", - "t1142", - "t1143", - "t1144", - "t1145", - "t1146", - "t1147", - "t1148", - "t1149", - "t1150", - "t1151", - "t1152", - "t1153", - "t1154", - "t1155", - "t1156", - "t1157", - "t1158", - "t1159", - "t1160", - "t1161", - "t1162", - "t1163", - "t1164", - "t1165", - "t1166", - "t1167", - "t1168", - "t1169", - "t1170", - "t1171", - "t1172", - "t1173", - "t1174", - "t1175", - "t1176", - "t1177", - "t1178", - "t1179", - "t1180", - "t1181", - "t1182", - "t1183", - "t1184", - "t1185", - "t1186", - "t1187", - "t1188", - "t1189", - "t1190", - "t1191", - "t1192", - "t1193", - "t1194", - "t1195", - "t1196", - "t1197", - "t1198", - "t1199", - "t1200", - "t1201", - "t1202", - "t1203", - "t1204", - "t1205", - "t1206", - "t1207", - "t1208", - "t1209", - "t1210", - "t1211", - "t1212", - "t1213", - "t1214", - "t1215", - "t1216", - "t1217", - "t1218", - "t1219", - "t1220", - "t1221", - "t1222", - "t1223", - "t1377", - "t1480", - "t1482", - "t1482", - "t1483", - "t1484", - "t1485", - "t1486", - "t1487", - "t1488", - "t1489", - "t1490", - "t1491", - "t1492", - "t1493", - "t1494", - "t1495", - "t1496", - "t1497", - "t1498", - "t1499", - "t1500", - "t1501", - "t1502", - "t1503", - "t1504", - "t1505", - "t1506", - "t1514", - "t1518", - "t1519", - "t1522", - "t1525", - "t1526", - "t1527", - "t1528", - "t1529", - "t1530", - "t1531", - "t1534", - "t1535", - "t1536", - "t1537", - "t1538", - "t1539", + "t1002", + "t1003", + "t1003.001", + "t1003.002", + "t1003.003", + "t1003.004", + "t1003.005", + "t1003.006", + "t1004", + "t1005", + "t1006", + "t1007", + "t1009", + "t1011", + "t1012", + "t1015", + "t1016", + "t1018", + "t1020", + "t1021", + "t1021.001", + "t1021.002", + "t1021.003", + "t1021.006", + "t1023", + "t1027", + "t1028", + "t1031", + "t1033", + "t1035", + "t1036", + "t1036.005", + "t1037", + "t1037.001", + "t1038", + "t1040", + "t1041", + "t1042", + "t1043", + "t1046", + "t1047", + "t1048", + "t1049", + "t1050", + "t1053", + "t1053.002", + "t1053.005", + "t1054", + "t1055", + "t1056", + "t1057", + "t1058", + "t1059", + "t1059.001", + "t1059.003", + "t1059.004", + "t1059.005", + "t1059.006", + "t1060", + "t1064", + "t1066", + "t1067", + "t1068", + "t1069", + "t1070", + "t1071", + "t1071.004", + "t1073", + "t1074", + "t1075", + "t1076", + "t1077", + "t1078", + "t1081", + "t1082", + "t1083", + "t1084", + "t1085", + "t1086", + "t1087", + "t1088", + "t1089", + "t1090", + "t1091", + "t1096", + "t1098", + "t1099", + "t1100", + "t1102", + "t1103", + "t1105", + "t1107", + "t1110", + "t1112", + "t1114", + "t1117", + "t1118", + "t1121", + "t1122", + "t1123", + "t1124", + "t1127", + "t1128", + "t1130", + "t1133", + "t1134", + "t1134.005", + "t1135", + "t1136", + "t1137", + "t1138", + "t1139", + "t1140", + "t1145", + "t1146", + "t1156", + "t1158", + "t1168", + "t1169", + "t1170", + "t1171", + "t1175", + "t1177", + "t1178", + "t1182", + "t1183", + "t1190", + "t1191", + "t1193", + "t1195", + "t1195.001", + "t1196", + "t1197", + "t1200", + "t1201", + "t1202", + "t1203", + "t1204", + "t1207", + "t1208", + "t1210", + "t1211", + "t1212", + "t1218", + "t1218.001", + "t1218.005", + "t1218.010", + "t1218.011", + "t1219", + "t1220", + "t1222", + "t1223", + "t1482", + "t1485", + "t1487", + "t1488", + "t1489", + "t1490", + "t1492", + "t1493", + "t1495", + "t1499", + "t1500", + "t1501", + "t1505", + "t1505.003", + "t1537", + "t1542.003", + "t1543.002", + "t1543.003", + "t1546.001", + "t1546.003", + "t1546.004", + "t1546.007", + "t1546.008", + "t1546.009", + "t1546.010", + "t1546.011", + "t1546.012", + "t1546.015", + "t1547.001", + "t1547.004", + "t1547.008", + "t1547.009", + "t1548.002", + "t1550.002", + "t1551", + "t1551.003", + "t1551.004", + "t1551.006", + "t1552.001", + "t1552.003", + "t1552.004", + "t1553.004", + "t1557.001", + "t1558", + "t1558.003", + "t1559.001", + "t1560", + "t1561.001", + "t1561.002", + "t1562.001", + "t1562.006", + "t1564.001", + "t1564.004", + "t1565.001", + "t1565.002", + "t1566.001", + "t1569.002", + "t1571", + "t1574.001", + "t1574.002", + "t1574.011", ] MITRE_TECHNIQUE_NAMES = ["process_injection", "signed_binary_proxy_execution", "process_injection"] # incomplete list MITRE_TACTICS = ["initial_access", "execution", "persistence", "privilege_escalation", "defense_evasion", "credential_access", "discovery", "lateral_movement", "collection", "exfiltration", "command_and_control", "impact", "launch"]