def __load_alert_ids(self): """ Parses each rule file to extract the relevant Identifiers, actions, headers and pre-build a matching string. :return rules: Dictionary containing parsed Snort rules from configured rules files. """ rules = {} for i in self._config.rule_list: # uses IDS tools library to extract rules rule_file = rule.parse_file(i) for x in rule_file: if x.enabled: rules[x.sid] = {} rules[x.sid]['sid'] = x.sid rules[x.sid]['gid'] = x.gid rules[x.sid]['rev'] = x.rev rules[x.sid]['logmatch'] = "{0}:{1}:{2}".format( str(x.gid), str(x.sid), str(x.rev)) rules[x.sid]['action'] = x.action rules[x.sid]['header'] = x.header self._logger.info( "Extracted {0} rules from the Snort configuration.".format( str(len(rules)))) return rules
def test_signature_content(base_path): errors = [] # Parse signature using idstools rule_files = glob(os.path.join(base_path, '*/*.rules')) rules = {} rule_ids = {} # Parse the rules: for rule_file in rule_files: try: parsed_rulefile = rule.parse_file(rule_file) if not parsed_rulefile: errors.append('Rule file %s failed to parse/is blank' % rule_file) continue rules[rule_file] = parsed_rulefile except: errors.append('Parsing error on %s' % rule_file) for rname, ruleset in rules.items(): for r in ruleset: # check if msg name contains MONA if not r.get('msg', '').startswith('MONA - '): errors.append('on %s msg doesn\'t start with MONA - ' % rname) if 'sid' not in r: errors.append('No SID defined on %s' % rname) r['sid'] = 0 if not r['sid'] >= 8000000 and r['sid'] < 9000000: errors.append('Invalid signature id on %s' % rname) if r['sid'] in rule_ids: errors.append('Duplicate SID: %s on %s and %s' % (r['sid'], rule_ids[r['sid']], rname)) else: rule_ids[r['sid']] = rname return errors
def extract_groups_from(input_file, use_supercats, limit): rules = rule.parse_file(input_file) groups = GroupClassifier(use_supercats) count = 0 for snort_rule in rules: if count > limit: break header = snort_rule.header.split(" ") if "pcre" not in snort_rule: # Don't care about the non regex rules. continue # This function reformats the PCRE pcre = is_valid_pcre(snort_rule.pcre) if not pcre: global not_valid not_valid += 1 # Not a supported PCRE, don't translate continue if header[1] in SUPPORTED_PROTOCOLS: proto = header[1] else: print("Type " + header[1] + " not recognized") proto = "all" src_ips = header[2] src_ips_type = None if src_ips in SUPPORTED_IP_CLASSES: src_ips_type = src_ips else: print("Unrecognized src IPs type: " + src_ips) src_ips_type = "any" src_ports = header[3] dst_ports = header[6] if ":" in src_ports or ":" in dst_ports or "," in src_ports or "," in dst_ports or "[" in src_ports or "[" in dst_ports: continue # TODO --- Do something about ports, which generally # have a wider range... groups.add(proto, src_ips_type, src_ports, dst_ports, format_pcre(pcre)) count += 1 print("Number of rules omitted due to unsupported features is" + str(not_valid)) return groups
def __load_alert_ids(self): """ Parses each rule file to extract the relevant Identifiers, actions, headers and pre-build a matching string. :return rules: Dictionary containing parsed Snort rules from configured rules files. """ rules = {} for i in self._config.rule_list: # uses IDS tools library to extract rules rule_file = rule.parse_file(i) for x in rule_file: if x.enabled: rules[x.sid] = {} rules[x.sid]['sid'] = x.sid rules[x.sid]['gid'] = x.gid rules[x.sid]['rev'] = x.rev rules[x.sid]['logmatch'] = "{0}:{1}:{2}".format(str(x.gid), str(x.sid), str(x.rev)) rules[x.sid]['action'] = x.action rules[x.sid]['header'] = x.header self._logger.info("Extracted {0} rules from the Snort configuration.".format(str(len(rules)))) return rules
#! /usr/bin/env python # # Rule File Parsing Example import sys from idstools import rule # For each rule in a rule file, print: # [GENERATOR_ID:SIGNATURE_ID:REVISION] RULE_MSG for rule in rule.parse_file(sys.argv[1]): print("[%d:%d:%d] %s" % ( rule.gid, rule.sid, rule.rev, rule.msg))
#! /usr/bin/env python # # Rule File Parsing Example import sys from idstools import rule # For each rule in a rule file, print: # [GENERATOR_ID:SIGNATURE_ID:REVISION] RULE_MSG for rule in rule.parse_file(sys.argv[1]): print("[%d:%d:%d] %s" % (rule.gid, rule.sid, rule.rev, rule.msg))
def main(): module = AnsibleModule(argument_spec=dict( rule=dict(required=True, default=None), state=dict(choices=['present', 'absent'], required=True), rules_file=dict(required=False, default='/etc/snort/rules/ansible_managed.rules'), ), supports_check_mode=True) matched_rules = [ snort_rule for snort_rule in rule.parse_file(module.params['rules_file']) if to_text(snort_rule) == to_text(rule.parse(module.params['rule'])) ] rule_found = True if matched_rules else False if module.params['state'] == 'present' and rule_found: module.exit_json( msg="Rule '{}' already present in rules_file {}".format( module.params['rule'], module.params['rules_file']), changed=False) elif module.params['state'] == 'present' and not rule_found: if module.check_mode: module.exit_json( msg="Rule '{}' would be added to rules_file {}".format( module.params['rule'], module.params['rules_file']), changed=True) with open(module.params['rules_file'], 'a') as rules_file: rules_file.write(to_text(rule.parse(module.params['rule']))) module.exit_json(msg="Rule '{}' added to rules_file {}".format( module.params['rule'], module.params['rules_file']), changed=True) if module.params['state'] == 'absent' and not rule_found: module.exit_json( msg="Rule '{}' does not exist in rules_file {}".format( module.params['rule'], module.params['rules_file']), changed=False) elif module.params['state'] == 'absent' and rule_found: orig_file_contents = [] with open(module.params['rules_file'], 'r') as rules_file: orig_file_contents = rules_file.readlines() new_file_contents = [ line for line in orig_file_contents if rule.parse(module.params['rule']) != rule.parse(line) ] if module.check_mode: if len(orig_file_contents) != len(new_file_contents): module.exit_json( msg="Rule '{}' would have been removed from rules_file {}". format(module.params['rule'], module.params['rules_file']), changed=True) with open(module.params['rules_file'], 'w') as rules_file: for line in new_file_contents: rules_file.write(line) module.exit_json( msg="Rule '{}' has been removed from rules_file {}".format( module.params['rule'], module.params['rules_file']), changed=True)
for content in contents.split("|"): if len(content) == 0: continue m = re.match(r'(\d\d ?)+', content) if m: out_content.append({"t": "bytes", "c": m.group(0)}) else: m = re.match(r'\d+', content) if m: out_content.append({"t": "decimal", "c": m.group(0)}) else: out_content.append({"t": "string", "c": content}) return out_content def parse_addresses(r): m = re.match(r'\S+ \S+ (\S+) (\S+) (->|<-) (\S+) (\S+)', r.raw) if not m: return {} else: return { "local_network": m.group(1), "local_port": m.group(2), "remote_network": m.group(4), "remote_port": m.group(5) } rules = [] for r in rule.parse_file(rules_file)[:10]: out_rule = {"msg": r.msg, "action": r.action, "content": parse_content(r)} out_rule.update(parse_addresses(r)) rules.append(out_rule) with open(output_file, "w") as f: json.dump({"rules": rules}, f)
# Author: Naveen Mukundan Ravindran import sys # Your system should have installed idstools from Python 3 packages. Check the description for how to install it. from idstools import rule # Download the latest snort rules from the website provided in the description filename = "snort3-community.rules" for rule in rule.parse_file(filename): # Print the Action of the rule print("Action: %s" % rule.action) # Print the Message Contents of the rule print("Message: %s" % rule.msg) # Print the Generator ID of the rule print("Generator id: %d" % rule.gid) # Print the Snort Rule ID of the rule print("Rule id: %d" % rule.sid) # Print the Revision Integer of the rule print("Revision Integer: %d" % rule.rev) # Print the Class type of the rule print("Class Type: %s" % rule.classtype) # Print the Priority Integer of the rule
def main(): module = AnsibleModule(argument_spec=dict( rule=dict(required=True, default=None), state=dict(choices=['present', 'absent'], required=True), rules_file=dict(required=False, default='/etc/snort/rules/ansible_managed.rules'), ), supports_check_mode=True) if not HAS_IDSTOOLS: module.fail_json( msg= "Python module idstools not found on host, but is required for snort_rule Ansible module" ) try: matched_rules = [ snort_rule for snort_rule in rule.parse_file(module.params['rules_file']) if to_text(snort_rule) == to_text(rule.parse(module.params['rule'])) ] except IOError: module.fail_json( msg= "rule file {} not found or permission was denied attempting access it" .format(module.params['rules_file'])) rule_found = True if matched_rules else False sigmap = maps.SignatureMap() try: sigmap.load_generator_map(open(GENMAP_FILE, 'r')) except IOError: module.fail_json( msg= "generator file {} not found or permission was denied attempting to access it" .format(GENMAP_FILE)) try: sigmap.load_signature_map(open(SIGMAP_FILE, 'r')) except IOError: module.fail_json( msg= "signature file {} not found or permission was denied attempting to access it" .format(SIGMAP_FILE)) if module.params['state'] == 'present' and rule_found: module.exit_json( msg="Rule '{}' already present in rules_file {}".format( module.params['rule'], module.params['rules_file']), changed=False) elif module.params['state'] == 'present' and not rule_found: if module.check_mode: module.exit_json( msg="Rule '{}' would be added to rules_file {}".format( module.params['rule'], module.params['rules_file']), changed=True) new_snort_rule = rule.parse(module.params['rule']) with open(module.params['rules_file'], 'a') as rules_file: rules_file.write(to_text("\n{}".format(new_snort_rule))) with open(SIGMAP_FILE, 'a') as sigmap_file: if "ref" in new_snort_rule and len(new_snort_rule["ref"]) > 0: sigmap_file.write( to_text("\n{} || {} || {}".format( new_snort_rule['sid'], new_snort_rule['msg'], " || ".join(new_snort_rule['ref'])))) else: sigmap_file.write( to_text("\n{} || {}".format(new_snort_rule['sid'], new_snort_rule['msg']))) module.exit_json(msg="Rule '{}' added to rules_file {}".format( module.params['rule'], module.params['rules_file']), changed=True) if module.params['state'] == 'absent' and not rule_found: module.exit_json( msg="Rule '{}' does not exist in rules_file {}".format( module.params['rule'], module.params['rules_file']), changed=False) elif module.params['state'] == 'absent' and rule_found: new_snort_rule = rule.parse(module.params['rule']) changed = False orig_rulefile_contents = [] orig_sigmapfile_contents = [] new_rulefile_contents = [] new_sigmapfile_contents = [] with open(module.params['rules_file'], 'r') as rules_file: orig_rulefile_contents = rules_file.readlines() with open(SIGMAP_FILE, 'r') as sigmap_file: orig_sigmapfile_contents = sigmap_file.readlines() new_rulefile_contents = [ line for line in orig_rulefile_contents if new_snort_rule != rule.parse(line) ] if "ref" in new_snort_rule and len(new_snort_rule["ref"]) > 0: new_sigmapfile_contents = [ line for line in orig_sigmapfile_contents if "{} || {} || {}".format( new_snort_rule['sid'], new_snort_rule['msg'], ' || '.join( new_snort_rule['ref'])) != line.strip() ] else: new_sigmapfile_contents = [ line for line in orig_sigmapfile_contents if "{} || {}".format(new_snort_rule['sid'], new_snort_rule['msg']) != line.strip() ] if module.check_mode: if len(orig_rulefile_contents) != len(new_rulefile_contents): module.exit_json( msg="Rule '{}' would have been removed from rules_file {}". format(module.params['rule'], module.params['rules_file']), changed=True) if len(orig_rulefile_contents) != len(new_rulefile_contents): changed = True with open(module.params['rules_file'], 'w') as rules_file: for line in new_rulefile_contents: rules_file.write(line) if new_sigmapfile_contents and (len(orig_sigmapfile_contents) != len(new_sigmapfile_contents)): changed = True with open(SIGMAP_FILE, 'w') as sigmap_file: for line in new_sigmapfile_contents: sigmap_file.write(line) module.exit_json( msg="Rule '{}' has been removed from rules_file {}".format( module.params['rule'], module.params['rules_file']), changed=changed)